printf in KEIL C51
转自:http://blog.csdn.net/it1988888/article/details/8821713
在keil中printf默认是向串口中发送数据的,所以,如果应用该函数,必须先初始化串口,否则可能引起死机的情况,并且在printf之前应该先将TI置位,摘抄原因如下:
1.printf函数是调用putchar函数输入的,而putchar应该是先判断ti是否为1,不为1则等待为1。如果为1则清0,然后送出一 个字符。因此你如果直接使用printf函数,你的程序就会在putchar函数中等待ti为1。这时你的程序就相当于直接死掉了。你可以通过改写 putchar函数实现自己的目的的。
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,启动第一次传输操作.可查看反汇编相关代码理解其工作机理!
下面举一个简单的例子:
//===========================
#include <reg51.h>
#include <stdio.h>
//-------------------------------
int main()
{
Uart_init(); //初始化串口,这里就不写具体代码了。
TI = 1; //keil 调用stdio.h中printf函数前要置位。
while(1)
{
printf("Hello world!\n");
delay_ms(800); //延时程序,这里也不写具体代码了。
}
return 0;
}
printf
http://www.keil.com/support/man/docs/c51/c51_printf.htm
Home »Library Reference »Reference » printf
Summary |
#include <stdio.h> int printf ( |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. 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 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.
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) { |
--------------------------------
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.
printf in KEIL C51的更多相关文章
- 【转】 Keil C51重定向printf到串口
概述 进行C/C++开发的时候我们都会需要打印调试信息,打印调试信息时我们习惯使用printf函数,但是在Keil C51环境下,由于我们的程序是下载到单片机里,使用printf函数时不能直接打印到串 ...
- KEIL C51 printf格式化输出特殊用法
作者:dragoniye 发布:2014-02-15 12:44 分类:硬件 抢沙发 /*******************************************KEI ...
- Keil C51 的printf
转自:http://blog.csdn.net/zhanglianpin/article/details/44779009 在Keil C51 中使用printf ,首先需要重新实现 putchar( ...
- Keil C51软件的使用
进入 Keil C51 后,屏幕如下图所示.几秒钟后出现编辑界 启动Keil C51时的屏幕 进入Keil C51后的编辑界面 简单程序的调试:学习程序设计语言.学习某种程序软件,最好的方法是直接操作 ...
- KEIL C51高级编程
第一节 绝对地址访问C51提供了三种访问绝对地址的方法: 1. 绝对宏:在程序中,用“#include”即可使用其中定义的宏来访问绝对地址,包括:CBYTE.XBYTE.PWORD.DBYTE.CWO ...
- Keil C51编译及连接技术
主要介绍Keil C51的预处理方法如宏定义.常用的预处理指令及文件包含指令,C51编译库的选择及代码优化原理,C51与汇编混合编程的方法与实现以及超过64KB空间的地址分页方法的C51实现. 教学目 ...
- keil C51 指针总结
变量就是一种在程序执行过程中其值能不断变化的量.要在程序中使用变量必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间.定义一个变量的格式如下: [存储种 ...
- KEIL C51中const和code的使用
code是KEIL C51 扩展的关键字,用code修饰的变量将会被放到CODE区里.但C语里的const关键字好像也有定义不能改变的变量的功能,这两个关键字有什么区别呢?在帮助手册里查找const, ...
- keil c51的内部RAM(idata)动态内存管理程序(转)
源:keil c51的内部RAM(idata)动态内存管理程序 程序比较简单,但感觉比较有意思,个人认为有一定应用价值,希望大家有更好的思路和方法,互相促进. 程序的基本思路是:在CPU堆栈指针SP以 ...
随机推荐
- Java线程和多线程(十四)——Synchronized关键字解析
曾经有一个比较有趣的面试问题,那就是,关于使用synchronized关键字,是用在方法上面尾号,还是用在一个代码块上面为好? 答案就是使用锁定代码块为更好.因为这样不会锁定对象.当synchroni ...
- python基础学习1-装饰器在登陆模块应用
LOGIN_USER ={"islogin":False} def outer(func): def inner(*args,**kwargs): if LOGIN_USER[&q ...
- 18-[模块]-shutil
shutil模块 高级的 文件.文件夹.压缩包 处理模块 (1)文件操作 shutil.copyfileobj(fsrc, fdst[, length]) 将文件内容拷贝到另一个文件中 import ...
- CF 724 G. Xor-matic Number of the Graph
G. Xor-matic Number of the Graph 链接 题意: 给定一个无向图,一个interesting的三元环(u,v,s)满足,从u到v的路径上的异或和等于s,三元环的权值为s, ...
- 洛咕 P3338 [ZJOI2014]力
好久没写过博客了.. 大力推式子就行了: \(E_i=\sum_{j<i}\frac{q_j}{(i-j)^2}+\sum_{j>i}\frac{q_j}{(j-i)^2}\) 那么要转化 ...
- python之GIL(Global Interpreter Lock)
一 介绍 ''' 定义: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple nati ...
- 【JUC源码解析】DelayQueue
简介 基于优先级队列,以过期时间作为排序的基准,剩余时间最少的元素排在队首.只有过期的元素才能出队,在此之前,线程等待. 源码解析 属性 private final transient Reentra ...
- Maven仓库 - 分发构件至远程仓库
分发构件至远程仓库 mvn install 会将项目生成的构件安装到本地Maven仓库,mvn deploy 用来将项目生成的构件分发到远程Maven仓库.本地Maven仓库的构件只能供当前用户使 ...
- python时间模块详解(time模块)
time 模块 -- 时间获取和转换 time 模块提供各种时间相关的功能 在 Python 中,与时间处理有关的模块包括:time,datetime 以及 calendar 必要说明: 虽然这个模块 ...
- Python之面向对象-反射
一.什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本省状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被 ...