1.printf系列的函數實現
懂得了單片機通過串口傳輸數據給電腦端窗口查看,那么,有時我們需要發(fā)送字符串,有時需要發(fā)送一個變量的數值是多少,以及還要發(fā)送回車換行這三種情況。所以我們把這三個功能函數封裝起來,方便后續(xù)的串口使用。
首先筆者寫的“void printf_str(u8 *str)”函數就是專門用來發(fā)送字符串給電腦端的。
其次“void printf_num(u32 num)”發(fā)送的變量的數值只支持顯示十進制數0~4294967295,也就是參數是u32類型。
最后“void printf_rn()”就是發(fā)送回車換行符了。
關于這三部分的代碼大家可以嘗試去閱讀一下是怎么實現的,如果有很多地方看不懂那么可以不用深究,往下學,筆者會在后面的知識點中講解其中的運用。
我們希望串口這部分功能模塊也能像定時器那樣封裝一個單獨文件來使用。
所以創(chuàng)建好“uart.c”和“uart.h”文件,復制以下代碼
2.uart.c的代碼
#include <reg52.h> #include <function.h>//詳見第六章第8講 void ConfigUART(u16 baud) { SCON = 0x50; //配置串口為模式1 TMOD &= 0x0F; //清零T1的控制位 TMOD |= 0x20; //配置T1為模式2 TH1 = 256 - (11059200/12/32)/baud;//計算T1重載值 TL1 = TH1; //初值等于重載值 ET1 = 0; //禁止T1中斷 ES = 1; //使能串口中斷 TR1 = 1; //啟動T1 } void printf_str(u8 *str) { while(*str != '\0')//連續(xù)發(fā)送字符串數據,直到檢測到結束符 { SBUF=*str++; while(!TI); //等待字節(jié)發(fā)送完成TI被置1就退出這個while循環(huán) TI = 0; //清0標志位 } } void printf_num(u32 num) { u8 buf[10]; char i;//取值范圍為-128~127 for (i=0; i<10; i++) //把長整型數轉換為10位十進制的數組 { buf[i] = num % 10; num = num / 10; //舍掉個位數,重新裝載 } for (i=9; i>=1; i--) { if (buf[i] != 0)break; //從最高位起,遇到0不理會,遇到非0則退出循環(huán) } while(i>=0) //剩余低位都如實發(fā)送出去 { SBUF='0'+buf[i]; //如果此時的buf[i]的值是1,那么電腦端窗口在“字符格式”模式下要想顯示字符“1”,只需'0'+1,因為‘0’就是ASCII碼值48 while(!TI); //等待字節(jié)發(fā)送完成TI被置1就退出這個while循環(huán) TI = 0; //清0標志位 i--; } } void printf_rn() //發(fā)送回車換行符 { SBUF='\r'; while(!TI); //等待字節(jié)發(fā)送完成TI被置1就退出這個while循環(huán) TI = 0; //清0標志位 SBUF='\n'; while(!TI); //等待字節(jié)發(fā)送完成TI被置1就退出這個while循環(huán) TI = 0; //清0標志位 }
3.uart.h的代碼
#ifndef __UART_H__ #define __UART_H__ void ConfigUART(u16 baud); void printf_str(u8 *str);//發(fā)送字符串 void printf_num(u32 num);//發(fā)送參數的數值 void printf_rn(); //發(fā)送回車換行符 #endif
4.main.c的代碼
#include <reg52.h> #include <function.h>//詳見第六章第8講 #include <uart.h> void main() { u8 key; u32 value=65535; LED_Init();//初始化LED硬件模塊 KEY_Init();//初始化按鍵模塊 EA = 1; //閉合總中斷開關 ConfigUART(9600); while(1) { key=KEY_Scan(0,1000); if(key==4) { printf_str("value=");//發(fā)送字符串 printf_num(value); //發(fā)送變量的數值 printf_rn(); //發(fā)送回車換行符 value++; } } } void InterruptUART() interrupt 4 { if (RI) //接收到字節(jié) { RI = 0;//手動清零接收中斷標志位 } }
在串口中斷函數中我們沒有再寫“if(TI){ TI = 0; }”,那是因為我們在所有的發(fā)送函數中都做了TI的清0處理,所以可以在串口中斷函數中不用再書寫TI。
大家別忘了創(chuàng)建好“uart.c”和“uart.h”之后要添加到工程文件中
打開串口,選擇“字符格式顯示”模式,不斷按K4,不停打印出如下內容
C語言網提供由在職研發(fā)工程師或ACM藍橋杯競賽優(yōu)秀選手錄制的視頻教程,并配有習題和答疑,點擊了解:
一點編程也不會寫的:零基礎C語言學練課程
解決困擾你多年的C語言疑難雜癥特性的C語言進階課程
從零到寫出一個爬蟲的Python編程課程
只會語法寫不出代碼?手把手帶你寫100個編程真題的編程百練課程
信息學奧賽或C++選手的 必學C++課程
藍橋杯ACM、信息學奧賽的必學課程:算法競賽課入門課程
手把手講解近五年真題的藍橋杯輔導課程