梁永恩,萬世明
(廣東白云學院大數據與計算機學院,廣州510450)
溫度和濕度是工農業生產、環境監測等領域中需要測量兩個重要的物理量。傳統的測量方式是利用模擬信號進行監測,監測系統需要增加信號放大、AD轉換等環節,電路結構較為復雜,數據處理也較為繁瑣。AM2302[1]是新一代的數字溫濕度傳感器,具有體積小、功耗低、響應速度快、信號傳輸距離長距離等優點。本文以AM2302為溫濕度傳感器,利用STM-32F103嵌入式微控制器為主控制器,使用實時操作系統uC/OS III(Micro C OS Three,微型的C語言編寫的操作系統第3版)[2-3]和emWin圖形庫,設計了溫濕度采集系統。該系統具有電路簡單、精度高、成本低、易于編程等優點。本文詳述了AM2302在uC/OS III的驅動設計和應用。
AM2302是一款新型的單總線數字溫濕度傳感器,內含一個電容式感濕元件和一個NTC測溫元件,全量程標定校準,可靠性和長期穩定性好。溫度測量范圍為-40~80℃;濕度測量精度為±2.0%RH;溫度測量精度為<±0.5℃;響應時間小于5s。采用單總線串行接口,與微控制器的連接簡單,功耗極低,信號傳輸距離可達20米以上。
uC/OS-III是第3代的可固化的、基于優先級的系統內核,支持現代的實時內核所期待的大部分功能,對任務數量和優先級數無限制,具有高度可移植性,特別適合于微處理器和控制器。由于其具有高度可靠性、魯棒性和安全性,uC/OS實時操作系統已經廣泛使用在照相機、航空電子產品等各種應用中。
AM2302為4針單排引腳封裝,其與STM32F103[4]的接口如圖1所示。STM32F103的PA0引腳作為單總線接口,連接AM2302的串行數據單總線SDA,為了保證通信穩定,這里SDA引腳加入了一個5.1KΩ的上拉電阻,VDD接3.3-6V的直流電源VCC,引腳NC懸空(不接VCC和GND)。

圖1 AM2302與STM32F103連接圖

