【小项目】STM32环境监测 | MQ2可燃气体传感器+雨滴传感器+DHT11温湿度传感器+OLED屏幕
目錄
- 概述
- 固件編寫
- DHT11溫濕度傳感器
- 概述
- 代碼
- MQ2可燃?xì)怏w傳感器和雨滴傳感器
- 概述
- ADC外設(shè)
- 代碼
- OLED屏幕
- 概述
- 代碼
- main.c文件
- 概述
- 代碼
- 總結(jié)
- 項(xiàng)目代碼下載
概述
前些陣子參加了廣東省電賽,因?yàn)橐咔榈脑虮荣惒荒茉诰€下進(jìn)行,甚至連回學(xué)校調(diào)試也不行,于是乎就水了一個(gè)省三。
備賽的時(shí)候,隊(duì)長(zhǎng)給我布置了這個(gè)小項(xiàng)目,說有可能會(huì)用在比賽的作品中,但實(shí)際就不知道了,所以在這里分享一下代碼。
固件編寫
這個(gè)需求對(duì)性能要求不高,像人見人愛、人手一個(gè)的STM32F103C8T6也能勝任,但因?yàn)槲覜]帶回家,所以用了野火的霸道V2開發(fā)板。
這塊開發(fā)板用的是STM32F103ZET6芯片。
DHT11溫濕度傳感器
概述
溫濕度傳感器玩過單片機(jī)的小伙伴都應(yīng)該特別熟悉了,在這里就不再贅述了。但還是放幾張時(shí)序圖解釋一下。
總體來說DHT11是串行通信,只用一根數(shù)據(jù)線進(jìn)行通信,通信的形式有點(diǎn)像IIC,都是先給一個(gè)響應(yīng)信號(hào),然后傳感器應(yīng)答后開始傳輸數(shù)據(jù),直到從機(jī)或主機(jī)發(fā)送結(jié)束信號(hào)。
下面是主機(jī)發(fā)送響應(yīng)信號(hào)的時(shí)序。
從機(jī)接收到主機(jī)的響應(yīng)信號(hào)后會(huì)按以下時(shí)序產(chǎn)生應(yīng)答信號(hào),表示接受響應(yīng)。
實(shí)際發(fā)送的數(shù)據(jù)都是以一低一高的形式表示,“0”和“1”的區(qū)別在于高電平的持續(xù)時(shí)間,利用這一點(diǎn)主機(jī)可以區(qū)分“0”和“1”比特。
代碼
下面是接收一個(gè)字節(jié)和接收溫濕度數(shù)據(jù)的代碼:
/* * 從DHT11讀取一個(gè)字節(jié),MSB先行*/ static uint8_t DHT11_ReadByte ( void ) {uint8_t i, temp=0;for(i=0;i<8;i++) { /*每bit以50us低電平標(biāo)置開始,輪詢直到從機(jī)發(fā)出 的50us 低電平 結(jié)束*/ while(DHT11_Dout_IN() == RESET);/*DHT11 以26~28us的高電平表示“0”,以70us高電平表示“1”,*通過檢測(cè) x us后的電平即可區(qū)別這兩個(gè)狀 ,x 即下面的延時(shí) */DHT11_DELAY_10US(4); //延時(shí)x us 這個(gè)延時(shí)需要大于數(shù)據(jù)0持續(xù)的時(shí)間即可 if(DHT11_Dout_IN() == SET)/* x us后仍為高電平表示數(shù)據(jù)“1” */{/* 等待數(shù)據(jù)1的高電平結(jié)束 */while(DHT11_Dout_IN() == SET);temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行 }else // x us后為低電平表示數(shù)據(jù)“0”{ temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行}}return temp;}/** 一次完整的數(shù)據(jù)傳輸為40bit,高位先出* 8bit 濕度整數(shù) + 8bit 濕度小數(shù) + 8bit 溫度整數(shù) + 8bit 溫度小數(shù) + 8bit 校驗(yàn)和 */ uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data) { /*輸出模式*/DHT11_Mode_Out_PP();/*主機(jī)拉低*/DHT11_Dout_0;/*延時(shí)18ms*/DHT11_DELAY_MS(18);/*總線拉高 主機(jī)延時(shí)30us*/DHT11_Dout_1; DHT11_DELAY_10US(3); //延時(shí)30us/*主機(jī)設(shè)為輸入 判斷從機(jī)響應(yīng)信號(hào)*/ DHT11_Mode_IPU();/*判斷從機(jī)是否有低電平響應(yīng)信號(hào) 如不響應(yīng)則跳出,響應(yīng)則向下運(yùn)行*/ if(DHT11_Dout_IN() == RESET) {/*輪詢直到從機(jī)發(fā)出 的80us 低電平 響應(yīng)信號(hào)結(jié)束*/ while(DHT11_Dout_IN() == RESET);/*輪詢直到從機(jī)發(fā)出的 80us 高電平 標(biāo)置信號(hào)結(jié)束*/while(DHT11_Dout_IN() == SET);/*開始接收數(shù)據(jù)*/ DHT11_Data->humi_int= DHT11_ReadByte();DHT11_Data->humi_deci= DHT11_ReadByte();DHT11_Data->temp_int= DHT11_ReadByte();DHT11_Data->temp_deci= DHT11_ReadByte();DHT11_Data->check_sum= DHT11_ReadByte();/*讀取結(jié)束,引腳改為輸出模式*/DHT11_Mode_Out_PP();/*主機(jī)拉高*/DHT11_Dout_1;/*檢查讀取的數(shù)據(jù)是否正確*/if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)return SUCCESS;else return ERROR;}elsereturn ERROR;}MQ2可燃?xì)怏w傳感器和雨滴傳感器
概述
因?yàn)榭扇細(xì)怏w檢測(cè)和雨滴感應(yīng)的傳感器原理較相似,所以放到一起講了。
可燃?xì)怏w傳感器用的是MQ2。
下面是雨滴模塊的樣子(簡(jiǎn)單到連名字都沒有)
兩個(gè)模塊都是用模擬信號(hào)通信,所以使用STM32的ADC外設(shè)就可以輕松讀取數(shù)據(jù)。
ADC外設(shè)
根據(jù)STM32的用戶手冊(cè)知道我們使用的這款芯片有3個(gè)ADC外設(shè),為了讓單片機(jī)能更快處理轉(zhuǎn)換模擬信號(hào),所以使用了雙ADC模式;為了讓我們能隨時(shí)調(diào)整采樣的時(shí)間,我還使用了ADC外設(shè)的外部觸發(fā)功能;為了保證數(shù)據(jù)傳輸?shù)男饰疫€使用了DMA進(jìn)行傳輸。
解釋一下雙ADC模式,通俗講就是正常是一個(gè)ADC處理2個(gè)模擬信號(hào)的轉(zhuǎn)換,現(xiàn)在2個(gè)ADC分別負(fù)責(zé)2個(gè)模擬信號(hào)的轉(zhuǎn)換,并且是硬件控制同時(shí)開始轉(zhuǎn)換的,因此效率會(huì)高很多。
STM32支持的雙ADC模式有好幾個(gè),具體可參考用戶文檔,在這里我們使用最常用的同步規(guī)則模式即可。
但需要注意的是雙ADC模式只能使用ADC1和ADC2外設(shè)
代碼
接下來放核心代碼吧,對(duì)于STM32的ADC玩法還挺多的,計(jì)劃在另外寫一篇文章來講一下。
adc.c文件:
adc.h文件:
/* 相關(guān)配置 */ #define CONV_TIME 100 // 采樣周期,單位ms/* 其他宏定義 */ #define TIM_PERIOD_VAL (CONV_TIME * 2 - 1)/* 管腳宏定義 */ #define TIM_PORT TIM3 #define TIM_PERI_CLK_PORT RCC_APB1Periph_TIM3#define DMA_PERI_CLK_PORT RCC_AHBPeriph_DMA1 #define ADC1_DR_Address ((uint32_t)0x4001244C) #define ADC_DMA_CHAL DMA1_Channel1void ADC_Config(void); uint16_t ADC_GetMQ2RawData(void); uint16_t ADC_GetWaterSensorRawData(void);OLED屏幕
概述
OLED屏幕應(yīng)該也有很多小伙伴玩過了。
這個(gè)屏幕的通信方式有挺多種的,比如說8080時(shí)序、IIC、SPI,具體是哪種通信方式要看買的時(shí)候商家的說明。
我買的這個(gè)是IIC的接口,我使用了硬件IIC對(duì)其通信。
代碼
簡(jiǎn)單貼一下代碼:
礙于篇幅就只放初始化和傳輸一個(gè)字節(jié)的代碼吧。
main.c文件
概述
應(yīng)隊(duì)長(zhǎng)的要求這個(gè)小項(xiàng)目用了FreeRTOS系統(tǒng),但實(shí)際上除了用到最基本的任務(wù)調(diào)度外,其他的功能都沒有用到。
至于FreeRTOS系統(tǒng)的移植網(wǎng)上都有好多的教程了,這里就不贅述了。
簡(jiǎn)單說主任務(wù)做的就是一段時(shí)間后切換OLED屏幕的顯示內(nèi)容(因?yàn)橐粔KOLED屏幕顯示不了所有傳感器的數(shù)據(jù))
代碼
簡(jiǎn)單貼一下代碼:
static void MainTask(void* params) {uint8_t status = 0;while(1){if (status){DHT11_Read_TempAndHumidity(&dht11_data);OLED_ShowTempAndHumi(dht11_data.temp_int, dht11_data.temp_deci, dht11_data.humi_int, dht11_data.humi_deci);printf("Displaying temperature and humidity\n");}else{OLED_ShowPpmAndWaterLevel(MQ2_GetPPM(), WaterSensor_GetWaterLevel());printf("Displaying PPM and water level\n");}status = !status;vTaskDelay(2000);} }static void AppInitTask(void* params) {taskENTER_CRITICAL(); // 進(jìn)入臨界段NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);USART_Config();MQ2_Init();WaterSensor_Init();ADC_Config();TIMER_Init();DHT11_Init();OLED_Init();printf("Init completed\n");vTaskDelay(100);xTaskCreate(MainTask, "MainTask", 1024, NULL, 5, NULL);printf("Main task created\n");vTaskDelete(NULL); // 刪除這個(gè)任務(wù)taskEXIT_CRITICAL(); // 退出臨界段 }/*** @brief 主函數(shù)* @param None* @retval None*/ int main(void) {BaseType_t xReturn = pdPASS;xReturn = xTaskCreate(AppInitTask, "AppInitTask", 1024, NULL, 5, NULL);if (xReturn == pdPASS) vTaskStartScheduler(); // 開啟任務(wù)調(diào)度else while(1); }總結(jié)
總的來說,這個(gè)項(xiàng)目還是蠻適合對(duì)STM32已經(jīng)入門然后想進(jìn)階的小伙伴。
項(xiàng)目包含了對(duì)各種常見模塊的代碼撰寫,每種模塊對(duì)應(yīng)的通信協(xié)議、用到的外設(shè)也不盡相同;項(xiàng)目還涉及了對(duì)FreeRTOS系統(tǒng)的基本移植和使用,對(duì)于想進(jìn)階STM32的小伙伴是非常好的。
項(xiàng)目代碼下載
鏈接:https://download.csdn.net/download/JackieCoo/86506760
總結(jié)
以上是生活随笔為你收集整理的【小项目】STM32环境监测 | MQ2可燃气体传感器+雨滴传感器+DHT11温湿度传感器+OLED屏幕的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MSP430F5529 DriverLi
- 下一篇: ThinkPad X220i 刷白名单B