轉自:http://blog.csdn.net/it1988888/article/details/8821713html
在keil中printf默認是向串口中發送數據的,因此,若是應用該函數,必須先初始化串口,不然可能引發死機的狀況,而且在printf以前應該先將TI置位,摘抄緣由以下:git
1.printf函數是調用putchar函數輸入的,而putchar應該是先判斷ti是否爲1,不爲1則等待爲1。若是爲1則清0,而後送出一 個字符。所以你若是直接使用printf函數,你的程序就會在putchar函數中等待ti爲1。這時你的程序就至關於直接死掉了。你能夠經過改寫 putchar函數實現本身的目的的。promise
2.Keil的串口處理比較巧妙的,個人分析以下:
putchar.c裏面,是先檢測TI再發送。這樣作的目的是把儘量多的時間留給2次串口操做之間的程序,而不是把等待字節發送的時間白白空等待浪費掉。因此,在系統初始化的時候,必定要令TI=1; 就能夠順暢的使用printf函數了。摟主sbuf=" "的辦法,其實就是令TI=1. 另外要特別注意,printf函數執行完畢後,最後一個字節並未發送完畢,例如在485通信中,此時若是切換爲收模式,會丟失最後一字節.app
3.通常串口發送都是等TI(字節發送完標誌)爲1就立刻發送下一字節,因爲無論是中斷仍是查詢TI標誌的方法,都會檢測TI,所以首次發送必須置 位TI標誌,使串口開始發送你的「在程序的初始化部分往串口數據寄存器SBUF裏放一個字符來起用終端顯示;」方法最終做用也就是把TI置1,改爲 TI=1;來啓動發送也是同樣的(固然,不會發出那個' '字符了)。less
4.<stdio.h>中定義,調用底層的putchar()來實現.底層發送數據到串口時,先查TI=1是否成立,死等直到TI=1時將新數據寫入SBUF,函數返回,因此要先將TI置1,啓動第一次傳輸操做.可查看反彙編相關代碼理解其工做機理!ide
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 theputcharfunction. The fmtstr argument is a format string that may be composed of characters, escape sequences, and format specifications.this 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.spa 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 enougharguments 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.
Note
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. Note
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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); } |
Information in this article applies to:
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?
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);