一.实验任务
用DS18B20实现环境温度的采集,并输出到数码管进行显示,当监测到的温度超过设定温度时用蜂鸣器进行报警。
二.硬件设计和原理
接线图:
蜂鸣器的硬件设计原理
蜂鸣器通常可分为有源蜂鸣器和无源蜂鸣器,无源蜂鸣器需要输出类似方波的波形来控制蜂鸣器发生,而有源蜂鸣器通上电源即可发出声音,具体的原理如下图:
我们这里用的蜂鸣器就是有源蜂鸣器,其相关的控制电路原理如下图所示:
这里用到的蜂鸣器原理是右侧的低电平触发,也即当控制蜂鸣器的引脚PA15设置为低电平时,蜂鸣器发出声音,当控制蜂鸣器的引脚PA15设置为高电平的时候蜂鸣器不发生,关闭。因此在初始化配置蜂鸣器的引脚的时候,为了初始化之后蜂鸣器不发声,需要把控制蜂鸣器的引脚PA15初始化设置为高电平。当需要控制蜂鸣器发声的时候,只需要设置控制引脚为低电平即可。硬件的连接接线如下图所示:
板载温度传感器的硬件设计原理:
温度传感器有数字量的也有模拟量的,模拟量的又分负温度系数的和正温度系数的,所谓的正负就是温度和电阻的关系,负温度系数是当温度升高的时候传感器的电阻值是变小的,正温度系数是当温度升高的时候传感器的电阻值是变大的,通常用到的有PT100和PT1000。详情如下图所示:
进行温度采集设计电路设计的时候,通常有两种:一种是电压源,一种是电流源,通常用到的是电压源,当采用电压源的时候电路也有两种,一种是温度传感器接到电压源的一端,一种是温度传感器接到地的一端,后一种偏多。具体如下图所示:
在这里我们可以使用开发板上温度传感器进行温度的开发验证测试,相关硬件介绍如下图所示:
板载温度采集的设计原理为温度变化转化为阻值变化,然后转化为电压变化,根据电压电阻的比例关系,可以计算出温度传感器上的电压V=VCC*R126/(R125+R126),具体的硬件原理如下图所示
根据温度采集的电压和温度传感器的温度电阻曲线,以及曲线的计算公式可以计算出对应的温度值,具体的计算详情如下图所示:
对于温度传感器DS18B20模块的硬件设计原理,相关的模块硬件连接接线如下图所示:
三.软件开发设计实现
1.配置syscfg参数2.重要源代码
(1)基础代码:蜂鸣器、数码管配置和相关参数。
#define DS18B20_DQ_IN_Read() DL_GPIO_readPins(PORT_TempSensor_PORT,PORT_TempSensor_PIN_TempSensor_PIN) #define delay_us 32 #define NUM_MAXLENGTH 8 uint8_t Num_List[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf};//数码管数字 volatile float temp=0.0; uint8_t Reserved_points=4; uint8_t temp_level[]={28,29};
(2)配置温度传感器。
void DS18B20_OneWireRisingEdge_Config(GPIO_Regs* PORTx,uint32_t PINx,uint32_t t1,uint32_t t2){ DL_GPIO_clearPins(PORTx, PINx); delay_cycles(delay_us*t1); DL_GPIO_setPins(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN); delay_cycles(delay_us*t2); } void DS18B20_DQ_IN() { DL_GPIO_disableOutput(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN); DL_GPIO_initDigitalInput(PORT_TempSensor_PIN_TempSensor_IOMUX); DL_GPIO_setPins(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN); DL_GPIO_enableOutput(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN); } void DS18B20_DQ_OUT() { DL_GPIO_disableOutput(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN); DL_GPIO_initDigitalOutput(PORT_TempSensor_PIN_TempSensor_IOMUX); DL_GPIO_setPins(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN); DL_GPIO_enableOutput(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN); } void DS18B20_RESET() { DS18B20_DQ_OUT(); DS18B20_OneWireRisingEdge_Config(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN,750,60); } uint8_t DS18B20_CHECK() { uint8_t counters=0; DS18B20_DQ_IN(); while(DS18B20_DQ_IN_Read()&&counters<200){ counters++; delay_cycles(delay_us*1); } if(counters>100) return 1; else counters=0; while(!(DS18B20_DQ_IN_Read())&&counters<240){ counters++; delay_cycles(delay_us*1); } if(counters>240) return 2; else return 0; } void DS18B20_WRITE_Byte(uint8_t data) { uint8_t byte=data; DS18B20_DQ_OUT(); for(uint8_t i=1;i<=8;i++){ if(byte&0x01){ DS18B20_OneWireRisingEdge_Config(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN,2,60); } else{ DS18B20_OneWireRisingEdge_Config(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN,60,2); } byte=byte>>1; } } uint8_t DS18B20_READ_Bit() { uint8_t bit; DS18B20_DQ_OUT(); DS18B20_OneWireRisingEdge_Config(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN,2,5); DS18B20_DQ_IN(); delay_cycles(delay_us*12); if(DS18B20_DQ_IN_Read()) bit=1; else bit=0; delay_cycles(delay_us*50); return bit; } uint8_t DS18B20_READ_Byte() { uint8_t bit=0; uint8_t byte=0; for(uint8_t i=1;i<=8;i++){ bit=DS18B20_READ_Bit(); byte|=bit<<(i-1); } return byte; } void DS18B20_START(void){ DS18B20_RESET(); DS18B20_CHECK(); DS18B20_WRITE_Byte(0xcc); DS18B20_WRITE_Byte(0x44); DS18B20_RESET(); DS18B20_CHECK(); DS18B20_WRITE_Byte(0xcc); DS18B20_WRITE_Byte(0xbe); } uint8_t DS18B20_INIT(void) { DS18B20_RESET(); return DS18B20_CHECK(); } float DS18B20_GetTemp(void) { float temp_value=0.0; uint8_t temp_msb,temp_lsb=0; uint16_t temp=0; DS18B20_START(); temp_lsb=DS18B20_READ_Byte(); temp_msb=DS18B20_READ_Byte(); temp=(temp_msb<<8)+temp_lsb; if((temp&0xF800)==0xF800) { temp=(~temp)+1; temp_value=temp*(-0.0625); } else temp_value=temp*0.0625; return temp_value; }
(3)配置数码管输出
void HC595_CLKRisingEdge_Config(GPIO_Regs* PORTx,uint32_t PINx,uint32_t t1,uint32_t t2) { DL_GPIO_clearPins(PORTx, PINx); delay_cycles(delay_us*t1); DL_GPIO_setPins(PORTx, PINx); delay_cycles(delay_us*t2); } void LED_Segment_WriteByte(uint8_t byte) { for(uint8_t i=1;i<=8;i++){ if(byte&0x80){ DL_GPIO_setPins(PORT_HC595_PORT,PORT_HC595_PIN_HC595_DIO_PIN); } else { DL_GPIO_clearPins(PORT_HC595_PORT,PORT_HC595_PIN_HC595_DIO_PIN); } HC595_CLKRisingEdge_Config(PORT_HC595_PORT,PORT_HC595_PIN_HC595_SCLK_PIN,2,2); byte<<=1; } } void LED_Segment_Display_Num_One(uint8_t Num_one,uint8_t index) { LED_Segment_WriteByte(Num_List[Num_one]); LED_Segment_WriteByte(1<<index); HC595_CLKRisingEdge_Config(PORT_HC595_PORT,PORT_HC595_PIN_HC595_RCLK_PIN,2,2); } void LED_Segment_Display_point(uint8_t Num_one,uint8_t index) { LED_Segment_WriteByte(Num_one); LED_Segment_WriteByte(1<<index); HC595_CLKRisingEdge_Config(PORT_HC595_PORT,PORT_HC595_PIN_HC595_RCLK_PIN,2,2); } void Num_LED_Segment_Process(uint32_t Num) { uint8_t num_lsb=0; uint8_t i; for(i=0;i<NUM_MAXLENGTH;i++) { num_lsb=Num%10; Num/=10; LED_Segment_Display_Num_One(num_lsb,i); if(Num==0)break; } } void Num_LED_Segment_Process_Float(float Num,uint8_t Reserved_points) { int Num_int=Num*pow(10,Reserved_points+1); if(Num_int%10>=5) Num_int=Num_int/10+1; else Num_int=Num_int/10; if(Reserved_points==0) Num_LED_Segment_Process(Num_int); else { Num_LED_Segment_Process(Num_int); LED_Segment_Display_point(0x7f,Reserved_points); LED_Segment_Display_point(0xff,Reserved_points); LED_Segment_Display_point(0xff,Reserved_points); } }
(4)配置数码管显示定时器,配置报错
void TIMER_0_INST_IRQHandler(void) { Num_LED_Segment_Process_Float(temp,Reserved_points); Num_LED_Segment_Process_Float(temp,Reserved_points); Num_LED_Segment_Process_Float(temp,Reserved_points); Num_LED_Segment_Process_Float(temp,Reserved_points); } void TIMER_1_INST_IRQHandler(void) { if(DS18B20_INIT()==0){ temp=DS18B20_GetTemp(); if(temp<temp_level[0]){ DL_GPIO_setPins(PORT_BEEP_PORT,PORT_BEEP_PIN__BEEP_PIN); } else if(temp>=temp_level[0]&&temp<temp_level[1]){ DL_GPIO_togglePins(PORT_BEEP_PORT,PORT_BEEP_PIN__BEEP_PIN); } else { DL_GPIO_clearPins(PORT_BEEP_PORT,PORT_BEEP_PIN__BEEP_PIN); } } else{ temp=0.1000; DL_GPIO_setPins(PORT_BEEP_PORT,PORT_BEEP_PIN__BEEP_PIN); delay_cycles(delay_us*1000); DL_GPIO_togglePins(PORT_LED_Red_PORT,PORT_LED_Red_PIN_LED_Red_PIN); } }
(5)主函数输出
int main(void) { SYSCFG_DL_init(); NVIC_SetPriority(TIMER_0_INST_INT_IRQN, 2); NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); DL_TimerG_startCounter(TIMER_0_INST); NVIC_SetPriority(TIMER_1_INST_INT_IRQN, 0); NVIC_EnableIRQ(TIMER_1_INST_INT_IRQN); DL_TimerG_startCounter(TIMER_1_INST); while (1) { delay_cycles(delay_us*500); } }
四、展示效果
由于操作不当,在之前造成了热敏电阻烧坏,现只能展示温度传感器出错时报错情况。(红灯亮起)