一、設(shè)計(jì)要求
本次課設(shè)要求學(xué)生們掌握四個(gè)方面,第一是文獻(xiàn)檢索及實(shí)驗(yàn)研究方法,第二是室內(nèi)環(huán)境監(jiān)控系統(tǒng)一般組成; 第三是掌握技術(shù)方案比選方法;最后是掌握STM32 ADC使用,同時(shí)本次課設(shè)需要做到以下幾個(gè)方面:
- 了解國內(nèi)室內(nèi)環(huán)境參數(shù)監(jiān)控系統(tǒng)組成及技術(shù)架構(gòu);
- 設(shè)計(jì)室內(nèi)環(huán)境參數(shù)監(jiān)控系統(tǒng),要求至少采集溫度及光照,完成環(huán)境參數(shù)傳感器選型;
- 基于開發(fā)板或其他32位微控制器及所選用的傳感器設(shè)計(jì)一個(gè)室內(nèi)環(huán)境參數(shù)采集終端,實(shí)現(xiàn)至少一路溫度、光照強(qiáng)度數(shù)據(jù)采集;
- 設(shè)置溫度和光照門限,當(dāng)溫度高于門限值時(shí)蜂鳴器報(bào)警,當(dāng)光照強(qiáng)度高于及低于門限值時(shí)控制LED燈亮度以實(shí)現(xiàn)光照調(diào)節(jié)(也可自行設(shè)計(jì)亮度調(diào)節(jié)方式)。
- 將采集到的溫度和光照強(qiáng)度數(shù)據(jù)顯示到LCD屏上;
二、設(shè)計(jì)原理
- 硬件設(shè)計(jì)
- 采用STM32F103ZET6單片機(jī)作為主控芯片,具有較強(qiáng)的處理能力,且具有低功耗、低成本等特點(diǎn),可以實(shí)現(xiàn)室內(nèi)環(huán)境參數(shù)監(jiān)控的多種復(fù)雜操作;
- 采用DHT11溫濕度傳感器,可以實(shí)時(shí)檢測室內(nèi)溫度和濕度;
- 采用光強(qiáng)傳感器,可以檢測室內(nèi)光照強(qiáng)度參數(shù);
- 采用LCD顯示屏,可以顯示室內(nèi)環(huán)境參數(shù)的實(shí)時(shí)數(shù)據(jù);
- 采用LED燈,可以模擬補(bǔ)光操作;
- 采用蜂鳴器,可以實(shí)現(xiàn)報(bào)警功能。
- 軟件設(shè)計(jì)
- 采用C語言編寫程序,實(shí)現(xiàn)對傳感器參數(shù)的采集、處理以及參數(shù)的顯示;
- 采用報(bào)警功能,當(dāng)室內(nèi)溫度參數(shù)超出設(shè)定范圍時(shí),可以發(fā)出警報(bào)信號;
- 采用室內(nèi)光照強(qiáng)度實(shí)時(shí)調(diào)節(jié),根據(jù)室內(nèi)光照強(qiáng)度參數(shù)實(shí)時(shí)調(diào)節(jié)以達(dá)到適合工作、學(xué)習(xí)的平衡狀態(tài)。
三、設(shè)計(jì)方案
1硬件設(shè)計(jì)
1.1硬件系統(tǒng)框圖
?文章來源地址http://www.zghlxwxcb.cn/news/detail-801020.html
1.2主控芯片模塊(STM32F103ZET6)
?
STM32F103ZET6芯片的主要特性如下:
- 集成了32位的ARM Cortex-M3內(nèi)核,最高工作頻率可達(dá)72MHZ,計(jì)算能力 ???為1.25DMIPS,具有單周期乘法指令和硬件除法器;
- 具有512KB片內(nèi)Flash存儲器和64KB片內(nèi)片內(nèi)SARM存儲器;
- 內(nèi)部集成了8MHZ晶體振蕩電路器,可外接416MHZ的時(shí)鐘源;
- 2.0-3.0V單一供電源,具有上電復(fù)位功能;
- 具有睡眠、停止、待機(jī)三種低功耗工作模式;
- 144個(gè)引腳LQFP封裝;
- 內(nèi)部集成了11個(gè)定時(shí)器:4個(gè)16位通用定時(shí)器,2個(gè)16位定時(shí)器可產(chǎn)生的PWM波控制電機(jī)的定時(shí)器,2個(gè)16位的可驅(qū)動DAC的定時(shí)器,2個(gè)加窗口的看門狗定時(shí)器和1 個(gè)24位的系統(tǒng)節(jié)拍定時(shí)器;
- 2個(gè)12位的DAC和3個(gè)12位的ADC;
- 集成了內(nèi)部溫度傳感和實(shí)時(shí)時(shí)鐘RTC;
- 具有112根高速通用輸入輸出口,可從其中任選16根作為外部中斷輸入口,幾乎全部GPIO口可承受5V輸入(PA0~PA7,PB0~PB1,PC0~PC5,PC13~PC15和PF6~PF10除外);
- 集成了13個(gè)外部通信接口:2個(gè)12C、3個(gè)SPI、1個(gè)CAN、5個(gè)UART、5個(gè)UART、1個(gè)USB2.0設(shè)備和1個(gè)并行SDIO;
- 具有12通道的DMA控制器,支持定時(shí)器、ADC、DAC、SDIO、12S、SPI、12C和UART外設(shè);
- 具有96位的全球唯一編號;
- 工作溫度-40~85℃;??
1.3電源電路模塊
1.4復(fù)位電路模塊
? ? ? ?可實(shí)現(xiàn)上電復(fù)位和按鍵復(fù)位,開發(fā)板接通電源時(shí),復(fù)位持續(xù)時(shí)間由R2電阻值C10容值乘積決定,一般情況下電阻值取10k電容值取10uf可以滿足復(fù)位要求,按鈕RESET可以實(shí)現(xiàn)按鍵復(fù)位,當(dāng)需要復(fù)位時(shí)按下RESET按鈕,RESET引腳直接接地,CPU進(jìn)入復(fù)位狀態(tài)。?
1.5時(shí)鐘電路模塊
?
從上圖可以看出三種不同的時(shí)鐘源可被用來驅(qū)動系統(tǒng)時(shí)鐘(SYSCLK):
(1)HSI振蕩器時(shí)鐘
(2)HSE振蕩器時(shí)鐘
(3)PLL時(shí)鐘
這些設(shè)備有以下2種二級時(shí)鐘源:
(1)40kHz低速內(nèi)部RC,可以用于驅(qū)動獨(dú)立看門狗和通過程序選擇驅(qū)動RTC。RTC用于從停機(jī)/ 待機(jī)模式下自動喚醒系統(tǒng)。
(2)32.768kHz低速外部晶體也可用來通過程序選擇驅(qū)動RTC(RTCCLK)。
當(dāng)不被使用時(shí),任一個(gè)時(shí)鐘源都可被獨(dú)立地啟動或關(guān)閉,由此優(yōu)化系統(tǒng)功耗。
1.6DHT11溫濕度傳感器模塊
? ? ? ?DHT11是一款溫濕度一體化的數(shù)字傳感器。該傳感器包括一個(gè)電容式測濕元件和一個(gè) NTC測溫元件,并與一個(gè)高性能 8 位單片機(jī)相連接。通過單片機(jī)等微處理器簡單的電路連接就能夠?qū)崟r(shí)的采集本地濕度和溫度。DHT11與單片機(jī)之間能采用簡單的單總線進(jìn)行通信,僅僅需要一個(gè)I/O口。傳感器內(nèi)部濕度和溫度數(shù)據(jù)40Bit的數(shù)據(jù)一次性傳給單片機(jī),數(shù)據(jù)采用校驗(yàn)和方式進(jìn)行校驗(yàn),有效的保證數(shù)據(jù)傳輸?shù)臏?zhǔn)確性。DHT11功耗很低,5V 源電壓下,工作平均最大電流0.5mA。
1.7光強(qiáng)傳感器模塊
?圖中,LSI為光敏二極管,外觀看起來與貼片LED類似(位于OLED插座旁邊,LSI)R34為其提供反向電壓,當(dāng)環(huán)境光線發(fā)生變化時(shí),LSI兩端的電壓也會隨之改變,通過ADC3_IN6通道獲取LIGHT_SENSOR(PF8)上面的電壓,即可得到環(huán)境光線的強(qiáng)弱,光線越強(qiáng),電壓越低,光線越弱,電壓越高。
1.8TFT_LCD顯示模塊
FTLCD 模塊采用 2*17 的 2.54 公排針與外部連接,即圖中 TFT_LCD 部分。從圖 1.8.1可以看出,正點(diǎn)原子 TFTLCD 模塊采用 16 位的并口方式與外部連接。該模塊與顯示功能的相關(guān)信號線如表 1.8.2:
?
?1.9LED照明補(bǔ)光模塊
?1.10蜂鳴器報(bào)警模塊
開發(fā)板配置了一個(gè)無源蜂鳴器BEEP作為系統(tǒng)報(bào)警使用,由PNP三極管Q1控制其導(dǎo)通或關(guān)閉,加兩個(gè)電阻實(shí)現(xiàn)當(dāng)管腳輸出3.3V電平時(shí)才能發(fā)生,且防止由于外部干擾導(dǎo)致的誤發(fā)聲。
- 軟件設(shè)計(jì)
- DHT11傳感器溫濕度采集
- 程序設(shè)計(jì)
- DHT11傳感器溫濕度采集
DHT11實(shí)驗(yàn)中使用的是單總線協(xié)議,用到的是庫函數(shù)中 GPIO 相關(guān)函數(shù)。
DHT11配置步驟 :
(1)使能DHT11數(shù)據(jù)線對應(yīng)的GPIO時(shí)鐘。 本實(shí)驗(yàn)中DHT11的數(shù)據(jù)線引腳是PG11,因此需要先使能 GPIOG 的時(shí)鐘;
(2)設(shè)置對應(yīng) GPIO 工作模式(開漏輸出),本實(shí)驗(yàn) GPIO 使用開漏輸出模式;
(3)參考單總線協(xié)議,編寫信號代碼:
- DHT11開始發(fā)送數(shù)據(jù)流程
主機(jī)發(fā)送開始信號后,延時(shí)等待 20us-40us 后讀取 DH11T 的回應(yīng)信號,讀取總線為低電平,說明 DHT11 發(fā)送響應(yīng)信號,DHT11 發(fā)送響應(yīng)信號后,再把總線拉高,準(zhǔn)備發(fā)送數(shù)據(jù),每一 bit 數(shù)據(jù)都以低電平開始,格式見下面圖示。如果讀取響應(yīng)信號為高電平,則 DHT11 沒有響應(yīng),請檢查線路是否連接正常。主機(jī)復(fù)位信號和DHT11響應(yīng)信號
(4)編寫 DHT11的讀函數(shù) ,基于讀1bit數(shù)據(jù)的基礎(chǔ)上,編寫 DHT11 讀1字節(jié)函數(shù)。
(5)編寫DHT11獲取溫度函數(shù), 參考 DHT11典型溫濕度讀取過程,編寫獲取溫濕度函數(shù)。
2.1.2程序流程圖
本實(shí)驗(yàn)開機(jī)的時(shí)候先檢測是否有 DHT1 1存在,如果沒有,則提示錯(cuò)誤。只有在檢測到 DHT11之后才開始讀取溫濕度值并顯示在 LCD 上,如果發(fā)現(xiàn)了 DHT1 1,則程序每隔 100ms 左右讀取一次數(shù)據(jù),并把溫濕度顯示在 LCD 上。 LED0 閃爍用于提示程序正在運(yùn)行。
2.1.3程序代碼
//復(fù)位DHT11
void DHT11_Rst(void)
{
DHT11_IO_OUT(); //SET OUTPUT
DHT11_DQ_OUT=0; //拉低DQ
delay_ms(20); //拉低至少18ms
DHT11_DQ_OUT=1; //DQ=1
delay_us(30); //主機(jī)拉高20~40us
}
//等待DHT11的回應(yīng)
//返回1:未檢測到DHT11的存在
//返回0:存在
u8 DHT11_Check(void)
{
u8 retry=0;
DHT11_IO_IN();//SET INPUT
while (DHT11_DQ_IN&&retry<100)//DHT11會拉低40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
else retry=0;
while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后會再次拉高40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
return 0;
}
//從DHT11讀取一個(gè)位
//返回值:1/0
u8 DHT11_Read_Bit(void)
{
u8 retry=0;
while(DHT11_DQ_IN&&retry<100)//等待變?yōu)榈碗娖? {
retry++;
delay_us(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry<100)//等待變高電平
{
retry++;
delay_us(1);
}
delay_us(40);//等待40us
if(DHT11_DQ_IN)return 1;
else return 0;
}
//從DHT11讀取一個(gè)字節(jié)
//返回值:讀到的數(shù)據(jù)
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//從DHT11讀取一次數(shù)據(jù)
//temp:溫度值(范圍:0~50°),humi:濕度值(范圍:20%~90%)
u8 DHT11_Read_Data(u8 *temp,u8 *humi)
{
u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//讀取40位數(shù)據(jù)
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}
}else return 1;
return 0;
}
//初始化DHT11的IO口 DQ 同時(shí)檢測DHT11的存在
u8 DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PG端口時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PG11端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOG, &GPIO_InitStructure); //初始化IO口
GPIO_SetBits(GPIOG,GPIO_Pin_11); //PG11 輸出高
DHT11_Rst(); //復(fù)位DHT11
return DHT11_Check();//等待DHT11的回應(yīng)
}
?
- 2光照強(qiáng)度采集
- 1程序設(shè)計(jì)
通過 ADC3_CH6通道讀取 LIGHT_SENSOR(PF8)上面的電壓,即可得到環(huán)境光線的強(qiáng)弱。光線越強(qiáng),電壓越低,光線越暗,電壓越高。
- 1.2
- 程序流程圖
通過 ADC3 的通道 6(PF8)讀取光敏傳感器(LS1)的電壓值,并轉(zhuǎn)換為 0~100 的光線強(qiáng)度值,顯示在 LCD 模塊上面。光線越亮,值越大;光線越暗,值越小。大家可以用手指遮擋 LS1和用手電筒照射 LS1,來查看光強(qiáng)變化。 LED0 閃爍用于提示程序正在運(yùn)行。
-
.2.3程序代碼
//初始化光敏傳感器 void Lsens_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);//使能PORTF時(shí)鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;//PF8 anolog輸入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入引腳 GPIO_Init(GPIOF, &GPIO_InitStructure); Adc3_Init(); } //讀取Light Sens的值 //0~100:0,最暗;100,最亮 u8 Lsens_Get_Val(void) { u32 temp_val=0; u8 t;//讀取次數(shù) for(t=0;t<LSENS_READ_TIMES;t++) { temp_val+=Get_Adc3(LSENS_ADC_CHX); //讀取ADC值 delay_ms(5); } temp_val/=LSENS_READ_TIMES;//得到平均值 if(temp_val>4000)temp_val=4000; return (u8)(100-(temp_val/40)); }
?
- ADC模數(shù)轉(zhuǎn)換
- 程序設(shè)計(jì)
- ADC模塊采集的是光敏電阻兩端的電壓值,電壓屬于模擬信息需轉(zhuǎn)化為數(shù)字信息,只有這樣才能的處理數(shù)據(jù)從而完成光照強(qiáng)度的監(jiān)控。
- 代碼
//初始化ADC3 //這里我們僅以規(guī)則通道為例 //我們默認(rèn)僅開啟通道6 void Adc3_Init(void) { ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3 , ENABLE ); //使能ADC3通道時(shí)鐘 RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE);//ADC復(fù)位 RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE);//復(fù)位結(jié)束 ADC_DeInit(ADC3); //復(fù)位ADC3,將外設(shè) ADC3的全部寄存器重設(shè)為缺省值 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式: 獨(dú)立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模數(shù)轉(zhuǎn)換工作在單通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模數(shù)轉(zhuǎn)換工作在單次轉(zhuǎn)換模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //轉(zhuǎn)換由軟件而不是外部觸發(fā)啟動 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC數(shù)據(jù)右對齊 ADC_InitStructure.ADC_NbrOfChannel = 1; //順序進(jìn)行規(guī)則轉(zhuǎn)換的ADC通道的數(shù)目 ADC_Init(ADC3, &ADC_InitStructure); //根據(jù)ADC_InitStruct中指定的參數(shù)初始化外設(shè)ADCx的寄存器 ADC_Cmd(ADC3, ENABLE); //使能指定的ADC3 ADC_ResetCalibration(ADC3); //使能復(fù)位校準(zhǔn) while(ADC_GetResetCalibrationStatus(ADC3)); //等待復(fù)位校準(zhǔn)結(jié)束 ADC_StartCalibration(ADC3); //開啟AD校準(zhǔn) while(ADC_GetCalibrationStatus(ADC3)); //等待校準(zhǔn)結(jié)束 } //獲得ADC3_ch6通道的值 u16 Get_Adc3(u8 ch) { //設(shè)置指定ADC的規(guī)則組通道,一個(gè)序列,采樣時(shí)間 ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC3,ADC通道,采樣時(shí)間為239.5周期 ADC_SoftwareStartConvCmd(ADC3, ENABLE); //使能指定的ADC3的軟件轉(zhuǎn)換啟動功能 while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC ));//等待轉(zhuǎn)換結(jié)束 return ADC_GetConversionValue(ADC3); //返回最近一次ADC3規(guī)則組的轉(zhuǎn)換結(jié)果 }
3.TFT_LCD顯示代碼
//初始化lcd void LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef readWriteTiming; FSMC_NORSRAMTimingInitTypeDef writeTiming; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE); //使能FSMC時(shí)鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOG,ENABLE); //使能PORTB,D,E,G以及AFIO復(fù)用功能時(shí)鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PB0 推挽輸出 背光 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //PORTD復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_14|GPIO_Pin_15; //PORTD復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); //PORTE復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; //PORTE復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStructure); //PORTG12復(fù)用推挽輸出 P0RTG0-->RS GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_12; //PORTD復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOG, &GPIO_InitStructure); //LCD開啟顯示 void LCD_DisplayOn(void) { if (lcddev.id == 0X5510) //5510開啟顯示指令 { LCD_WR_REG(0X2900); //開啟顯示 } else //9341/5310/1963/7789 等發(fā)送開啟顯示指令 { LCD_WR_REG(0X29); //開啟顯示 } } //LCD關(guān)閉顯示 void LCD_DisplayOff(void) { if (lcddev.id == 0X5510) //5510關(guān)閉顯示指令 { LCD_WR_REG(0X2800); //關(guān)閉顯示 } else //9341/5310/1963/7789 等發(fā)送關(guān)閉顯示指令 { LCD_WR_REG(0X28); //關(guān)閉顯示 } } //清屏函數(shù) //color:要清屏的填充色 void LCD_Clear(u16 color) { u32 index = 0; u32 totalpoint = lcddev.width; totalpoint *= lcddev.height; //得到總點(diǎn)數(shù) LCD_SetCursor(0x00, 0x0000); //設(shè)置光標(biāo)位置 LCD_WriteRAM_Prepare(); //開始寫入GRAM for (index = 0; index < totalpoint; index++) { LCD->LCD_RAM=color; } } //在指定區(qū)域內(nèi)填充指定顏色 //區(qū)域大小:(xend-xsta+1)*(yend-ysta+1) //xsta //color:要填充的顏色 void LCD_Fill(u16 sx, u16 sy, u16 ex, u16 ey, u16 color) { u16 i, j; u16 xlen = 0; xlen = ex - sx + 1; for (i = sy; i <= ey; i++) { LCD_SetCursor(sx, i); //設(shè)置光標(biāo)位置 LCD_WriteRAM_Prepare(); //開始寫入GRAM for (j = 0; j < xlen; j++) { LCD->LCD_RAM=color; //設(shè)置光標(biāo)位置 } } } //在指定區(qū)域內(nèi)填充指定顏色塊 //(sx,sy),(ex,ey):填充矩形對角坐標(biāo),區(qū)域大小為:(ex-sx+1)*(ey-sy+1) //color:要填充的顏色 void LCD_Color_Fill(u16 sx, u16 sy, u16 ex, u16 ey, u16 *color) { u16 height, width; u16 i, j; width = ex - sx + 1; //得到填充的寬度 height = ey - sy + 1; //高度 for (i = 0; i < height; i++) { LCD_SetCursor(sx, sy + i); //設(shè)置光標(biāo)位置 LCD_WriteRAM_Prepare(); //開始寫入GRAM for (j = 0; j < width; j++) { LCD->LCD_RAM=color[i * width + j]; //寫入數(shù)據(jù) } } } //在指定位置顯示一個(gè)字符 //x,y:起始坐標(biāo) //num:要顯示的字符:" "--->"~" //size:字體大小 12/16/24 //mode:疊加方式(1)還是非疊加方式(0) void LCD_ShowChar(u16 x, u16 y, u8 num, u8 size, u8 mode) { u8 temp, t1, t; u16 y0 = y; u8 csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2); //得到字體一個(gè)字符對應(yīng)點(diǎn)陣集所占的字節(jié)數(shù) num = num - ' '; //得到偏移后的值(ASCII字庫是從空格開始取模,所以-' '就是對應(yīng)字符的字庫) for (t = 0; t < csize; t++) { if (size == 12)temp = asc2_1206[num][t]; //調(diào)用1206字體 else if (size == 16)temp = asc2_1608[num][t]; //調(diào)用1608字體 else if (size == 24)temp = asc2_2412[num][t]; //調(diào)用2412字體 else return; //沒有的字庫 for (t1 = 0; t1 < 8; t1++) { if (temp & 0x80)LCD_Fast_DrawPoint(x, y, POINT_COLOR); else if (mode == 0)LCD_Fast_DrawPoint(x, y, BACK_COLOR); temp <<= 1; y++; if (y >= lcddev.height)return; //超區(qū)域了 if ((y - y0) == size) { y = y0; x++; if (x >= lcddev.width)return; //超區(qū)域了 break; } } } } //m^n函數(shù) //返回值:m^n次方. u32 LCD_Pow(u8 m, u8 n) { u32 result = 1; while (n--)result *= m; return result; } //顯示數(shù)字,高位為0,則不顯示 //x,y :起點(diǎn)坐標(biāo) //len :數(shù)字的位數(shù) //size:字體大小 //color:顏色 //num:數(shù)值(0~4294967295); void LCD_ShowNum(u16 x, u16 y, u32 num, u8 len, u8 size) { u8 t, temp; u8 enshow = 0; for (t = 0; t < len; t++) { temp = (num / LCD_Pow(10, len - t - 1)) % 10; if (enshow == 0 && t < (len - 1)) { if (temp == 0) { LCD_ShowChar(x + (size / 2)*t, y, ' ', size, 0); continue; } else enshow = 1; } LCD_ShowChar(x + (size / 2)*t, y, temp + '0', size, 0); } } //顯示數(shù)字,高位為0,還是顯示 //x,y:起點(diǎn)坐標(biāo) //num:數(shù)值(0~999999999); //len:長度(即要顯示的位數(shù)) //size:字體大小 //mode: //[7]:0,不填充;1,填充0. //[6:1]:保留 //[0]:0,非疊加顯示;1,疊加顯示. void LCD_ShowxNum(u16 x, u16 y, u32 num, u8 len, u8 size, u8 mode) { u8 t, temp; u8 enshow = 0; for (t = 0; t < len; t++) { temp = (num / LCD_Pow(10, len - t - 1)) % 10; if (enshow == 0 && t < (len - 1)) { if (temp == 0) { if (mode & 0X80)LCD_ShowChar(x + (size / 2)*t, y, '0', size, mode & 0X01); else LCD_ShowChar(x + (size / 2)*t, y, ' ', size, mode & 0X01); continue; } else enshow = 1; } LCD_ShowChar(x + (size / 2)*t, y, temp + '0', size, mode & 0X01); } } //顯示字符串 //x,y:起點(diǎn)坐標(biāo) //width,height:區(qū)域大小 //size:字體大小 //*p:字符串起始地址 void LCD_ShowString(u16 x, u16 y, u16 width, u16 height, u8 size, u8 *p) { u8 x0 = x; width += x; height += y; while ((*p <= '~') && (*p >= ' ')) //判斷是不是非法字符! { if (x >= width) { x = x0; y += size; } if (y >= height)break; //退出 LCD_ShowChar(x, y, *p, size, 0); x += size / 2; p++; } }
2.5蜂鳴器報(bào)警代碼
void BEEP_Init(void)//BEEP初始化 { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口時(shí)鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;//beep->PB8端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//端口模式配置 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//端口速率配置 GPIO_Init(GPIOB,&GPIO_InitStructure);//根據(jù)參數(shù)初始化GPIOB_Pin8 GPIO_ResetBits(GPIOB,GPIO_Pin_8);//初始時(shí)端口配置為低電平 } if(temperature>=34) { BEEP=1; }
2.6LED照明補(bǔ)光程序代碼
//TIM3 PWM部分初始化 //PWM輸出初始化 //arr:自動重裝值 //psc:時(shí)鐘預(yù)分頻數(shù) void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定時(shí)器3時(shí)鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能GPIOE外設(shè)和AFIO復(fù)用功能模塊時(shí)鐘 //設(shè)置該引腳為復(fù)用輸出功能,輸出TIM3 CH2的PWM脈沖波形 GPIOA.7 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO //初始化TIM3 TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動的自動重裝載寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位 //初始化TIM3 Channel2 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時(shí)器模式:TIM脈沖寬度調(diào)制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高 TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM3 OC2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的預(yù)裝載寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3 }
三、主程序
int main(void) { u8 adcx;//光照強(qiáng)度 u8 t=0; u8 temperature;//溫度 u8 humidity; //濕度 u16 led1pwmval; //PWN輸出的占空比 delay_init(); //延時(shí)函數(shù)初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置中斷優(yōu)先級分組為組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級 uart_init(115200); //串口初始化為115200 LED_Init(); //初始化與LED連接的硬件接口 BEEP_Init(); //初始化BEEP LCD_Init(); //初始化LCD Lsens_Init(); //初始化光敏傳感器 TIM3_PWM_Init(899,0); //不分頻。PWM頻率=72000000/900=80Khz POINT_COLOR=RED;//設(shè)置字體為紅色 //顯示提示信息 LCD_ShowString(30,50,200,16,16,"Based On STM32"); LCD_ShowString(30,70,200,16,16,"DHT11_LSENS MONITORING"); LCD_ShowString(30,90,200,16,16,"Copyright GROUP1"); LCD_ShowString(30,110,200,16,16,"2022/12/25"); while(DHT11_Init()) //DHT11初始化 { LCD_ShowString(30,130,200,16,16,"DHT11 Error"); delay_ms(200); LCD_Fill(30,130,239,130+16,WHITE); delay_ms(200); } LCD_ShowString(30,130,200,16,16,"DHT11 OK"); POINT_COLOR=BLUE;//設(shè)置字體為藍(lán)色 LCD_ShowString(30,170,200,16,16,"LSENS_VAL:"); LCD_ShowString(30,190,200,16,16,"Temp: C"); LCD_ShowString(30,210,200,16,16,"Humi: %"); while(1) { adcx=Lsens_Get_Val(); LCD_ShowxNum(30+10*8,170,adcx,3,16,0);//顯示ADC的值 if(t%10==0) //每100ms讀取一次 { DHT11_Read_Data(&temperature,&humidity); //讀取溫濕度值 LCD_ShowNum(30+40,190,temperature,2,16); //顯示溫度 LCD_ShowNum(30+40,210,humidity,2,16); //顯示濕度 } delay_ms(10); t++; if(temperature>=34) { BEEP=1; } led1pwmval=(100-adcx)/10;//根據(jù)光照強(qiáng)度實(shí)時(shí)調(diào)整LED1的亮度 TIM_SetCompare2(TIM3,led1pwmval);} }
四、測試
-
? ? ? 項(xiàng)目文件編譯并下載到單片機(jī)后上電,LCD屏上可以清晰顯示當(dāng)前測試環(huán)境的溫度、濕度和光照強(qiáng)度。?
-
通過上面兩圖的對比,未外加燈光時(shí)光照強(qiáng)度為7,LED1很亮;當(dāng)外加燈光時(shí),光照強(qiáng)度為93,LED1微亮或者熄滅。
-
?
測試時(shí)室溫為14攝氏度,當(dāng)設(shè)置溫度報(bào)警上限為10攝氏度時(shí),可以聽到蜂鳴器發(fā)出聲音報(bào)警。?文章來源:http://www.zghlxwxcb.cn/news/detail-801020.html
?
到了這里,關(guān)于嵌入式室內(nèi)環(huán)境參數(shù)監(jiān)控系統(tǒng)設(shè)計(jì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!