圖2 通信時序
驅動程序是實時內核和硬件之間的接口,是連接底層硬件和操作系統內核的“橋梁”。驅動程序一般需要實現以下功能:(1)對設備進行初始化;(2)把數據從內核傳送到硬件或從硬件讀取數據;(3)讀取應用程序傳送給設備的數據和回送應用程序請求的數據;(4)監測和處理設備出現的異常。
AM2302的SDA引腳用于微控制器與AM2302之間的通訊和同步,采用單總線數據格式。AM2302的通信時序如圖2所示。
發送數據前,MCU把數據總線SDA拉低至少800us后釋放總線,發送一次起始信號,AM2302從休眠模式進入高速模式。然后AM2302發送80us左右的低電平作為輸出響應,接著AM2302拉高SDA總線80us左右代表準備進入數據傳送。SDA一次通訊時間5ms左右,當前數據傳輸為40位,高位先出。具體數據格式:40位數據=16位濕度數據+16位溫度數據+8位校驗和。溫度數據的最高位為符號位,當溫度低于0℃時,該位為1。這里的濕度值和溫度值均為實際值的10倍。發送40位數據后將觸發一次溫濕度數據采集,數據采集結束后AM2302自動進入休眠模式,直到下次通信來臨。
根據前述的時序圖,微控制器讀取AM3203溫濕度數據的流程圖如圖3所示。
關鍵代碼如下:
//設置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操作函數
#define DQ_OUT PAout(0)//數據輸出端口PA0#define DQ_IN PAin(0)//數據輸入端口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;
//讀取溫度任務,每2s讀一次溫濕度數據
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);}}
//清除傳感器數據
void Clear_data(void){RH_data_H=0;RH_data_L=0;T_data_H=0;T_data_H=0;Check_data=0;}
//讀取溫濕度數據,讀取正確返回1,否則返回0
unsigned char ReadDataFromAM2302(void){
unsigned int count; //循環計數
IO_AM2302_OUT();//設置為推挽輸出DQ_OUT=0;//輸出0
delay_ms(1); //延時1ms
DQ_OUT=1; //釋放總線
delay_us(30);
IO_AM2302_IN(); //設置為輸入狀態
//判斷傳感器是否發出響應信號
if(DQ_IN==0){count=0;//判斷從機發出80us的低電平響應信號是否結束
while(!DQ_IN){ //防止進入死循環
if(++count>300) {return 0;}}
i=0;
//判斷從機是否發出80us的高電平,如發出則進入數據接收狀態
while(DQ_IN){delay_us(1);
if(++count>300){ return 0;}}//防止進入死循環
//數據接收,接收濕度高位、濕度低位、溫度高位,溫度低位
校驗和(前4個字節之和)
RH_data_H=ReadOneByte();
R H_data_L=ReadOneByte();
T_data_H=ReadOneByte();
T_data_L=ReadOneByte();
Check_data=ReadOneByte();
//校驗收到的數據是否正確
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;}//未收到傳感器響應,返回0
return 0;}
//從AM2302讀取一個字節數據
unsigned char ReadOneByte(void){
unsigned char i,temp;unsigned int count=0;
//存儲讀出的一個字節數據
unsigned char data=0;
for(i=0;i<8;i++){count=0;
//檢測上次低電平是否結束
while(!DQ_IN){ if(++count>=300) break;}
delay_us(30);
//AM230.2~30us的高電平表示“0”,以 68~75us高電平
表示“1”
//通過檢測30us后的電平即可區別這兩個狀態
temp=0;
if(DQ_IN)temp=1;
count=0;
while(DQ_IN) { if(++count>=200) break;}//等待高電
平結束
data<<=1;
data|=temp;}return data; }
emWin是SEGGER公司開發的嵌入式圖形庫,它與單任務和多任務環境、專用操作系統或具有任何商業RTOS兼容,采用C語言源代碼。適用于任何尺寸、具有任何顯示控制器和CPU的物理和虛擬顯示器。emWin總共包括4層,從底層到高層分別是LCD驅動器、圖形庫、小工具庫和窗口管理器,每一層都可以分開單獨使用。通過對LCD驅動器層的修改后,可以很方便的移植到STM32F103使用。STemWin是針對ST公司的emWin版本,最新版本為5.28。本系統中采用2.4英寸TFT-LCD顯示屏,顯示控制器采用ILI9325。移植工作主要有以下幾個步驟:(1)在工程中添加STem?Win的源文件和庫文件(STemWin528_CM3_OS_Keil.lib);(2)修改LCD和GUI配置文件,設置使用操作系統、設置EMWIN內存大小、添加LCD驅動文件、修改LcdWriteReg()、LcdWriteData()、LcdWriteDataMultiple()、LcdReadDataMultiple()、LCD_X_Config()、LCD_X_Dis?playDriver()等函數以正確初始化LCD及設置相關的讀寫寄存器;(3)添加GUI_X_uCOS.c文件,加入時間相關函數、信號量、消息郵箱相關函數、與鍵盤相關函數等。

圖3 讀取溫濕度數據流程圖
溫濕度數據更新的代碼如下:
OS_EVENT*AM2302_Update_Sem;//溫濕度數據更新權
AM2302_Update_Sem=OSSemCreate(1);//創建一個信號量,參數1表示此信號量有效。
void AM2302_Disp_Task(void*p_arg){//溫濕度數據顯示更新任務
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任務用來更新溫濕度數據的顯示。使用OSSemPend函數等待一個信號量有效,通過一個OSSemPost函數釋放一個信號量。更新溫濕度數據之前,要等待AM2302_Up?date_Sem信號量有效并獲得更新的控制權。更新完畢后,要及時地釋放掉信號量,以便其他任務使用這個資源。界面顯示效果如圖4所示。

圖4 界面顯示效果
基于uC/OS III提出了AM2302的驅動程序設計及應用方案。AM2302體積小、功耗低、響應快,適用于測量溫濕度的各類應用場合。配合嵌入式實時操作系統uC/OS III和嵌入式圖形庫emWin,簡化了系統設計,提高了系統的易用性和可操作性。