①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,否则程序就算能编译通过也是无法运行的,用法见这里http://blog.csdn.net/googlemi/article/details/8988567
③内部拓展RAM
定义:集成在单片机内部的数据存储器,在物理上是内部,但逻辑上是外部,访问时需要使用MOVX或者xdata访问,具体可以看STC8051手册,如下所示
从这里可以看出,STC12C5A60S2单片机内部含有1024byte=1Kbyte的内部拓展RAM,在访问的时候,使用C语言的时候,需要加上xdata才可以访问,使用汇编的时候需要用MOVX指令访问。
到这里我们先来算一算STC12C5A60S2单片机在不接外部RAM的情况下总的RAM大小,先看一下内部的RAM分布图
:内部RAM(256byte)包括三部分:低128byte,高128byte和特殊功能寄存器区,特别注意和51不同,他的特殊功能寄存器和高128byte地址重叠,但是物理上是分开的,所有内部可用的RAM有256byte,所以到此为止可以得到内部RAM大小总共有:256byte+1024byte=1280byte
说了这么多,下面不多说,直接上程序
《一》直接使用系统自带的printf函数:特别注意需要置位TI=1,否则是无法发送的,程序如下:
[cpp] view plaincopyprint?
01.//此程序主要用于uart发送(proteus终端不能显示汉字,但串口助手可以),输入换行符 换行
02.#include
03.//stdio.h,string.h用于printf函数原型
04.#include
05.
06.
07.void delay(unsigned int z);
08.void uart_init(void);//串行口初始化
09.
10.int main(void)
11.{
12. int a=99;
13. char *string="abde";
14. uart_init();
15. while(1)
16. {
17. printf("%d %x %c %s %p ",a,a,(char)a,string,string);
18. delay(1000);
19. }
20. return 0;
21.}
22.
23.void uart_init(void)
24.{
25. TMOD=0x20;//即0010 0000,定时器/计数器1,工作方式2
26. TH1=0xfd;//设置波特率为9600
27. TL1=0xfd;
28. TR1=1;//启动定时器/计数器1
29.
30. SCON=0x50; //0101 0000.串口工作方式1,允许串行控制
31. PCON=0x00;//设置SMOD=0
32. IE=0x90; //CPU允许中断,串行允许中断
33.
34. TI=1;//直接使用printf必须加入此句才能实现发送
35.}
36.
37.void delay(unsigned int z)
38.{
39. unsigned int x,y;
40. for(x=z;x>0;x--)
41. for(y=110;y>0;y--);
42.}
//此程序主要用于uart发送(proteus终端不能显示汉字,但串口助手可以),输入换行符 换行
#include
//stdio.h,string.h用于printf函数原型
#include
void delay(unsigned int z);
void uart_init(void);//串行口初始化
int main(void)
{
int a=99;
char *string="abde";
uart_init();
while(1)
{
printf("%d %x %c %s %p ",a,a,(char)a,string,string);
delay(1000);
}
return 0;
}
void uart_init(void)
{
TMOD=0x20;//即0010 0000,定时器/计数器1,工作方式2
TH1=0xfd;//设置波特率为9600
TL1=0xfd;
TR1=1;//启动定时器/计数器1
SCON=0x50; //0101 0000.串口工作方式1,允许串行控制
PCON=0x00;//设置SMOD=0
IE=0x90; //CPU允许中断,串行允许中断
TI=1;//直接使用printf必须加入此句才能实现发送
}
void delay(unsigned int z)
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
《二》自己动手写一个类似printf的函数:uart_printf
但是这种情况占用RAM较多,因为需要开辟大数组,所以需要使用拓展型的51单片机,普通的AT89C51和STC89C52之类的会造成内存不够用、堆栈溢出等等问题,所以以下程序都是基于STC12C5A60S2的,因为它含有内部拓展的1024byte的RAM,可以用来存储大数组
[cpp] view plaincopyprint?
01.//此程序主要用于uart发送(proteus不能仿真,但实际是可以运行的),输入换行符 换行
02.#include
03.//stdio.h,stdarg.h用于vsprintf函数原型
04.#include
05.#include
06.
07.void delay(unsigned int z);
08.void uart_init(void);//串行口初始化
09.void sendbyte(unsigned char c);
10.void sendstring(unsigned char *string);
11.void uart_printf(const char *fmt,...);
12.
13.int main(void)
14.{
15. int a=99;
16. uart_init();
17. while(1)
18. {
19. uart_printf("10进制:%d 16进制:%x 字符格式:%c ",a,a,a);
20. delay(1000);
21. }
22. return 0;
23.}
24.
25.void uart_init(void)
26.{
27. TMOD=0x20;//即0010 0000,定时器/计数器1,工作方式2
28. TH1=0xf3;//设置波特率为2400
29. TL1=0xf3;
30. TR1=1;//启动定时器/计数器1
31.
32. SCON=0x50; //0101 0000.串口工作方式1,允许串行控制
33. PCON=0x00;//设置SMOD=0[page]
34. IE=0x00; //由于是查询方式,故需要禁止中断,CPU不允许中断,串行不允许中断
35.
36.}
37.
38.void delay(unsigned int z)
39.{
40. unsigned int x,y;
41. for(x=z;x>0;x--)
42. for(y=110;y>0;y--);
43.}
44.
45.void sendbyte(unsigned char c)
46.{
47. if(c==' ')//如果遇到 就换行
48. {
49. //发送CR(carriage return)
50. SBUF=0x0D;
51. while(!TI);//等待发送完成
52. TI=0;
53.
54. //发送 LF(NL line feed,new line)
55. SBUF=0x0A;
56. while(!TI);//等待发送完成
57. TI=0;
58. }
59. else
60. {
61. SBUF=c;
62. while(!TI);//等待发送完成
63. TI=0;
64. }
65.}
66.
67.void sendstring(unsigned char *string)//此处*string相当于数组
68.{
69. while(*string!='