第二節(jié)和第三節(jié)介紹了如何使用C語言編程單片機(jī),制作 LED 閃爍小燈,以及 LED “呼吸燈”。上一節(jié)介紹了利用 DHT11 溫濕度傳感器測(cè)量室內(nèi)溫度和濕度的方法,本節(jié)將把它們結(jié)合,制作一些更加“有意思”的小玩意兒。
溫濕度報(bào)警器
溫濕度傳感器的很多實(shí)際應(yīng)用的場(chǎng)景都是檢測(cè)一個(gè)“閾值”——例如,如果環(huán)境溫度在 40 攝氏度以下則一切正常,一旦環(huán)境溫度超過 40 攝氏度,就會(huì)有報(bào)警信息,通常以“聲光”的形式(鈴聲、警報(bào)燈等)給出。
參照實(shí)際應(yīng)用,我們可以使用C語言編程單片機(jī),用緩和的 LED “呼吸燈”表示正常溫濕度情況。而一旦出現(xiàn)溫度超過閾值的情況,則可以用急促的 LED 閃爍小燈表示。
先來看看上一節(jié)獲取室內(nèi)溫濕度的單片機(jī) C語言程序代碼:
void main() { char dat[5] = {0}; int cks; init_uart(9600); set_timer0(10); // 10us prints("init...\r\n"); delay_10us(50000);delay_10us(50000); delay_10us(50000);delay_10us(50000); prints("program start...\r\n"); while(1){ dht11_start(); dht11_read_once(dat); cks = 0; cks += dat[0]; cks += dat[1]; cks += dat[2]; cks += dat[3]; if((char)cks == dat[4]){ prints("RH: ");printn(dat[0]);prints(".");printn(dat[1]);prints(" "); prints("TM: ");printn(dat[2]);prints(".");printn(dat[3]);prints("\r\n"); }else{ prints("capture failed\r\n"); } delay_10us(50000);delay_10us(50000); } }
乍一看,要實(shí)現(xiàn)上面的設(shè)計(jì)好像很簡單,只需要判斷一下溫度值,再?zèng)Q定使用哪一套 LED 小燈的控制程序(“呼吸燈”程序,或者“閃爍”程序)就可以了。
但是 DHT11 傳感器需要的 delay_10us(50000); 語句會(huì)破壞 LED 小燈的控制程序,因?yàn)樵谶@ 500ms 期間,單片機(jī)處于等待狀態(tài),無法控制 LED 小燈閃爍或者“呼吸”。那么,沒有辦法解決這個(gè)問題嗎?也不是,請(qǐng)看 LED 小燈“閃爍”的核心C語言程序:
while(1){ P20 = 0; delay(10); P20 = 1; delay(10); }
以及 LED 的“呼吸燈”的核心C語言程序:
void twinkle_once(unsigned char darkTime) { P20 = 0; delay(100-darkTime); P20 = 1; delay(darkTime); }
仔細(xì)思考一下,應(yīng)該能明白無論是 LED “閃爍”程序,還是“呼吸”程序,其實(shí)都依賴“延時(shí)”。那思路就有了,直接使用 LED 小燈的控制程序代替 delay_10us(50000); 不就可以了嗎?的確如此,請(qǐng)繼續(xù)往下看。
編寫C語言程序,制作自己的警報(bào)器
先在上一節(jié) C語言代碼的基礎(chǔ)上氨氣報(bào)警器,實(shí)現(xiàn)更大尺度的 5ms 延時(shí)函數(shù):
void delay_5ms(unsigned int n) { while(n--) delay_10us(5); }
使用 delay_5m() 函數(shù)替換之前定義的“不精確”延時(shí)函數(shù) delay() 函數(shù)甲烷報(bào)警器,這樣我們就能知道較為精確的 LED 小燈的控制程序執(zhí)行時(shí)間,也就能更加方便的替換 delay_10us(50000); 語句。
現(xiàn)在寫出“呼吸”1 秒的 LED “呼吸燈”C語言程序就不難了,請(qǐng)看:
void led_breath_1s() { static int cnt = 0; static char dark_time = 0, dir = 1 ; while(1){ twinkle_once(dark_time); if( 0==((cnt++)%4) ){ if(dir) dark_time += 1; else dark_time -= 1; if(dark_time >= 100) dir = 0; if(dark_time <= 60) dir = 1; } if(cnt > 200){ cnt = 0; break; } } }
twinkle_once() 執(zhí)行一次需要 5ms 的時(shí)間,cnt 計(jì)數(shù)到 200 次就恰好是 1 秒,另外,if( 0==((cnt++)%4) ) 語句仍然能夠控制 LED 小燈的“呼吸”頻率。其他部分的代碼與之前介紹的就沒什么不同了。
類似的,閃爍 1 秒的 LED “閃爍”C語言程序可以如下實(shí)現(xiàn):
void led_twinkle_1s() { char cnt = 5; while(cnt--){ P21 = 1; delay_10us(10000); P21 = 0; delay_10us(10000); } }
閃爍一次需要 200 ms 的時(shí)間,那么閃爍 5 次就是 1秒了?,F(xiàn)在使用 led_breath_1s() 和 led_twinkle_1s() 函數(shù)替換delay_10us(50000); 語句就可以了。請(qǐng)看:
void main() { char dat[5] = {0}; int cks; init_uart(9600); set_timer0(10); // 10us prints("init...\r\n"); // delay_10us(50000);delay_10us(50000); // delay_10us(50000);delay_10us(50000); led_breath_1s(); led_breath_1s(); prints("program start...\r\n"); while(1){ dht11_start(); dht11_read_once(dat); cks = 0; cks += dat[0]; cks += dat[1]; cks += dat[2]; cks += dat[3]; if((char)cks == dat[4]){ prints("RH: ");printn(dat[0]);prints(".");printn(dat[1]);prints(" "); prints("TM: ");printn(dat[2]);prints(".");printn(dat[3]);prints("\r\n"); }else{ prints("capture failed\r\n"); } if(dat[2] > 15) led_twinkle_1s(); else led_breath_1s(); //delay_10us(50000);delay_10us(50000); } }
初始化時(shí),使用了 led_breath_1s(); 代替了 DHT11 傳感器需要的延時(shí),每次獲取溫濕度值的時(shí)候,則判斷了溫度值,如果溫度大于 15 攝氏度,使用LED的“閃爍”程序代替延時(shí) 1秒,否則使用 LED 的“呼吸燈”程序代替。
現(xiàn)在編譯C語言程序,燒寫到單片機(jī),可以得到如下結(jié)果:
一開始,DHT11 探測(cè)到的溫度較低,所以LED指示燈是“呼吸”狀態(tài)的溫濕度探測(cè),然后使用手捏住 DHT11,溫度升高超過“閾值”后,LED 小燈就變成“閃爍”狀態(tài)了。
還有問題嗎?
上面的控制程序還不是很完美,相信細(xì)心的朋友應(yīng)該看出來了,LED小燈處于“呼吸”狀態(tài)時(shí),總是會(huì)有一次閃爍。這是因?yàn)槲覀儾杉?DHT11 傳回來的溫濕度信息時(shí),也有幾十毫秒的延時(shí),在這段時(shí)間內(nèi),單片機(jī)是無法控制 LED 小燈的溫濕度探測(cè),所以小燈會(huì)一直處于最近一次的亮暗狀態(tài),查看 led_twinkle_1s() 函數(shù)的C語言代碼就知道,LED 小燈最后的狀態(tài)是亮的狀態(tài),這就解釋了我們遇到的問題。
這其實(shí)也是單片機(jī)編程的一個(gè)特點(diǎn)溫濕度探測(cè),若單片機(jī)內(nèi)部沒有運(yùn)行操作系統(tǒng),則編寫并行的程序幾乎是不可能的,所以串行的阻塞延時(shí)應(yīng)該盡量避免,否則就會(huì)出現(xiàn)類似上面的問題。那么,上面這種問題不借助于操作系統(tǒng)也能解決嗎?當(dāng)然可以,借助于單片機(jī)的中斷系統(tǒng)就很好解決,限于篇幅,以后再說了。
歡迎在評(píng)論區(qū)一起討論,質(zhì)疑。文章都是手打原創(chuàng),每天最淺顯的介紹C語言、linux等嵌入式開發(fā),喜歡我的文章就關(guān)注一波吧,可以看到最新更新和之前的文章哦。
騰元達(dá)編輯,轉(zhuǎn)載請(qǐng)注明出處
- 2023-09-17
什么環(huán)境需要安裝氧氣檢測(cè)儀?有什么作用? - 2023-09-10
垃圾填埋場(chǎng)有毒有害氣體如何防范? - 2023-09-10
常見有毒有害氣體以及如何防范? - 2023-09-10
固定式可燃?xì)怏w探測(cè)器一般用什么氣體標(biāo)定 - 2023-08-19
密閉空間如何選擇氣體檢測(cè)儀? - 2021-09-08
二氧化氮探測(cè)器 二氧化氮NO2傳感器 - 2021-09-08
pm2.5檢測(cè)儀 歡迎##簡陽PM2.5揚(yáng)塵監(jiān)測(cè)系統(tǒng)環(huán)境檢測(cè)儀##集團(tuán) - 2021-09-08
在線式二氧化碳檢測(cè)儀 - 2021-09-08
噪音檢測(cè)儀 噪聲檢測(cè)儀哪個(gè)品牌好? - 2021-09-08
pm2.5檢測(cè)儀 云南玉溪 揚(yáng)塵監(jiān)測(cè)PM10監(jiān)測(cè)PM2.5監(jiān)測(cè)TSP檢測(cè)儀揚(yáng)塵監(jiān)測(cè)儀