单片机C语言实现printf文档格式.docx
- 文档编号:14873446
- 上传时间:2022-10-25
- 格式:DOCX
- 页数:10
- 大小:76.49KB
单片机C语言实现printf文档格式.docx
《单片机C语言实现printf文档格式.docx》由会员分享,可在线阅读,更多相关《单片机C语言实现printf文档格式.docx(10页珍藏版)》请在冰豆网上搜索。
proteusvirtualterminal使用注意事项
a.virtualterminal默认显示字符,如果单片机发送的是非显示字符,则虚拟终端不会显示,会导致用户认为通讯未通。
运行程序,在虚拟终端窗口里面点击右键,在弹出菜单里面:
选HEXDISPLAYMODEU显示按十六进制显示,能显示所有字符。
b.virtualterminal默认情况下不显示回显字符,
运行程序,在虚拟终端窗口里面点击右键,在弹出菜单里面:
选EchoTypedCharacters显示回显字符
c.virtualterminal和模拟物理串口COMPIM不能同时使用,同时使用
会发生相互影响。
d.启动仿真后可以右键单击终端,最后一栏打开和关闭串口显示终
直接使用系统自带的printf函数:
特别注意需要置位TI=1,否则是无法发送的,程序如下(此程序在proteus终端上不能显示汉字,但在串口调试助手上可以)
/******decription
******************
利用printf函数向串口打印信息
51单片机晶振频率11.0592MHZ
串口通信波特率9600bps
**********************************『
#include<
reg51.h>
intrins.h>
string.h>
stdio.h>
#defineucharunsignedchar
#defineuintunsignedint
voiddelay_1ms(uintz)
{
uintx,y;
for(x=z;
x>
0;
x--)
for(y=110;
y>
y--);
}
voiduart_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
)
voidmain()
(
uart_init();
while
(1)
//SBUF='
H'
;
//while(TI==0);
//TI=0;
printf("
iamherro!
\n\r"
);
delay_1ms(1000);
ff=0;
%c"
num);
voidser_interrupt()interrupt4
if(RI==1)
ES=0;
RI=0;
num=SBUF;
ff=1;
4.编写自己的printf函数(这个函数不能再proteus中仿真,但实际中
可以使用)
a.预备知识
①C语言函数:
vsprintf,
其原型为intvsprintf(char*string,char*format,va_listparam);
作用为将param按格式format写入字符串string中,因此他可以用于将任何格式数据转化为字符串数据,比如把整数97转化为ASCII码的97的
程序就像下面这样vsprintf(string,"
%d"
97),当然还有一点需要注意:
在keil里面使用sprintf需要包含stdio.h这个头文件(当然这里也可以使用sprintf,作用完全差不多,只需要稍加修改即可,不多介绍)。
说
到这里,再来说说另一个函数itoa吧,其实他比vsprintf更简单,其原型为char*itoa(intvalue,char*string,intradix),作用为将value按radix进制写入到string字符串中,使用时需要包含头文件stdlib.h,
可是在keil里面却无法使用,头文件里面不包含itoa,即使把VC里
面的复制进来貌似还是不行,呵呵,目前不知道原因。
②可变参数函数
具体来说就是stdarg.h里面的这几个函数va_start,va_arg,va_list,va_end这几个参数用于开辟一段内存区域,可以配合vsprintf使用,但是对内存使用较大,需要单片机具备一定的RAM,否则程序就算能编译通过也是无法运行的。
函数形参列表中的变量在内存中的位置是顺次排列的。
头文件Stdarg.h里的几个宏定义就是利用了这么一点,顺次获取多个参数Keil中上述函数的定义如下
typedefchar*va_list;
//va_list即为字符指针类型
#defineva_start(ap,v)ap=(va_list)&
v+sizeof(v)
#defineva_arg(ap,t)(((int*)ap)++[0])
#defineva_end(ap)//keil中什么也没有做
每个平台下面的Stdarg头文件的定义都是不相同的。
就拿keil那里的来入手。
先看一个最简单的可变参数列表的函数:
voidmytest(inta,...)
intb;
va_listap;
va_start(ap,a);
b=va_arg(ap,int);
va_end(ap);
%d,%d"
a,b);
i.首先定义一个va_list型的变量ap,也就是char*。
ii.va_start(ap,a彦替换之后就是ap=(va_list)&
a+sizeof(a);
首先取a的地址,即第一个固定参数的地址,然后强制类型转换为va_list,接着后移a的内存大小,把当前这个地址值赋给ap。
很明显,就是第一个参数a后面的那个地方,按照上面说的,也就是第一个可变参数。
即现在把ap指向第一个可变参数。
iii.b=va_arg(ap,int宏替换为b=((int*)ap)++[0];
自加在后,因此是获取第一个参数的值赋给b,然后ap后移一个
类型的位置,即指向下一个元素的地址。
iiii.va_end(ap),这里什么都没有做,在ADS那个版本里是将ap指向
NULL防止误操作。
具体内容详见
③内部拓展RAM
定义:
集成在单片机内部的数据存储器,在物理上是内部,但逻辑上
是外部,访问时需要使用MOVX或者xdata访问,具体可以看STC8051手册。
89C52单片机内含有1024byte=1Kbyte的内部拓展RAM,在访问的时候,使用C语言的时候,需要加上xdata才可以访问,使用汇编的时候需要用MOVX指令访问。
xdata:
访问内部RAM数据
源程序
利用系统自带printf函数TI初始值必须置1
***********************************
*******
includesfile
*************
〃用于vsprintf函数原型
stdarg.h>
voiddelay_1ms(uintz);
voiduart_init(void);
voidsendbyte(ucharc);
voidsendstring(uchar*string);
可变参数列表函数
voiduart_printf(constchar*fmt,...
voidmain(void)
inta=99;
uart_printf("
10进制%d16进制%x字符格式%c"
a,a,a);
)voidsendbyte(unsignedcharc)
if(c=='
\n'
SBUF=0X0D;
while(TI==0);
TI=0;
SBUF=0X0A;
else
SBUF=c;
voidsendstring(unsignedchar*string)
while(*string!
='
\0'
)//判断是否到字符串的尾端
sendbyte(*string);
string++;
voiduart_printf(constchar*fmt,...)
charxdatastring[1024];
〃访问内部RAM
va_start(ap,fmt);
vsprintf(string,fmt,ap);
sendstring(string);
voiduart_interrupt()interrupt4
/*添加处理代码*/
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 语言 实现 printf