新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機使用printf函數的兩種辦法

        單片機使用printf函數的兩種辦法

        作者: 時間:2016-11-26 來源:網絡 收藏
        今天就簡單來說說怎么在51單片機中使用"printf"函數:包括使用自帶的printf函數和自己動手寫一個printf函數,再貼代碼之前先介紹幾個相關的知識,主要用于自己寫printf函數。

        ①C語言函數:vsprintf,

        本文引用地址:http://www.104case.com/article/201611/321829.htm

        其原型為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


        上一頁 1 2 下一頁

        關鍵詞: 單片機printf函

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 麟游县| 岳阳县| 高密市| 前郭尔| 玛多县| 高淳县| 察雅县| 呼伦贝尔市| 中卫市| 察哈| 宁蒗| 永靖县| 旬邑县| 龙陵县| 岳阳市| 道孚县| 楚雄市| 汕尾市| 临沂市| 多伦县| 翁牛特旗| 交口县| 会宁县| 渭源县| 龙州县| 常山县| 清水县| 临邑县| 乌鲁木齐市| 东乡| 彭泽县| 碌曲县| 临汾市| 怀宁县| 南华县| 阿勒泰市| 通河县| 海阳市| 延津县| 乐山市| 温泉县|