單片機使用printf函數的兩種辦法
①C語(yǔ)言函數:vsprintf,
本文引用地址:http://dyxdggzs.com/article/201611/321829.htm其原型為int vsprintf(char *string, char *format, va_list param);,作用為將param按格式format寫(xiě)入字符串string中,因此他可以用于將任何格式數據轉化為字符串數據,比如把整數97轉化為ASCII碼的97的程序就像下面這樣vsprintf(string,"%d",97),當然還有一點(diǎn)需要注意:在keil里面使用sprintf需要包含stdio.h這個(gè)頭文件(當然這里也可以使用sprintf,作用完全差不多,只需要稍加修改即可,不多介紹)。說(shuō)到這里,再來(lái)說(shuō)說(shuō)另一個(gè)函數itoa吧,其實(shí)他比vsprintf更簡(jiǎn)單,其原型為char *itoa(int value, char *string, int radix),作用為將value按radix進(jìn)制寫(xiě)入到string字符串中,使用時(shí)需要包含頭文件stdlib.h,可是在keil里面卻無(wú)法使用,頭文件里面不包含itoa,即使把VC里面的復制進(jìn)來(lái)貌似還是不行,呵呵,目前不知道原因。
②可變參數函數
具體來(lái)說(shuō)就是stdarg.h里面的這幾個(gè)函數va_start,va_arg,va_list,va_end,這幾個(gè)參數用于開(kāi)辟一段內存區域,可以配合vsprintf使用,但是對內存使用較大,需要單片機具備一定的RAM,否則程序就算能編譯通過(guò)也是無(wú)法運行的,用法見(jiàn)這里http://blog.csdn.net/googlemi/article/details/8988567
③內部拓展RAM
定義:集成在單片機內部的數據存儲器,在物理上是內部,但邏輯上是外部,訪(fǎng)問(wèn)時(shí)需要使用MOVX或者xdata訪(fǎng)問(wèn),具體可以看STC8051手冊,如下所示
從這里可以看出,STC12C5A60S2單片機內部含有1024byte=1Kbyte的內部拓展RAM,在訪(fǎng)問(wèn)的時(shí)候,使用C語(yǔ)言的時(shí)候,需要加上x(chóng)data才可以訪(fǎng)問(wèn),使用匯編的時(shí)候需要用MOVX指令訪(fǎng)問(wèn)。
到這里我們先來(lái)算一算STC12C5A60S2單片機在不接外部RAM的情況下總的RAM大小,先看一下內部的RAM分布圖
:內部RAM(256byte)包括三部分:低128byte,高128byte和特殊功能寄存器區,特別注意和51不同,他的特殊功能寄存器和高128byte地址重疊,但是物理上是分開(kāi)的,所有內部可用的RAM有256byte,所以到此為止可以得到內部RAM大小總共有:256byte+1024byte=1280byte
說(shuō)了這么多,下面不多說(shuō),直接上程序
《一》直接使用系統自帶的printf函數:特別注意需要置位TI=1,否則是無(wú)法發(fā)送的,程序如下:
[cpp] view plaincopyprint?
01.//此程序主要用于uart發(fā)送(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,定時(shí)器/計數器1,工作方式2
26. TH1=0xfd;//設置波特率為9600
27. TL1=0xfd;
28. TR1=1;//啟動(dòng)定時(shí)器/計數器1
29.
30. SCON=0x50; //0101 0000.串口工作方式1,允許串行控制
31. PCON=0x00;//設置SMOD=0
32. IE=0x90; //CPU允許中斷,串行允許中斷
33.
34. TI=1;//直接使用printf必須加入此句才能實(shí)現發(fā)送
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發(fā)送(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,定時(shí)器/計數器1,工作方式2
TH1=0xfd;//設置波特率為9600
TL1=0xfd;
TR1=1;//啟動(dòng)定時(shí)器/計數器1
SCON=0x50; //0101 0000.串口工作方式1,允許串行控制
PCON=0x00;//設置SMOD=0
IE=0x90; //CPU允許中斷,串行允許中斷
TI=1;//直接使用printf必須加入此句才能實(shí)現發(fā)送
}
void delay(unsigned int z)
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
《二》自己動(dòng)手寫(xiě)一個(gè)類(lèi)似printf的函數:uart_printf
但是這種情況占用RAM較多,因為需要開(kāi)辟大數組,所以需要使用拓展型的51單片機,普通的AT89C51和STC89C52之類(lèi)的會(huì )造成內存不夠用、堆棧溢出等等問(wèn)題,所以以下程序都是基于STC12C5A60S2的,因為它含有內部拓展的1024byte的RAM,可以用來(lái)存儲大數組
[cpp] view plaincopyprint?
01.//此程序主要用于uart發(fā)送(proteus不能仿真,但實(shí)際是可以運行的),輸入換行符換行
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進(jìn)制:%d 16進(jìn)制:%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,定時(shí)器/計數器1,工作方式2
28. TH1=0xf3;//設置波特率為2400
29. TL1=0xf3;
30. TR1=1;//啟動(dòng)定時(shí)器/計數器1
31.
32. SCON=0x50; //0101 0000.串口工作方式1,允許串行控制
33. PCON=0x00;//設置SMOD=0
評論