单片机使用printf函数的两种办法
T89C51和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
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!=)//判断是否到字符串末尾
70. {
71. sendbyte(*string);
72. string++;
73. }
74.}
75.
76.void uart_printf(const char *fmt,...)
77.{
78. va_list ap;
79. char xdata string[1024];//访问内部拓展RAM,非访问外部RAM,不能超过内部拓展RAM大小(此处为1024)
80.
81. va_start(ap,fmt);
82. vsprintf(string,fmt,ap);//此处也可以使用sprintf函数,用法差不多,稍加修改即可,此处略去
83. sendstring(string);
84. va_end(ap);
85.}
//此程序主要用于uart发送(proteus不能仿真,但实际是可以运行的),输入换行符换行
#include
//stdio.h,stdarg.h用于vsprintf函数原型
#include
#include
void delay(unsigned int z);
void uart_init(void);//串行口初始化
void sendbyte(unsigned char c);
void sendstring(unsigned char *string);
void uart_printf(const char *fmt,...);
int main(void)
{
int a=99;
uart_init();
while(1)
{
uart_printf("10进制:%d 16进制:%x 字符格式:%c",a,a,a);
delay(1000);
}
return 0;
}
void uart_init(void)
{
TMOD=0x20;//即0010 0000,定时器/计数器1,工作方式2
TH1=0xf3;//设置波特率为2400
TL1=0xf3;
TR1=1;//启动定时器/计数器1
SCON=0x50; //0101 0000.串口工作方式1,允许串行控制
PCON=0x00;//设置SMOD=0
IE=0x00; //由于是查询方式,故需要禁止中断,CPU不允许中断,串行不允许中断
}
void delay(unsigned int z)
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void sendbyte(unsigned char c)
{
if(c==)//如果遇到就换行
{
//发送CR(carriage return)
SBUF=0x0D;
while(!TI);//等待发送完成
TI=0;
//发送 LF(NL line feed,new line)
SBUF=0x0A;
while(!TI);//等待发送完成
TI=0;
}
else
{
SBUF=c;
while(!TI);//等待发送完成
TI=0;
}
}
void sendstring(unsigned char *string)//此处*string相当于数组
{
while(*string!=)//判断是否到字符串末尾
{
sendbyte(*string);
string++;
}
}
void uart_printf(const char *fmt,...)
{
va_list ap;
char xdata string[1024];//访问内部拓展RAM,非访问外部RAM,不能超过内部拓展RAM大小(此处为1024)
va_start(ap,fmt);
vsprintf(string,fmt,ap);//此处也可以使用sprintf函数,用法差不多,稍加修改即可,此处略去
sendstring(string);
va_end(ap);
}
最后简单总结 :其中第一种方法用于中断方式工作会有问题,因为其底层是调用putchar函数实现的,工作方式为中断,但是比较简单,可以通过proteus仿真;第二种方法更完善,不过程序比较复杂,不能使用proteus仿真,但实际是可以工作的。?
注明:这篇文章是我在网上看到的,转载一下,自
单片机printf函 相关文章:
- 如何在单片机上使用printf函数(11-26)
- 单片机使用printf函数进行串口打印输出(11-26)
- 单片机中printf函数的重映射(11-26)
- MSP430G2553单片机使用printf函数进行串口打印输出(11-13)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)