单片机C语言实现printf
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单片机串口实现printf函数
背景叙述:
在初学C语言时,利用printf函数向屏幕上输出字符,非常的好用和方便。学会单片机以后,尤其在学会串口通信之后,通过单片机的串口向PC机发送数据,怎么实现printf函数的功能。对于学习单片机来说,如果没有仿真器,出错误的时候不好找,只能用最笨的办法,使用printf函数,可是在KEIL里面使用printf却不像VC里面那么简单,因为其发送和硬件是有关系的。所以今天就简单来说说怎么在51单片机中使用"printf"函数:包括使用自带的printf函数和自己动手写一个printf函数
功能描述:
通过printf函数向串口发送数据,显示在终端或者串口助手上Proteus中串口终端的介绍
1、连接方法如下所示
2、串口的配置
尤其注意配置的波特率一定要和程序代码中所写的一样(否则会造成
无法显示字符)
数据位
停止位
奇偶校验位
极性(这些属性基本上是默认的配置)
3、串口终端的使用
proteus virtual terminal 使用注意事项
a. virtual terminal 默认显示字符,如果单片机发送的是非显示字符,则虚拟终端不会显示,会导致用户认为通讯未通。
运行程序,在虚拟终端窗口里面点击右键,在弹出菜单里面:
选HEX DISPLAY MODE,则显示按十六进制显示,能显示所有字符。
b.virtual terminal 默认情况下不显示回显字符,
运行程序,在虚拟终端窗口里面点击右键,在弹出菜单里面:
选Echo Typed Characters 显示回显字符
c.virtual terminal 和模拟物理串口COMPIM不能同时使用,同时使用会发生相互影响。
d. 启动仿真后可以右键单击终端,最后一栏打开和关闭串口显示终端
源程序
直接使用系统自带的printf函数:特别注意需要置位TI=1,否则是无法发送的,程序如下(此程序在proteus终端上不能显示汉字,但在串口调试助手上可以)
/******decription******************
利用printf函数向串口打印信息
51单片机晶振频率11.0592MHZ
串口通信波特率9600bps
利用printf函数TI初始值必须置1
***********************************/
/*******includes file*************/
#include
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
void delay_1ms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void uart_init(void)
TMOD=0x20; //定时计数器1,工作方式2
TH1=0xFD; //设置波特率9600
TL1=0xFD;
TR1=1;
SCON=0x50;
PCON=0x00;
EA=1;
ES=1;
TI=1; //若利用printf函数则TI初始值必须置1 }
void main()
{
uart_init();
while(1)
{
// SBUF = 'H';
// while(TI==0);
// TI=0;
printf("i am herro!\n\r");
delay_1ms(1000);
if(ff)
{
ff=0;
printf("%c",num);
}
}
}
void ser_interrupt() interrupt 4
{
if(RI==1)
{
ES=0;
RI=0;
num=SBUF;
ES=1;
ff=1;
}
}
4.编写自己的printf函数(这个函数不能再proteus中仿真,但实际中可以使用)
a.预备知识
①C语言函数:vsprintf,
其原型为int vsprintf(char *string, char *format, va_list param);,作用为将param按格式format写入字符串string中,因此他可以用于将任何格式数据转化为字符串数据,比如把整数97转化为ASCII码的97的程序就像下面这样vsprintf(string,"%d",97),当然还有一点需要注意:在keil里面使用sprintf需要包含stdio.h这个头文件(当然这里也可以使用sprintf,作用完全差不多,只需要稍加修改即可,不多介绍)。说到这里,再来说说另一个函数itoa吧,其实他比vsprintf更简单,其原型为char *itoa(int value, char *string, int radix),作用为将value按radix进制写入到string字符串中,使用时需要包含头文件stdlib.h,可是在keil里面却无法使用,头文件里面不包含itoa,即使把VC里面的复制进来貌似还是不行,呵呵,目前不知道原因。
②可变参数函数
具体来说就是stdarg.h里面的这几个函数va_start,va_arg,va_list,va_end,这几个参数用于开辟一段内存区域,可以配合vsprintf使用,但是对内存使用较大,需要单片机具备一定的RAM,否则程序就算能编译通过也是无法运行的。
函数形参列表中的变量在内存中的位置是顺次排列的。头文件Stdarg.h里的几个宏定义就是利用了这么一点,顺次获取多个参数Keil中上述函数的定义如下
typedef char * va_list; //va_list即为字符指针类型
#define va_start(ap,v) ap = (va_list)&v + sizeof(v)