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

2020-12-25 電子產品世界
今天就簡單來說說怎麼在51單片機中使用"printf"函數:包括使用自帶的printf函數和自己動手寫一個printf函數,再貼代碼之前先介紹幾個相關的知識,主要用於自己寫printf函數。

①C語言函數:vsprintf,

本文引用地址:http://www.eepw.com.cn/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

相關焦點

  • 單片機使用printf函數進行串口列印輸出
    以前在使用keil編寫51單片機程序的時候,經常使用printf函數列印輸出一些關鍵的過程數據到電腦,方便監控程序的運行狀況。最近使用IAR for MSP430 調試 MSP430G2553 程序的時候,發現了一些小問題,MSP430G2553單片機並沒有按照我的預期輸出數據到電腦。帶著疑惑我查看了keil的幫助文件裡面的printf函數說明,原來printf函數最終是調用putchar函數來實現列印輸出字符的。
  • 51單片機實現scanf和printf函數
    最開始學習C語言時,使用printf和scanf進行格式化輸入輸出十分方便。學習單片機有很長時間了,之前要再屏幕上顯示一個變量或者通過串口傳出一些變量值觀測的話,需要進行一系列的取餘取整運算,很是麻煩。
  • MSP430G2553單片機使用printf函數進行串口列印輸出
    以前在使用keil編寫51單片機程序的時候,經常使用printf函數列印輸出一些關鍵的過程數據到電腦,方便監控程序的運行狀況。最近使用IAR for MSP430 調試MSP430G2553程序的時候,發現了一些小問題,MSP430G2553單片機並沒有按照我的預期輸出數據到電腦。
  • 如何在單片機上使用printf函數
    當我們在調試代碼時,通常需要將程序中的某個變量列印至PC機上,來判斷我們的程序是否按預期的運行,printf函數很好的做到了這一點,它能直接以字符的方式輸出變量名和變量的值,這樣使輸出的信息很直觀;但printf函數在使用時,不僅僅要初始化串口
  • printf()函數重定向到STM32串口輸出
    /html/1573.htmlC語言中使用printf()函數輸出是非常方便功能非常強大的,如果能將printf()函數使用到串口上,能實現非常多的強大輸出功能,極大方便我們使用串口輸出功能。()函數使用標準庫,標準庫中包括printf()等函數使用了半主機模式,導致無法運行(見參考)解決辦法:1,使用微庫,在工程屬性的Target->Code Generation中勾選Use MicroLIB2, 重新實現庫中某些函數,避免使用標準庫(見參考)參考:http://blog.csdn.net/wdscq1234/article
  • 如何在STM32單片機的MDK工程中使用printf
    打開APP 如何在STM32單片機的MDK工程中使用printf 發表於 2018-12-24 14:25:12 首先,要包含頭文件「stdio.h」 第二:printf()函數使用了int fputc(int ch,FILE *f)完成其功能。
  • TrueStudio開發工具:printf函數輸出使用沒方向,怎麼辦?
    在TrueStudio開發工具中使用printf函數如果第一次接觸可能會找不到方向,現將最近剛剛接觸STM32CubeMX配置生成TrueStudio工程串口列印的使用過程進行如下說明。C、串口1配置為異步通信模式配置單片機運行頻率按照下圖設置為主頻72Mhz。
  • STM32中如何使用printf()函數
    STM32串口通信中使用printf發送數據配置方法(開發環境 Keil RVMDK在STM32串口通信程序中使用printf發送數據,非常的方便。可在剛開始使用的時候總是遇到問題,常見的是硬體訪真時無法進入main主函數,其實只要簡單的配置一下就可以了。
  • 關於單片機程序中使用printf的一點建議
    在Keil函數中,用printf函數調試起來很方便。但必須注意以:1.必須先初始化串口,否則可能引起死機的情況,並且在printf之前應該先將TI置位。
  • 在使用串口列印printf()函數時的配置
    在使用串口列印printf()函數時的配置在STM32串口通信程序中使用printf發送數據,非常的方便。可在剛開始使用的時候總是遇到問題,下面就說一下使用printf需要做哪些配置。printf函數是c語言庫stdio.h中的函數,在使用printf列印時,應包含頭文件,其次還要配置fputc()函數,1、首先要在你的main 文件中 包含「stdio.h」 (標準輸入輸出頭文件)。
  • STM32程序添加printf函數後無法運行的解決方法(串口實驗)
    (USART1, (uint8_t) ch);while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);return ch;}因printf()之類的函數,使用了半主機模式。
  • STM32+Keil 如何使用printf函數?
    那麼只能通過程序向硬體串口發數據了,這樣調用的時候用自定義的函數即可,也很方便,例如:本文引用地址:http://www.eepw.com.cn/article/201611/317105.htmvoid send_char_to_usart(unsigned char c){}但是可否直接使用printf函數呢?
  • 關於printf和scanf函數的一些問題(含拓展)
    筆者認為C語言入門最好的辦法就是多寫點直接上手,相信你馬上會越來越熟練並發現其中的樂趣嘻嘻,那時候你就不會像筆者我剛上第一節程序課的時候嚇得懷疑自己選錯了專業了,因為在這之前筆者是真的一點都不懂啊。註明出處:《C程序設計(第五版)》,知乎@關於編程哪些事、@這個範、@無言講編程
  • STM8L051F3等小容量單片機sprintf函數的重構
    sprintf函數是字符串格式化命令,主要功能是把格式化的數據寫入某個字符串中。
  • 學習c語言筆記——C庫函數printf()
    c語言中的printf是什麼來的?」。我答:「它是一個函數,主要用來輸出運算結果。」 ,下面就給大家介紹C庫函數printf()使用方法。下面我們通過一個調用c庫函數的c語言案例來說明printf()函數的使用方法,如c語言1。
  • STM32 keil printf的使用
    keil)工程屬性的「Target「-》」Code Generation「中勾選」Use MicroLIB本文引用地址:http://www.eepw.com.cn/article/201611/315976.htm前提是你有一個完整keil的工程 比如ADC的調試的時候很多時候用到串口 這裡教你怎麼樣使用Printf 函數
  • 【經典】把脈printf中的C進階技巧
    因為printf需要實現可變參數,那麼肯定是需要有約定的傳參數的規則,該約定的規則就決定了函數內部如何獲得對應參數。    對於大部分小夥伴在平時的開發中基本上都是使用固定的參數類型,不過對於類似於printf這種用戶接口使用型函數,實現可變參數就顯得更加具有靈活性。學習過C++的小夥伴應該有種感覺,可變參數有點類似於函數重載,不過C的可變參數必須包含一個參數。
  • 51單片機基礎剖析(基於C語言)
    2.函數的參數和局部變量的存儲模式 C51 編譯器允許採用三種存儲器模式:SMALL,COMPACT 和LARGE。一個函數的存儲器模式確定了函數的參數的局部變量在內存中的地址空間。處於SMALL模式下的函數參數和局部變量位於8051單片機內部RAM中,處於COMPACT和LARGE模式下的函數參數和局部變量則使用單片機外部RAM。
  • Linux中printf命令使用實例
    在編寫shell腳本時,我們使用echo列印到標準輸出。echo是一個簡單的命令,但其功能有限,想要更好的控制輸出格式,可以使用printf命令。還包括了三個\n換行符,printf命令默認不會添加還行符號,需要手動添加。類型轉換說明符是一個字符,用於指定如何解釋相應的參數,該字符是必須添加的,以下是顯示所有類型轉換及其作用的列表:該例子使用%d,%x,%o將後面提供的參數轉化為十進位、十六進位、八進位。
  • STM32中使用HAL庫重定向printf()函數
    函數添加頭文件#include "stdio.h"添加函數// 重定向函數1int fputc(int ch,FILE *f){    uint8_t temp[1]={ch};    HAL_UART_Transmit