又是一周過去。不知這一周大家過得怎么樣?是否開心,是否有所收獲。
秋天,是一個收獲的季節。這一切都是建立在春耕夏播的基礎之上。
以上是序。
通過前面的學習,我們學會了如何用串口發送數據和接收固定字節的命令。今天,我們繼續討論串口應用協議,主要焦點還是在如何有效地使用串口發送數據。為了簡化描述,假設我們基于8051單片機開發一個溫濕度采集系統,周期將溫度和濕度數據上報到上位機。溫度和濕度定義如下:
float temperature = 25.0; //溫度
float humidity = 70.0; //濕度
我們至少可以設計出以下兩種不同的串口應用協議:
1.固定大小的消息:先發送float類型的溫度,再發送float類型的濕度。每次傳輸8個字節。
溫度(4字節) |
濕度(4字節) |
代碼實現:
// 固定消息發送溫度和濕度函數
void send_temperature_and_humidity(float temperature, float humidity)
{
uart_sendFloat(temperature); //發送溫度
uart_sendFloat(humidity);//發送濕度
}
-
字符串消息,先發送溫度的字符串,再發送濕度的字符串,兩者之間有明顯的分隔符(例如空格、分號或冒號),結尾一般以“ ”結束。
"25.0, 70.0 " |
//以字符串消息發送溫度和濕度函數
void send_temperature_and_humidity_string(float temperature, float humidity)
{
printf("%f,%f ", tempeature, humidity); //以字符串消息發送溫度、濕度
}
以上兩種應用協議中,哪一種最好呢?
-
從消息長度來看,固定消息大小都是8個字節,而字符串消息則超過8個字節且長度不定(請思考為什么?)
-
從可讀性來看,在ASCII接收模式下,字符串消息可讀性高(人可直接讀),固定消息“不可讀”。
-
從效率和保密性(假設有這一條吧),固定消息勝出,因為它發送的是原始二進制數據,占用字節最少。
為了傳輸更多的數據和實現更復雜的功能,我們通常在固定消息的基礎上引入更多的輔助數據。例如,增加校驗位保證數據傳輸無誤,增加地址字節以區分不同設備等。但對于有些上位機(LabVIEW)來說,它對字符串數據的解釋可以一步到位,無需按圖索驥。
AT命令常用于控制WiFi模塊、SMS模塊等,就是以字符串消息實現的。
練手項目:假設有一個多點溫度采集系統,架構如下圖所示。
其中,N值取決于具體的系統要求。試基于固定長度消息設計串口應用協議,實現多點數據的上報。
太簡單了,一次傳完N點溫度,如下:
1#溫度 |
2#溫度 |
...... |
N#溫度 |
順序讀取1#~N#的溫度,先放到緩沖里,一次調用串口發送函數將N點數據發送出去。收工!
N很小時,沒有毛病。假設N=128,則要求溫度緩存數組長度至少為128個,一個溫度數值占4字節(float),要128*4 = 512B,這超出了可用內存。如果不同的項目,N點都不一樣,那么上位機的程序必須根據N點修改串口接收程序。累死。
怎么辦?我們可以每讀一個DS18B20,就將溫度發送到串口。重復N次就完成一次溫度采集與上報。
為了區分是哪個DS18B20,我們增加一個字節數據表示設備號(1~N)。所以,串口上報協議變為:
設備號(1字節, unsigned char) |
溫度(4字節,float) |
N最大為255。這么做的好處一個是簡化了程序,也便于上位機接收和處理數據。
關鍵代碼:
unsigned char ds18b20_no= 1;
//讀取溫度并發送到串口
float temperature;
temperature = ds18b20_readTermperature(ds18b20_no); //讀取溫度
uart_sendUchar(ds18b20_no); //發送設備號
uart_sendFloat(temperature); //發送溫度
ds18b20_readTermperature()函數是讀取溫度函數,本例中我們先使用模擬的(而不是真正去讀一個DS18B20)。實現如下:
//讀取DS18B20溫度(模擬)
float ds18b20_readTemperature(unsigned char no)
{
static unsigned char tick = 0; //為了模擬得到一個變化的溫度引入的變量
float temperature;
tick++;
temperature = no + tick*0.1;
return temperature;
}
我們引入模塊化編程的思想,把發送功能封裝到一個函數里。函數是模塊化開發的必經之路。函數的引入增強了代碼的可讀性和復用性,也便于修改和維護程序。經過不斷積累,函數庫的引入可以使開發事半功倍。例如前面我們把串口封裝到uart.h和uart.c,就是模塊化思想的淋漓盡致的體現。使用串口,則直接添加uart.h和uart.c到工程,然后在主程序包含uart.h,直接調用定義好的串口函數就可以訪問串口。
//發送溫度函數,設備號(1B)溫度(4B)
void sendTemperature(unsigned char no, float temperature)
{
uart_sendUchar(no);
uart_sendFloat(temperature);
}
我們使用C51編程入門(二十二)串口編程入門--串口應用協議(一)的proteus仿真電路,使用LabVIEW開發上位機來接收多點溫度數據并顯示。
仿真電路(沒有接DS18B20,,溫度模擬產生)
LabVIEW上位機能夠正確接收并解碼數據。LabVIEW的程序框圖如下:
結束語
附上本次串口源碼,如下。如果你覺得本篇文章有所幫助,請點贊,請打賞。您的支持是對我們的最大鼓勵。如果需要仿真電路和串口工程源碼以及LabVIEW上位機源碼,請在后臺留言。
下一篇文章我們將完善仿真電路,增加DS18B20元件及驅動程序,并完善LabVIEW上位機(增加溫度保存功能)。如果有可能,后面會開發LabVIEW串口程序的相關教程,并提供LabVIEW源碼。
完整的代碼:(uart.h和uart.c略,前一篇文章已經給出)
//uart_firstdemo.c
//#include"reg51.h"
sbit beeper_en = P2^0;
sbit key_s1 = P1^0;
char msg[] = "Welcome back. ";
unsigned char uart_rx_buffer[2];
unsigned int count = 0;
//函數定義
void delayMS(unsigned int nms);
void keyScan(); //按鍵掃描
float ds18b20_readTemperature(unsigned char no); //讀取DS18B20溫度
void sendTemperature(unsigned char no, float temperature); //發送溫度函數
void main()
{
unsignedchards18b20_no=1;//設備號
unsigned char ds18b20_N = 3; //ds18b20總數
float temperature; //溫度
uart_init();
while(1)
{
temperature = ds18b20_readTemperature(ds18b20_no); //讀溫度
sendTemperature(ds18b20_no, temperature); //發送溫度
ds18b20_no++;
if(ds18b20_no > ds18b20_N)//已經讀完所有點的溫度
{
ds18b20_no = 1;
delayMS(1000);//等待1s左右,再開始下一次采集
}
}
}
void keyScan()
{
floattemperature;
if(key_s1 == 0)
{
delayMS(10);//消抖
if(key_s1 == 0) //按鍵按下,讀取并上報1#地點的溫度
{
temperature = ds18b20_readTemperature(1); //讀溫度
sendTemperature(1, temperature); //發送溫度
}
}
}
//延時函數
void delayMS(unsigned int nms)
{
unsignedinti,j;
for(i=0;i
for(j=0;j<130;j++);
}
//讀取DS18B20溫度(模擬)
float ds18b20_readTemperature(unsigned char no)
{
static unsigned char tick = 0;
float temperature;
tick++;
temperature = no + tick*0.1;
return temperature;
}
//發送溫度函數
void sendTemperature(unsigned char no, float temperature)
{
uart_sendUchar(no);
uart_sendFloat(temperature);
}
-
單片機
+關注
關注
6063文章
44925瀏覽量
647002 -
串口
+關注
關注
14文章
1585瀏覽量
78660 -
字符串
+關注
關注
1文章
589瀏覽量
21114 -
溫濕度采集系統
+關注
關注
0文章
6瀏覽量
6155
原文標題:C51編程入門(二十三)串口編程入門--串口應用協議(二)
文章出處:【微信號:輕松學單片機,微信公眾號:輕松學單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
基于單片機的溫濕度采集系統的硬件設計

基于單片機的溫濕度控制系統

基于單片機的糧倉溫濕度監控系統

基于單片機的多路溫濕度采集系統

評論