本實例基於STM32W108的SimpleMac協議棧,利用無線節點完成對溫度、溼度、超聲波、煙霧、聲音、光敏等傳感器的控制及數據採集,並實時將數據發送到STM32W108開發板,完成傳感器數據的彙集,並通過串口傳送給PC機。
13.4 傳感器數據採集程序設計與實現
下面將根據不同的傳感器分別進行傳感器數據採集程序的設計說明,最後給出數據包的發送、接收及主函數部分的詳細內容。
13.4.1 溫度傳感器
temperature.h文件內容:
#ifndef __TEMPERATURE_H__ #define __TEMPERATURE_H__ #define TEMP_BUS PORTA_PIN(5) //PA5 #define TEMP_BUS_INPUT_GPIO GPIO_PAIN //端口A輸入寄存器 #define TEMP_BUS_OUTPUT_GPIO GPIO_PAOUT //端口A輸出寄存器 #define TEMP_BUS_GPIO_PIN PA5_BIT //PA5_BIT的值爲4 #define TEMP_BUS_WAKE_SOURCE 0x00000080 #define TEMP_BUS_SET (GPIO_PASET_ADDR+((GPIO_PBCFGL_ADDR -GPIO_PACFGL_ADDR)*(TEMP_BUS/8))) #define TEMP_BUS_CLR (GPIO_PACLR_ADDR+((GPIO_PBCFGL_ADDR -GPIO_PACFGL_ADDR)*(TEMP_BUS/8))) extern u16 Read_Temperature();// 讀溫度函數 #endif |
temperature.c文件:
#include PLATFORM_HEADER #include BOARD_HEADER #include "temperature.h" #include "hal/micro/micro-common.h" #include "hal/micro/cortexm3/micro-common.h"
#define LOW 0//低電平 #define HIGH 1//高電平
/************************************************************************** 功能描述:設置端口,將端口置高或置低 輸入參數:status:電平的參數,高電平或低電平 輸出參數:無 *************************************************************************/ static void SetPort(int8u Statu) { halGpioConfig(TEMP_BUS, GPIOCFG_OUT); //設置總線爲輸出狀態 if(TEMP_BUS/8 < 3) { if(Statu==HIGH)//高電平 *((volatile int32u *)TEMP_BUS_SET) = BIT(TEMP_BUS&7); //設置寄存器bit4 else *((volatile int32u *)TEMP_BUS_CLR) = BIT(TEMP_BUS&7); //清除寄存器bit4 } }
/************************************************************************** 功能描述:獲取端口狀態 輸入參數:無 輸出參數:u8類型值,1或0,0表示低電平,1表示高電平 *************************************************************************/ u8 GetPort() { halGpioConfig(TEMP_BUS, GPIOCFG_IN); //設置總線爲輸入狀態
//bit4爲1返回1,爲0返回0 return (TEMP_BUS_INPUT_GPIO & (1<<TEMP_BUS_GPIO_PIN))?1:0; }
/************************************************************************** 功能描述:實現us級延時 輸入參數:int32u類型變量,延遲時間 輸出參數:無 *************************************************************************/ void Delay_1us(int32u x) { halCommonDelayMicroseconds(x); //延時x us }
/************************************************************************** 功能描述:對DS18B20進行復位操作 輸入參數:無 輸出參數:無 *************************************************************************/ void DS18B20_Reset() { SetPort(LOW); //輸出低電平,拉低總線 Delay_1us(500); //延遲500us SetPort(HIGH); //釋放總線 Delay_1us(60); //延遲60us while(GetPort()); //等待從機DS18B20應答(低電平有效) while(!GetPort()); //等待從機DS18B20釋放總線 }
/************************************************************************** 功能描述:向DS18B20寫一個字節 輸入參數:u8類型變量,寫入DS18B20的數據 輸出參數:無 *************************************************************************/ void DS18B20_Write(u8 Data) { u8 i; for(i=0;i<8;i++) { SetPort(LOW); //拉低總線 Delay_1us(10); //延遲10us(最大15us) SetPort(Data&0x01); //將數據的最低位寫出 Delay_1us(40); //延遲40us(最大45us) SetPort(HIGH); //釋放總線 Delay_1us(1); //稍微延遲 Data>>=1; } }
/************************************************************************** 功能描述:從DS18B20讀一個字節 輸入參數:無 輸出參數:u8類型變量,從DS18B20讀取的一個字節數據 *************************************************************************/ u8 DS18B20_Read() { u8 i,dat; for(i=0;i<8;i++) { SetPort(LOW); // 拉低總線,啓動輸入 Delay_1us(1); // 延遲1us SetPort(HIGH); // 釋放總線 dat = (GetPort() << 7) | (dat >> 1);//最先讀出的是最低位數據 Delay_1us(45); // 延遲 45us(最大45us) } return dat; }
/************************************************************************** 功能描述:讀取當前溫度,利用DS18B20進行溫度的採集 輸入參數:無 輸出參數:u16類型變量,讀取的溫度值,當前溫度值=返回值/100 *************************************************************************/ u16 Read_Temperature() { u8 Temp1,Temp2;
//DS18B20 開始轉換: DS18B20_Reset(); //DS18B20 復位 DS18B20_Write(0xCC); // 跳過 ROM DS18B20_Write(0x44); // 溫度轉換 Delay_1us(800); // 延遲 750~900us
//DS18B20 讀暫存數據: DS18B20_Reset(); //DS18B20 復位 DS18B20_Write(0xCC); // 跳過 ROM DS18B20_Write(0xbe); // 讀取 RAM Temp1=DS18B20_Read(); // 讀低八位, LS Byte, RAM0 Temp2=DS18B20_Read(); // 讀高八位, MS Byte, RAM1 DS18B20_Reset(); //DS18B20 復位,表示讀取結束
//對於負數,轉換成整數之後進行單位轉換,然後再重新轉換回負數補碼形式 if(Temp2&0xFC) return (u16)((~((u16)(((~((Temp2<<8)|Temp1))+1)*6.25)))+1); // 高八位第八位進行整 else return (u16)(((Temp2<<8)|Temp1)*6.25); //0.0625=xx, 0.625=xx.x, 6.25=xx.xx } |
13.4.2 溫溼度傳感器
DH11.h文件:
#ifndef __DH11_H__ #define __DH11_H__ #define DBUS PORTC_PIN(6) //PC6引腳 #define DBUS_INPUT_GPIO GPIO_PAIN //輸入引腳 #define DBUS_OUTPUT_GPIO GPIO_PAOUT //輸出引腳 #define DBUS_GPIO_PIN PC6_BIT #define DBUS_WAKE_SOURCE 0x00000080 #define DBUS_SET (GPIO_PCSET_ADDR) #define DBUS_CLR (GPIO_PCCLR_ADDR)
extern void SetDH11Status(int32u status); //設置相應端口爲高電平或低電平 extern u8 GetDH11Status(); //獲取傳感器狀態 extern void DH11Start(); //啓動DH11傳感器,觸發一次信號採集; extern u8 GetDH11BD(); //按字節讀取採集的數據 extern void GetDH11Data(); //獲取採集的數據 #endif |
DHT11.c文件:
#include PLATFORM_HEADER #include BOARD_HEADER #include "DH11.h" #include "hal/micro/micro-common.h" #include "hal/micro/cortexm3/micro-common.h" #include "stdio.h"
#define LOW 0//低電平 #define HIGH 1//高電平
/************************************************************************** 功能描述:完成對相應端口設置給定的電平 輸入參數:status:電平的參數,高電平或低電平 輸出參數:無 *************************************************************************/ void SetDH11Status(int32u status) { halGpioConfig(DBUS,GPIOCFG_OUT); //將DBUS端口設置爲輸出模式 if(DBUS/8 < 3) { if(status==HIGH) //高電平 *((volatile int32u *)DBUS_SET) = BIT(DBUS&7); else //低電平 *((volatile int32u *)DBUS_CLR) = BIT(DBUS&7); } }
/************************************************************************** 功能描述:獲取端口DBUS_INPUT_GPIO的電平狀態 輸入參數:無 輸出參數:u8類型變量,返回1表示高電平,返回0表示低電平 *************************************************************************/ u8 GetDH11Status() { return (DBUS_INPUT_GPIO & (1<<DBUS_GPIO_PIN)) ? 1 : 0; }
/************************************************************************** 功能描述:完成對DHT11傳感器的初始化,觸發一次數據採集 輸入參數:無 輸出參數:無 *************************************************************************/ void DH11Start() { SetDH11Status(LOW); //把總線拉低至少18ms等待DHT11響應 halCommonDelayMicroseconds(18000); SetDH11Status(HIGH); //釋放總線,輸出高電平 halCommonDelayMicroseconds(20); //延時等待20-40us halGpioConfig(DBUS,GPIOCFG_IN); }
/************************************************************************** 功能描述:完成對給採集到的數據的按字節讀取 輸入參數:無 輸出參數:無 *************************************************************************/ u8 GetDH11BD() { u8 i,tmp; //i爲循環變量,tmp爲標誌位,爲1表示讀出的是1,爲0表示讀出的是0 u8 temp=0; //存放最終讀到的數據 halCommonDelayMicroseconds(30); //延時30us for(i=0;i<8;i++) //循環得到8位的最終數據 { temp=temp<<1;
//每個位傳輸都以50us的低電平時隙開始,所以在此等待低電平結束 while(!GetDH11Status()); if(GetDH11Status()) //如果輸出爲0,則高電平持續時間爲26us-28us { halCommonDelayMicroseconds(28); }
/*如果讀到的數據爲1,則高電平持續時間爲70us,那麼28us後仍爲高電平,則 表明讀取的數據爲1,設置標誌位*/ if(GetDH11Status()) { tmp=1; halCommonDelayMicroseconds(40); } else tmp=0; temp|=tmp; } return temp; } |
本文出自《STM32W108嵌入式無線傳感器網絡》邱鐵,夏鋒,周玉編著.清華大學出版社,2014年5月