课程3的任务目标是实现温度报警器,采集DS18B20的温度数据并实时显示。我们通过课程三的学习掌握了ADC采集的相关配置以及应用,不过课后的习题所使用的DS18B20是数字型温度传感器,在实际的任务实现过程中并没有用到ADC的相关知识。
这一次我们使用的的器件有数码管模块、有源扬声器模块、DS18B20温度传感器模块。我们先了解一下新模块。
有源扬声器模块:

本模块通过一个三极管进行驱动,并且是低电平触发,实际这块的控制只要通过一个引脚技能实现;
DS18B20温度传感器模块:
这个是这次任务比较难得一部分,DS18B20是通过单总线的方式进行通信的,这种通信协议对于时序的要求是非常严格的,我们需要根据时序图去编写起始、数据传输、结束等通信阶段。
我们在找到了一个DS18B20的驱动文件以及数据手册进行驱动的快速设计,单总线也就是所有通信都是通过这一根线实现的,我们需要根据时序切换输入输出状态,为了方便创建如下程序:
void delay_us(uint32_t Data)
{
delay_cycles(Data*32);
}
void ConfigDQ_IN(void)//配置为输入
{
DL_GPIO_disableOutput(GPIO_18B20_PORT, GPIO_18B20_PIN_Tem_PIN);
DL_GPIO_initDigitalInput(GPIO_18B20_PIN_Tem_IOMUX);
DL_GPIO_setPins(GPIO_18B20_PORT, GPIO_18B20_PIN_Tem_PIN);
DL_GPIO_enableOutput(GPIO_18B20_PORT, GPIO_18B20_PIN_Tem_PIN);
}
void ConfigDQ_OUT(void)//配置为输出入
{
DL_GPIO_disableOutput(GPIO_18B20_PORT, GPIO_18B20_PIN_Tem_PIN);
DL_GPIO_initDigitalOutput(GPIO_18B20_PIN_Tem_IOMUX);
DL_GPIO_setPins(GPIO_18B20_PORT, GPIO_18B20_PIN_Tem_PIN);
DL_GPIO_enableOutput(GPIO_18B20_PORT, GPIO_18B20_PIN_Tem_PIN);
}配置初始状态:
uint8_t DS18B20_Rst(void)
{
uint8_t Time=0;
ConfigDQ_OUT(); //设置为输出
DQReset; //拉低DQ
delay_us(750); //拉480us
DQSet; //DQ=1
delay_us(60); //60US
ConfigDQ_IN(); //设置为输入
//等待ds18b20回应
while (ReadDQ==1 && Time<200)
{
Time++;
delay_us(1);
}
if(Time>200)
return 1;
else
Time=0;
while (ReadDQ == 0 && Time<240)
{
Time++;
delay_us(1);
}
if(Time>240)
return 1;
else
return 0;
}写数据:

void Write_Byte(uint8_t data)
{
uint8_t i;
uint8_t bit;
ConfigDQ_OUT(); //设置为输出
for (i=1;i<=8;i++)
{
bit=data&0x01;
data=data>>1;
if(bit) // 写1
{
DQReset;
delay_us(2);
DQSet;
delay_us(60);
}
else //写0
{
DQReset;
delay_us(60);
DQSet;
delay_us(2);
}
}
}读数据:

uint8_t Read_Byte(void)
{
uint8_t i,bit,data;
data=0;
for (i=1;i<=8;i++)
{
ConfigDQ_OUT(); //设置为输出
DQReset;
delay_us(2);
ConfigDQ_IN(); //设置为输入
delay_us(10);
if(ReadDQ)
bit=1;
else
bit=0;
delay_us(48);
//将获得的dt放在最前面,然后再右移一下空出最前面的位置
data=(bit<<7)|(data>>1);
}
return data;
}接下来就是数据的读取了:
uint16_t GetTemp(void)
{
uint16_t tem;
uint8_t temp,TH,TL;
DS18B20_Rst();
Write_Byte(0xcc);
Write_Byte(0x44);
DS18B20_Rst();
Write_Byte(0xcc);
Write_Byte(0xbe);
TL=Read_Byte();
TH=Read_Byte();
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;//温度为负
}在定时器中调用GetTemp(void)获取温度,为什么要放到定时器里呢,因为中断发生会影响单总线的时序正确性,导致数据错误。暂定和之前课程的频率,每500ms采集一次,同时采集后判断温度是否大于280(温度是扩大十倍的值),大于限制就打开蜂鸣器,小于就关闭蜂鸣器。温度报警器功能同样通过按键去开启和关闭。
效果如下:

我要赚赏金
