梁永恩,萬世明
(廣東白云學(xué)院大數(shù)據(jù)與計(jì)算機(jī)學(xué)院,廣州510450)
溫度和濕度是工農(nóng)業(yè)生產(chǎn)、環(huán)境監(jiān)測(cè)等領(lǐng)域中需要測(cè)量?jī)蓚€(gè)重要的物理量。傳統(tǒng)的測(cè)量方式是利用模擬信號(hào)進(jìn)行監(jiān)測(cè),監(jiān)測(cè)系統(tǒng)需要增加信號(hào)放大、AD轉(zhuǎn)換等環(huán)節(jié),電路結(jié)構(gòu)較為復(fù)雜,數(shù)據(jù)處理也較為繁瑣。AM2302[1]是新一代的數(shù)字溫濕度傳感器,具有體積小、功耗低、響應(yīng)速度快、信號(hào)傳輸距離長(zhǎng)距離等優(yōu)點(diǎn)。本文以AM2302為溫濕度傳感器,利用STM-32F103嵌入式微控制器為主控制器,使用實(shí)時(shí)操作系統(tǒng)uC/OS III(Micro C OS Three,微型的C語言編寫的操作系統(tǒng)第3版)[2-3]和emWin圖形庫,設(shè)計(jì)了溫濕度采集系統(tǒng)。該系統(tǒng)具有電路簡(jiǎn)單、精度高、成本低、易于編程等優(yōu)點(diǎn)。本文詳述了AM2302在uC/OS III的驅(qū)動(dòng)設(shè)計(jì)和應(yīng)用。
AM2302是一款新型的單總線數(shù)字溫濕度傳感器,內(nèi)含一個(gè)電容式感濕元件和一個(gè)NTC測(cè)溫元件,全量程標(biāo)定校準(zhǔn),可靠性和長(zhǎng)期穩(wěn)定性好。溫度測(cè)量范圍為-40~80℃;濕度測(cè)量精度為±2.0%RH;溫度測(cè)量精度為<±0.5℃;響應(yīng)時(shí)間小于5s。采用單總線串行接口,與微控制器的連接簡(jiǎn)單,功耗極低,信號(hào)傳輸距離可達(dá)20米以上。
uC/OS-III是第3代的可固化的、基于優(yōu)先級(jí)的系統(tǒng)內(nèi)核,支持現(xiàn)代的實(shí)時(shí)內(nèi)核所期待的大部分功能,對(duì)任務(wù)數(shù)量和優(yōu)先級(jí)數(shù)無限制,具有高度可移植性,特別適合于微處理器和控制器。由于其具有高度可靠性、魯棒性和安全性,uC/OS實(shí)時(shí)操作系統(tǒng)已經(jīng)廣泛使用在照相機(jī)、航空電子產(chǎn)品等各種應(yīng)用中。
AM2302為4針單排引腳封裝,其與STM32F103[4]的接口如圖1所示。STM32F103的PA0引腳作為單總線接口,連接AM2302的串行數(shù)據(jù)單總線SDA,為了保證通信穩(wěn)定,這里SDA引腳加入了一個(gè)5.1KΩ的上拉電阻,VDD接3.3-6V的直流電源VCC,引腳NC懸空(不接VCC和GND)。
圖1 AM2302與STM32F103連接圖
圖2 通信時(shí)序
驅(qū)動(dòng)程序是實(shí)時(shí)內(nèi)核和硬件之間的接口,是連接底層硬件和操作系統(tǒng)內(nèi)核的“橋梁”。驅(qū)動(dòng)程序一般需要實(shí)現(xiàn)以下功能:(1)對(duì)設(shè)備進(jìn)行初始化;(2)把數(shù)據(jù)從內(nèi)核傳送到硬件或從硬件讀取數(shù)據(jù);(3)讀取應(yīng)用程序傳送給設(shè)備的數(shù)據(jù)和回送應(yīng)用程序請(qǐng)求的數(shù)據(jù);(4)監(jiān)測(cè)和處理設(shè)備出現(xiàn)的異常。
AM2302的SDA引腳用于微控制器與AM2302之間的通訊和同步,采用單總線數(shù)據(jù)格式。AM2302的通信時(shí)序如圖2所示。
發(fā)送數(shù)據(jù)前,MCU把數(shù)據(jù)總線SDA拉低至少800us后釋放總線,發(fā)送一次起始信號(hào),AM2302從休眠模式進(jìn)入高速模式。然后AM2302發(fā)送80us左右的低電平作為輸出響應(yīng),接著AM2302拉高SDA總線80us左右代表準(zhǔn)備進(jìn)入數(shù)據(jù)傳送。SDA一次通訊時(shí)間5ms左右,當(dāng)前數(shù)據(jù)傳輸為40位,高位先出。具體數(shù)據(jù)格式:40位數(shù)據(jù)=16位濕度數(shù)據(jù)+16位溫度數(shù)據(jù)+8位校驗(yàn)和。溫度數(shù)據(jù)的最高位為符號(hào)位,當(dāng)溫度低于0℃時(shí),該位為1。這里的濕度值和溫度值均為實(shí)際值的10倍。發(fā)送40位數(shù)據(jù)后將觸發(fā)一次溫濕度數(shù)據(jù)采集,數(shù)據(jù)采集結(jié)束后AM2302自動(dòng)進(jìn)入休眠模式,直到下次通信來臨。
根據(jù)前述的時(shí)序圖,微控制器讀取AM3203溫濕度數(shù)據(jù)的流程圖如圖3所示。
關(guān)鍵代碼如下:
//設(shè)置I/O方向
#define IO_AM2302_IN(){GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;}
#define IO_AM2302_OUT(){GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;}
//I/O操作函數(shù)
#define DQ_OUT PAout(0)//數(shù)據(jù)輸出端口PA0#define DQ_IN PAin(0)//數(shù)據(jù)輸入端口PA0
unsigned int RH_data,T_data;//定義濕度值,溫度值//濕度高、低8位,溫度高、低8位
unsigned char RH_data_H,RH_data_L;
unsigned char T_data_H,T_data_L;
unsigned char Check_data,ReadSuccess,Sensor_AnswerFlag,Sensor_ErrorFlag;
//讀取溫度任務(wù),每2s讀一次溫濕度數(shù)據(jù)
static void ReadData_task(void*p_arg){OS_ERR err;
while(1){Clear_data();ReadSuccess=ReadDataFromAM2302();OSTimeDlyHMSM(0,0,2,0,OS_OPT_TIME_HMSM_STRICT,&err);}}
//清除傳感器數(shù)據(jù)
void Clear_data(void){RH_data_H=0;RH_data_L=0;T_data_H=0;T_data_H=0;Check_data=0;}
//讀取溫濕度數(shù)據(jù),讀取正確返回1,否則返回0
unsigned char ReadDataFromAM2302(void){
unsigned int count; //循環(huán)計(jì)數(shù)
IO_AM2302_OUT();//設(shè)置為推挽輸出DQ_OUT=0;//輸出0
delay_ms(1); //延時(shí)1ms
DQ_OUT=1; //釋放總線
delay_us(30);
IO_AM2302_IN(); //設(shè)置為輸入狀態(tài)
//判斷傳感器是否發(fā)出響應(yīng)信號(hào)
if(DQ_IN==0){count=0;//判斷從機(jī)發(fā)出80us的低電平響應(yīng)信號(hào)是否結(jié)束
while(!DQ_IN){ //防止進(jìn)入死循環(huán)
if(++count>300) {return 0;}}
i=0;
//判斷從機(jī)是否發(fā)出80us的高電平,如發(fā)出則進(jìn)入數(shù)據(jù)接收狀態(tài)
while(DQ_IN){delay_us(1);
if(++count>300){ return 0;}}//防止進(jìn)入死循環(huán)
//數(shù)據(jù)接收,接收濕度高位、濕度低位、溫度高位,溫度低位
校驗(yàn)和(前4個(gè)字節(jié)之和)
RH_data_H=ReadOneByte();
R H_data_L=ReadOneByte();
T_data_H=ReadOneByte();
T_data_L=ReadOneByte();
Check_data=ReadOneByte();
//校驗(yàn)收到的數(shù)據(jù)是否正確
if(Check_data==RH_data_H+RH_data_L+T_data_H+T_da?
ta_L){
RH_data=RH_data_H <<8|RH_data_L;T_data=T_data_H<<8|
T_data_L;
retu.;}
else{return 0;}//未收到傳感器響應(yīng),返回0
return 0;}
//從AM2302讀取一個(gè)字節(jié)數(shù)據(jù)
unsigned char ReadOneByte(void){
unsigned char i,temp;unsigned int count=0;
//存儲(chǔ)讀出的一個(gè)字節(jié)數(shù)據(jù)
unsigned char data=0;
for(i=0;i<8;i++){count=0;
//檢測(cè)上次低電平是否結(jié)束
while(!DQ_IN){ if(++count>=300) break;}
delay_us(30);
//AM230.2~30us的高電平表示“0”,以 68~75us高電平
表示“1”
//通過檢測(cè)30us后的電平即可區(qū)別這兩個(gè)狀態(tài)
temp=0;
if(DQ_IN)temp=1;
count=0;
while(DQ_IN) { if(++count>=200) break;}//等待高電
平結(jié)束
data<<=1;
data|=temp;}return data; }
emWin是SEGGER公司開發(fā)的嵌入式圖形庫,它與單任務(wù)和多任務(wù)環(huán)境、專用操作系統(tǒng)或具有任何商業(yè)RTOS兼容,采用C語言源代碼。適用于任何尺寸、具有任何顯示控制器和CPU的物理和虛擬顯示器。emWin總共包括4層,從底層到高層分別是LCD驅(qū)動(dòng)器、圖形庫、小工具庫和窗口管理器,每一層都可以分開單獨(dú)使用。通過對(duì)LCD驅(qū)動(dòng)器層的修改后,可以很方便的移植到STM32F103使用。STemWin是針對(duì)ST公司的emWin版本,最新版本為5.28。本系統(tǒng)中采用2.4英寸TFT-LCD顯示屏,顯示控制器采用ILI9325。移植工作主要有以下幾個(gè)步驟:(1)在工程中添加STem?Win的源文件和庫文件(STemWin528_CM3_OS_Keil.lib);(2)修改LCD和GUI配置文件,設(shè)置使用操作系統(tǒng)、設(shè)置EMWIN內(nèi)存大小、添加LCD驅(qū)動(dòng)文件、修改LcdWriteReg()、LcdWriteData()、LcdWriteDataMultiple()、LcdReadDataMultiple()、LCD_X_Config()、LCD_X_Dis?playDriver()等函數(shù)以正確初始化LCD及設(shè)置相關(guān)的讀寫寄存器;(3)添加GUI_X_uCOS.c文件,加入時(shí)間相關(guān)函數(shù)、信號(hào)量、消息郵箱相關(guān)函數(shù)、與鍵盤相關(guān)函數(shù)等。
圖3 讀取溫濕度數(shù)據(jù)流程圖
溫濕度數(shù)據(jù)更新的代碼如下:
OS_EVENT*AM2302_Update_Sem;//溫濕度數(shù)據(jù)更新權(quán)
AM2302_Update_Sem=OSSemCreate(1);//創(chuàng)建一個(gè)信號(hào)量,參數(shù)1表示此信號(hào)量有效。
void AM2302_Disp_Task(void*p_arg){//溫濕度數(shù)據(jù)顯示更新任務(wù)
OS_ERR err;char text1[6]={0};for(;;){
OSSemPend(AM2302_Update_Sem,0,&err);
sprintf(text1,"%4.1f",T_data/10.0);
TEXT_SetText(WM_GetDialogItem(hWin,ID_TEXT_0),text1);
TEXT_SetText(WM_GetDialogItem(hWin,ID_TEXT_1),"℃");
……
OSSemPost(AM2302_Update_Sem);}
OSTimeDly(250);}
上述代碼中,AM2302_Disp_Task任務(wù)用來更新溫濕度數(shù)據(jù)的顯示。使用OSSemPend函數(shù)等待一個(gè)信號(hào)量有效,通過一個(gè)OSSemPost函數(shù)釋放一個(gè)信號(hào)量。更新溫濕度數(shù)據(jù)之前,要等待AM2302_Up?date_Sem信號(hào)量有效并獲得更新的控制權(quán)。更新完畢后,要及時(shí)地釋放掉信號(hào)量,以便其他任務(wù)使用這個(gè)資源。界面顯示效果如圖4所示。
圖4 界面顯示效果
基于uC/OS III提出了AM2302的驅(qū)動(dòng)程序設(shè)計(jì)及應(yīng)用方案。AM2302體積小、功耗低、響應(yīng)快,適用于測(cè)量溫濕度的各類應(yīng)用場(chǎng)合。配合嵌入式實(shí)時(shí)操作系統(tǒng)uC/OS III和嵌入式圖形庫emWin,簡(jiǎn)化了系統(tǒng)設(shè)計(jì),提高了系統(tǒng)的易用性和可操作性。