【玩转TI MSPM0L1306】课程 任务三 利用DS18B20实现温度报警功能
前言 :这里我使用的是keil5.39(keil版本必须在5.38A以上),编译器使用的是6.21版本,安装教程官网上面有详细的介绍,这里就不过多的说明了,如果说在使用keil版本出现问题的话,还是建议大家学习一下ccs编译环境,真的很好用。
一:任务目标:
1:蜂鸣器发声实现按键音效
2:数码管实现温度显示
3:温度报警器的实现
4:课后练习 :用DS18B20实现环境温度的采样
用数码管显示,并实现高温蜂鸣器报警
二:使用工具:
1.LP-MSPM0L1306开发板;
2.Mic USB线
3.74HC595数码管模块
4:杜邦线 5根
三:硬件介绍:
1:按键检测电路
S2按键:PA14 默认外部下拉,检测高电平有效,配置IO时需要内部下拉或悬空。这个功能我们之前使用过,这里就不作重复介绍了。
2:蜂鸣器驱动电路
本次使用蜂鸣器为低电平触发方式,IO使用PA16 口,配置IO时需要内部上拉或悬空,
(这里我在学习时候发现与ADC检测的冲突了,IO引脚就顺延了一下)
实物图片:
原理图:
实物图片:
软件配置,利用SYSCONFIG配置一下,配置如下:
基本的配置操作和之前教程中的控制LED灯的闪烁一致。
软件操作如下:
需要注意的是:在使用按键检测和蜂鸣器的IO引脚时,需要初始化引脚,否则不能正常使用。
主程序代码如下:
while (1)
{
if(Function == 0)
{
KeyValue = DL_GPIO_readPins(Blinky_PORT,GPIO_LEDS_USER_KEY_01_PIN); // Read the state of key input
if(KeyValue == 0)
{
DL_GPIO_clearPins(Blinky_PORT, GPIO_LEDS_USER_Twinkle_LED_PIN); //PA0= 0;turn on led
DL_GPIO_clearPins(Blinky_PORT, GPIO_BEEP_OUT_01_PIN); //PA0= 0;turn on led
KeyCount++;
if(KeyCount >= 999)
{
KeyCount = 0 ;
KeyCount_S++ ;
}
if( KeyCount_S >=10) KeyCount_S = 0 ;
}
else
{
DL_GPIO_setPins(Blinky_PORT, GPIO_LEDS_USER_Twinkle_LED_PIN); //PA0= 1;turn off led
DL_GPIO_setPins(Blinky_PORT, GPIO_BEEP_OUT_01_PIN); //PA0= 1;turn off led
}
}
Disp_Data(KeyCount_S,KeyCount);
}
实物效果如下:
2:数码管实现温度显示
硬件资源:利用板载的NTC温度传感器进行温度采集
原理图:
实物图片如下:
NTC的工作原理:NTC阻值随着温度的升高而降低,通过原理图得知会引起电压的变换,通过ADC采样得到采样值,再通过查表法得到电阻值;
1:NTC接法:3.3V供电,电阻10K/ NTC(10K)。
2:ADC电压关系为:Uadc = 3.3*RT/(10000+RT);
3:ADC(12bit)采样AD值为:AD = Uadc*4096/3.3 = 4096*RT/(10000+RT)(由于单片机是12位的AD,满点采样值为2^12=4096)
4:最后通过AD/RT和RT/℃的对应关系,可通过查表方式得到AD 值对应温度。
软件代码如下:首先利用sysconfig 配置一下ADC功能:
以上配置参考视频中的进行配置,然后自动生产底层代码:
/* ADC12_0 Initialization */
static const DL_ADC12_ClockConfig gADC12_0ClockConfig = {
.clockSel = DL_ADC12_CLOCK_ULPCLK,
.divideRatio = DL_ADC12_CLOCK_DIVIDE_8,
.freqRange = DL_ADC12_CLOCK_FREQ_RANGE_24_TO_32,
};
SYSCONFIG_WEAK void SYSCFG_DL_ADC12_0_init(void)
{
DL_ADC12_setClockConfig(ADC12_0_INST, (DL_ADC12_ClockConfig *) &gADC12_0ClockConfig);
DL_ADC12_initSingleSample(ADC12_0_INST,
DL_ADC12_REPEAT_MODE_ENABLED, DL_ADC12_SAMPLING_SOURCE_AUTO, DL_ADC12_TRIG_SRC_SOFTWARE,
DL_ADC12_SAMP_CONV_RES_12_BIT, DL_ADC12_SAMP_CONV_DATA_FORMAT_UNSIGNED);
DL_ADC12_configConversionMem(ADC12_0_INST, ADC12_0_ADCMEM_0,
DL_ADC12_INPUT_CHAN_9, DL_ADC12_REFERENCE_VOLTAGE_VDDA, DL_ADC12_SAMPLE_TIMER_SOURCE_SCOMP0, DL_ADC12_AVERAGING_MODE_DISABLED,
DL_ADC12_BURN_OUT_SOURCE_DISABLED, DL_ADC12_TRIGGER_MODE_AUTO_NEXT, DL_ADC12_WINDOWS_COMP_MODE_DISABLED);
DL_ADC12_setSampleTime0(ADC12_0_INST,500);
/* Enable ADC12 interrupt */
DL_ADC12_clearInterruptStatus(ADC12_0_INST,(DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED));
DL_ADC12_enableInterrupt(ADC12_0_INST,(DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED));
DL_ADC12_enableConversions(ADC12_0_INST);
}
因为我是在keil5中进行编译,下载的所以大家在移植代码的时候,需要注意要调用ADC0的初始化函数,SYSCFG_DL_ADC12_0_init();,并且使能ADC中断函数; DL_ADC12_enablePower(ADC12_0_INST);
实物效果如下:
3:温度报警器的实现
课程目标:PTC采样环境温度,数码管显示温度(℃),蜂鸣器实现超温报警
通过上两节课程的学习,我学会了控制蜂鸣器的功能和利用ADC采集温度,这节课我只需在原基础上进行修改,设置一下温度的上限值,超过上限值时候,开始温度报警,并且可以通过按键取消蜂鸣器的报警,具体代码如下:
ADC_Temprature = ReadTemprature();
ADC_Temprature_DEAL = NTC_AD_Search(ADC_Temprature) ;
if((ADC_Temprature_DEAL >= High_TEMP) && (Cancel_OUT == true ))
{
DL_GPIO_clearPins(Blinky_PORT, GPIO_LEDS_USER_Twinkle_LED_PIN); //PA0= 0;turn on led
DL_GPIO_clearPins(Blinky_PORT, GPIO_BEEP_OUT_01_PIN); //PA16= 0;turn on BEEP
}
if((ADC_Temprature_DEAL < High_TEMP)) //当温度低于设定温度时后,再次超过设定值时,才允许报警
{
Cancel_OUT = true ;
}
/*读取按键功能*/
KeyValue = DL_GPIO_readPins(Blinky_PORT,GPIO_LEDS_USER_KEY_01_PIN); // Read the state of key input
if(KeyValue == 0)
{
DL_GPIO_setPins(Blinky_PORT, GPIO_LEDS_USER_Twinkle_LED_PIN); //PA0= 0;turn on led
// DL_GPIO_setPins(Blinky_PORT, GPIO_BEEP_OUT_01_PIN); //PA0= 0;turn on beep
Cancel_OUT = false ;
}
Disp_Data_work2(ADC_Temprature_DEAL,ADC_Temprature);
课后练习:用DS18B20实现环境温度的采样,用数码管显示,并实现高温蜂鸣器报警
DS18B20介绍:
①、 独特的单总线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实
现微处理器与DS18B20的双向通讯。大大提高了系统的抗干扰性。
② 、测温范围 -55℃~+125℃,精度为±0.5℃。
③、支持多点组网功能,多个DS18B20可以并联在唯一的三线上,最多只能并联8个,
实现多点测温,如果数量过多,会使供电电源电压过低,从而造成信号传输的
不稳定。
④、 工作电源: 3.0~5.5V/DC (可以数据线寄生电源)。
⑤ 、在使用中不需要任何外围元件。
⑥、 测量结果以9~12位数字量方式串行传送。
软件介绍:
单总线是一种半双工通信方式
DS18B20共有6种信号类型:复位脉冲、应答脉冲、写0、写1、读0和读1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前。
边讲信号类型,边讲代码配置的方式,让大家了解STM32驱动18B20过程。
一:复位脉冲
单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480 us,,以产生复位脉冲。接着主机释放总线,4.7K的上拉电阻将单总线拉高,延时15~60 us,并进入接收模式(Rx)。接着DS18B20拉低总线60~240 us,以产生低电平应答脉冲。
//========================================================================
// 函数: DS18B20_Rst(void)
// 描述: 复位 DS18B20
// 参数: None.
// 返回: None.
// 版本: V1.0, 2024-05-09
//========================================================================
void DS18B20_Rst(void)
{
DL_GPIO_initDigitalOutput(GPIO_GRP_0_PIN_3_RC_IOMUX);
DS18B20_DAT(0);
delay_us(750) ;
DS18B20_DAT(1);
delay_us(15) ;
}
二:应答信号:
//========================================================================
// 函数: DS18B20_Rst(void)
// 描述: 等待DS18B20的回应
// 返回1:未检测到DS18B20的存在
// 返回0:存在
// 参数: None.
// 返回: None.
// 版本: V1.0, 2024-05-09
//========================================================================
char DS18B20_Check(void)
{
int retry=0;
DL_GPIO_initDigitalInput(GPIO_GRP_0_PIN_3_RC_IOMUX); //SET PG11 INPUT
while (DL_GPIO_readPins(HC595_PORT, GPIO_GRP_0_PIN_3_RC_PIN)&&retry<200)
{
retry++;
delay_us(1);
};
if(retry>=200)return 1;
else retry=0;
while ((!DL_GPIO_readPins(HC595_PORT, GPIO_GRP_0_PIN_3_RC_PIN))&&retry<240)
{
retry++;
delay_us(1);
};
if(retry>=240)return 1;
return 0;
}
3:写时序:
写时序包括写0时序和写1时序。所有写时序至少需要60us,且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。
//========================================================================
// 函数: void DS18B20_Write_Byte(char dat)
// 描述: 写一个字节到DS18B20
// dat:要写入的字节
// 参数: None.
// 返回: None.
// 版本: V1.0, 2024-05-09
//========================================================================
void DS18B20_Write_Byte(char dat)
{
unsigned char j;
unsigned char testb;
DL_GPIO_initDigitalOutput(GPIO_GRP_0_PIN_3_RC_IOMUX);; //SET PG11 OUTPUT
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
DS18B20_DAT(0);
delay_us(2) ;
DS18B20_DAT(1);
delay_us(60) ;
}
else
{
DS18B20_DAT(0);
delay_us(60) ;
DS18B20_DAT(1);
delay_us(2) ;
}
}
}
写1时序:主机输出低电平,延时2us,然后释放总线,延时60us。
写0时序:主机输出低电平,延时60us,然后释放总线,延时2us。
四: 读时序
单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。
所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态。
//========================================================================
// 函数: int DS18B20_Read_Bit(void)
// 描述: 等待DS18B20的回应
// 从DS18B20读取一个位
// 返回值:1/0
// 参数: None.
// 返回: None.
// 版本: V1.0, 2024-05-09
//========================================================================
int DS18B20_Read_Bit(void)
{
unsigned char data;
DL_GPIO_initDigitalOutput(GPIO_GRP_0_PIN_3_RC_IOMUX);; //SET PG11 OUTPUT
DS18B20_DAT(0);
delay_us(2) ;
DS18B20_DAT(1);
DL_GPIO_initDigitalInput(GPIO_GRP_0_PIN_3_RC_IOMUX);
delay_us(12);
if(DL_GPIO_readPins(HC595_PORT, GPIO_GRP_0_PIN_3_RC_PIN) ) data=1;
else data=0;
delay_us(50);
return data;
}
五:读取一个字节数据
//========================================================================
// 函数: char DS18B20_Read_Byte(void)
// 描述: DS18B20读取一个字节
// 返回值:读到的数据
// 参数: None.
// 返回: None.
// 版本: V1.0, 2024-05-09
//========================================================================
char DS18B20_Read_Byte(void)
{
unsigned char i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
总结步骤:
我们来看看DS18B20的典型温度读取过程,DS18B20的典型温度读取过程为:复位à发SKIP ROM命令(0XCC)à发开始转换命令(0X44)à延时à复位à发送SKIP ROM命令(0XCC)à发读存储器命令(0XBE)à连续读出两个字节数据(即温度)à结束。
//========================================================================
// 函数: short DS18B20_Get_Temp(void)
// 说明:从ds18b20得到温度值
// 精度:0.1C
// 返回值:温度值 (-550~1250)
// 版本: V1.0, 2024-05-09
//========================================================================
short DS18B20_Get_Temp(void)
{
unsigned char temp;
unsigned char TL,TH;
short tem;
DS18B20_Start (); // ds1820 start convert
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0xbe); // convert
TL=DS18B20_Read_Byte(); // LSB
TH=DS18B20_Read_Byte(); // MSB
if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0; //温度为负
}else temp=1; //温度为正
tem=TH; //获得高八位
tem<<=8;
tem+=TL; //获得底八位
tem=(float)tem*0.625; //转换
if(temp)return tem; //返回温度值
else return -tem;
}
以上为DS13B20驱动函数:
按键检测代码如下:
/*读取用户按键1 ---S2 功能*/
work3_keyValue1 = DL_GPIO_readPins(Blinky_PORT,GPIO_LEDS_USER_KEY_01_PIN); // Read the state of key input
if((work3_keyValue1 == 0) && ( work3_key1Up == true ))
{
DL_GPIO_setPins(Blinky_PORT, GPIO_LEDS_USER_Twinkle_LED_PIN); //PA0= 0;turn on led
DL_GPIO_setPins(Blinky_PORT, GPIO_BEEP_OUT_01_PIN); //PA0= 0;turn on beep
work3_key1Up = false ;
DisMode++ ;
if(DisMode >3)
{
DisMode = 1 ;
}
}
if(work3_keyValue1 == 0x4000)
{
work3_key1Up = true ;
}
/*读取用户按键2 ---S1 功能*/
work3_keyValue2 = DL_GPIO_readPins(Blinky_PORT,GPIO_LEDS_USER_KEY_02_PIN); // Read the state of key input
if((work3_keyValue2 == 0) && ( work3_key2Up == true ))
{
DL_GPIO_setPins(Blinky_PORT, GPIO_LEDS_USER_Twinkle_LED_PIN); //PA0= 0;turn on led
DL_GPIO_setPins(Blinky_PORT, GPIO_BEEP_OUT_01_PIN); //PA0= 0;turn on beep
work3_key2Up = false ;
/*只有在配置界面下,才对温度阈值进行设置*/
if(DisMode == 1)
{
Value_Max = Value_Max + 5 ;
if( Value_Max >= 350)
Value_Max =25 ;
}
}
if(work3_keyValue2 == 0x40000)
{
work3_key2Up = true ;
}
温度报警检测:
/*报警检测功能*/
if(DS18B20_TEMP > Value_Max )
{
DisMode = 2 ;
DL_GPIO_clearPins(Blinky_PORT, GPIO_BEEP_OUT_01_PIN); //PA16= 0;turn on BEEP
}
修改温度阈值函数:
/*只有在配置界面下,才对温度阈值进行设置*/
if(DisMode == 1)
{
Value_Max = Value_Max + 5 ;
if( Value_Max >= 350)
Value_Max =25 ;
}
主程序如下:
/*读取板载的NTC温度值,*/
ADC_Temprature = ReadTemprature();
ADC_Temprature_DEAL = NTC_AD_Search(ADC_Temprature) ;
keyDeal();
/*读取DS18B20数据*/
/*界面显示函数*/
if(DisMode == 1)
Disp_Data_work4(Value_Max);
else if(DisMode == 2)
Disp_Data_work5(DS18B20_TEMP);
else
Disp_Data_work3(ADC_Temprature_DEAL,DS18B20_TEMP);
其中温度读取在定时器内调用,每50MS 读取一次。。
这里我增加了设置温度设定值功能和按键取消报警的功能,这个在视频中有所体现。
实物效果如下: