在keil中使用printf()函数的要点
在keil中printf默认是向串口中发送数据的,所以,如果应用该函数,必须先初始化串口,否则可能引起死机的情况,并且在printf之前应该先将TI置位,摘抄原因如下:
1、printf函数是调用putchar函数输入的,而putchar应该是先判断ti是否为1,不为1则等待为1。如果为1则清0,然后送出一个字符。因此你如果直接使用printf函数,你的程序就会在putchar函数中等待ti为1。这时你的程序就相当于直接死掉了。你可以通过改写putchar函数实现自己的目的。TI相当于是初始化~不给赋初值就不干活
2、Keil的串口处理比较巧妙的,我的分析如下:
putchar.c里面,是先检测TI再发送。这样做的目的是把尽可能多的时间留给2次串口操作之间的程序,而不是把等待字节发送的时间白白空等待浪费掉。所以,在系统初始化的时候,一定要令TI=1; 就可以顺畅的使用printf函数了。搂主sbuf=" "的办法,其实就是令TI=1. 另外要特别注意,printf函数执行完毕后,最后一个字节并未发送完毕,例如在485通讯中,此时如果切换为收模式,会丢失最后一字节.
3、一般串口发送都是等TI(字节发送完标志)为1就马上发送下一字节,由于不管是中断还是查询TI标志的方法,都会检测TI,因此首次发送必须置位TI标志,使串口开始发送你的“在程序的初始化部分往串口数据寄存器SBUF里放一个字符来起用终端显示;”方法最终作用也就是把TI置1,改成TI=1;来启动发送也是一样的(当然,不会发出那个' '字符了)。
4、<stdio.h>中定义,调用底层的putchar()来实现.底层发送数据到串口时,先查TI=1是否成立,死等直到TI=1时将新数据写入SBUF,函数返回,所以要先将TI置1,启动第一次传输操作.可查看反汇编相关代码理解其工作机理!
5、自己理解:在多机通讯中,应该也要形成像putchar()函数的机理,要有串口中断服务程序,并且是在该程序中判断TI,根据TI是不是该发送下一组数据~同样对于接收的一方..
//===========================
#include <reg51.h>
#include <stdio.h>
//-------------------------------
int main()
{
Uart_init(); //初始化串口,这里就不写具体代码了。
TI = ; //keil 调用stdio.h中printf函数前要置位。
)
{
printf("Hello world!\n");
delay_ms(); //延时程序,这里也不写具体代码了。
}
;
}
printf
http://www.keil.com/support/man/docs/c51/c51_printf.htm
Home »Library Reference »Reference » printf
| Summary |
#include <stdio.h> int printf ( const char *fmtstr /* format string */ <[>, arguments ... <]>); /* additional arguments */ |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description |
The printf function formats a series of strings and numeric values and builds a string to write to the output stream using theputchar function. The fmtstrargument is a format string that may be composed of characters, escape sequences, and format specifications. Ordinary characters and escape sequences are copied to the stream in the order in which they are interpreted. Format specifications always begin with a percent sign ('%') and require that additionalarguments are included in the printf function call. The format string is read from left to right. The first format specification encountered references the firstargument after fmtstr and converts and outputs it using the format specification. The second format specification accesses the secondargument after fmtstr, and so on. If there are more arguments than format specifications, extra arguments are ignored. Results are unpredictable if there are not enough arguments for the format specifications or if the argument types do not match those specified byfmtstr. Format specifications have the following general format: % <[>flags<]> <[>width<]> <[>.precision<]> <[>{b|B|l|L}<]> type
Each field in the format specification may be a single character or a number which specifies a particular format option. The type field is a single character that specifies whether the argument is interpreted as a character, string, number, or pointer, as shown in the following table.
Characters following a percent sign that are not recognized as a format specification are treated as ordinary characters. For example, "%%" writes a single percent sign to the output stream. The flags field is a single character used to justify the output and to print +/- signs and blanks, decimal points, and octal and hexadecimal prefixes, as shown in the following table.
The width field is a non-negative number that specifies the minimum number of characters printed. If the number of characters in the output value is less than width, blanks are added on the left (by default) or right (when the - flag is specified) to pad to the minimum width. If width is prefixed with a '0', zeros are padded instead of blanks. The width field never truncates the output. If the length of the output value exceeds the specified width, all characters are output. The width field may be an asterisk ('*'), in which case an int argument from the argument list provides the width value. Specifying a 'b' in front of the asterisk specifies that the argument is an unsigned char. The precision field is a non-negative number that specifies the number of characters to print, the number of significant digits, or the number of decimal places. Theprecision field can cause truncation or rounding of the output value in the case of a floating-point number as specified in the following table.
The precision field may be an asterisk ('*'), in which case an int argument from the argument list provides the value. Specifying a 'b' in front of the asterisk specifies that the argument is an unsigned char.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Return Value |
The printf function returns the number of characters actually written to the output stream. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| See Also |
gets,printf517,puts,scanf,scanf517,sprintf,sprintf517,sscanf,sscanf517,vprintf,vsprintf |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Example |
#include <stdio.h>
void tst_printf (void) {
char a = 1;
int b = 12365;
long c = 0x7FFFFFFF;
unsigned char x = 'A';
unsigned int y = 54321;
unsigned long z = 0x4A6F6E00;
float f = 10.0;
float g = 22.95;
char buf [] = "Test String";
char *p = buf;
printf ("char %bd int %d long %ld\n",a,b,c);
printf ("Uchar %bu Uint %u Ulong %lu\n",x,y,z);
printf ("xchar %bx xint %x xlong %lx\n",x,y,z);
printf ("String %s is at address %p\n",buf,p);
printf ("%f != %g\n", f, g);
printf ("%*f != %*g\n", (int)8, f, (int)8, g);
}
|
--------------------------------
C51: PRINTF GIVES WRONG VALUES
Information in this article applies to:
- C51 All Versions
QUESTION
In C51, I am using printf and sprintf with many arguments and it is printing out wrong values. What is the reason for this behavior?
ANSWER
There are any number of reasons why printf can output incorrect values.
Probably the most common reason is that the format specifier and the argument type do not match. To solve this kind of problem, explicitly type cast each argument to the desired type. Be sure that you accurately specify the correct format specifier for that type.
Another reason may be that the number of bytes you may pass to functions with variable-length argument lists is fixed (since arguments are not passed on the stack). In small and compact memory model, printf and sprintf only reserve 15 bytes for the argument list. In the large memory model 40 bytes are reserved. For example, 15 bytes allow you to pass up to five generic (3-byte) pointers, or one generic pointer and three long arguments. This parameter limitation is a compromise to the limited memory available in 8051 devices.
Eight arguments will not fit in the space reserved for small or compact memory models. So, instead of one sprintf call with many arguments you must perform two or three calls and distribute the arguments among the sprintf calls. For example:
The following code exceeds the parameter space limits since seven generic pointers (21 bytes) are passed to sprintf.
char str[] = "Any Text"; sprintf (buff_out, "%s %s %s %s %s", str, str, str, str, str);
The above example may be rewritten as follows:
char str[] = "Any Text"; int len; len = sprintf (buff_out, "%s %s %s ", str, str, str); sprintf (buff_out + len, "%s %s", str, str);
MORE INFORMATION
- Refer to printf in the Cx51 User's Guide.
在keil中使用printf()函数的要点的更多相关文章
- C 中 关于printf 函数中度剖析
题外话 这篇博文主要围绕printf函数分析的,主要讲解printf 使用C的可变参数机制, printf是否可重入(是否线程安全), printf函数的源码实现. 正文 1.C中可变参数机制 我们 ...
- MFC 中的 “printf” 函数
怀念C语言的我,MFC没法使用的C语言printf函数,于是: int MFCprintf(const char* m_data, ...){ CString str; char printf_buf ...
- C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .
我们在C语言编程中会遇到一些参数个数可变的函数,一般人对它的实现不理解.例如Printf(): Printf()函数是C语言中非常常用的一个典型的变参数函数,它 的原型为: int printf( c ...
- trueStudio中使用printf函数
1.通过printf输出浮点数需要如下设置: 在工程属性下找到C/C++ build->Settings->Tool Settings->C Linker->Miscellan ...
- STM32 KEIL 下的 printf 函数
1 //加入以下代码,支持printf函数,而不需要选择use MicroLIB 2 #if 1 3 #pragma import(__use_no_semihosting) 4 //标准库需要的支持 ...
- 关于在MDK中使用 printf 函数
microlib 提供了一个有限的 stdio 子系统,它仅支持未缓冲的 stdin.stdout 和 stderr. 这样,即可使用 printf() 来显示应用程序中的诊断消息. 要使用高级 I/ ...
- STM32中如何对printf函数重定向
通过USART1向计算机的串口调试助手打印数据,或者接收计算机串口调试助手的数据,接下来我们现STM32工程上的printf()函数,方便用于程序开发中调试信息的打印. 方法一:使用MicroLIB库 ...
- 如何在单片机上使用printf函数(printf)(avr)(stm)(lpc)(单片机)(转)
摘要: 当我们在调试代码时,通常需要将程序中的某个变量打印至PC机上,来判断我们的程序是否按预期的运行,printf函数很好的做到了这一点,它能直接以字符的方式输出变量名和变量的值,printf ...
- STM32 printf()函数和scanf()函数重定向到串口
STM32 printf()函数和scanf()函数重定向到串口 printf()函数和scanf()函数重定向 在学习STM32的时候,常常需要用串口来测试代码的正确与否,这时候就要要用到print ...
随机推荐
- SCGHR 分析思路
-- 分析某个模块业务 a:添加表,登记表,历史表,信息表 --- (把表名搞清楚,再看具体的字段) 先搞清楚大概的数据流向,在着手具体的数据,大处布局,小处着手 b:表中的字段,以及各表直接传递什么 ...
- php中使用伪静态
上次简单的说了下php中正则表达式的使用,这一次正则表达式可以派上用场了,学习伪静态需要能够很好的使用正则表达式,那么伪静态和真静态的区别是什么呢,我觉得应该是伪静态可以节约磁盘空间.利于SEO.访问 ...
- 左移运算符<<
在许多计算机编程语言(例如:C语言.C++语言.Java语言.JavaScript语言,Pascal语言等)中,“<<”代表左移运算符(就相当于'shl').该运算符为双目运算符,结合方向 ...
- Tomcat的错误 之 java.lang.IllegalArgumentException: Document base * does not exist
Tomcat的异常 之 java.lang.IllegalArgumentException: Document base 有些刚开始使用的Tomcat的朋友会出现的问题,明明已经将某个web应用从t ...
- C++中的构造函数和析构函数
构造函数: 在类实例化对象时自动执行,对类中的数据进行初始化.构造函数可以从载,可以有多个,但是只能有一个缺省构造函数. 析构函数: 在撤销对象占用的内存之前,进行一些操作的函数.析构函数不能被重载, ...
- SharedPreferences的工具类,使用起来方便、快捷
SharedPreferences的工具类,使用起来方便.快捷:上代码:import android.content.Context;import android.content.SharedPref ...
- UML简易看懂
这是一堂关于UML基础知识的补习课:现在我们做项目时间都太紧了,基本上都没有做过真正的class级别的详细设计,更别提使用UML来实现规范建模了:本篇主要就以前自己一直感觉很迷糊的几种class之间的 ...
- 安装Linux和Windows的双系统
平时使用较多的操作系统是Windows,想玩玩Linux平时也是在虚拟机上,强迫症的怎么能忍,一直想装个双系统,也能强迫自己练习Linux命令,之前重装系统的时候也试着装了一下,但是准备不够充分.结果 ...
- JAVA File转Byte[]
/** * 获得指定文件的byte数组 */ public static byte[] getBytes(String filePath){ byte[] buffer = null; try { F ...
- 禁止Windows远程桌面拷贝文件
通过组策略,我们可以解决以上问题,开始菜单运行输入gpedit.msc,进入“计算机配置”项,按顺序进入“管理模板”.“windows组件”.“终端服务”.“客户端/服务器数据重定向”.在详细描述栏中 ...
Note