本节实现通过18B20温度传感器模块采集温度,通过数码管模块显示,超限通过蜂鸣器报警。
这次的蜂鸣器是有源蜂鸣器,低电平触发。
配置IO口状态
DS18B20是一种具有高精度、数字输出和单总线通信数字温度传感器,可以提供9位温度读 数。数字输出:DS18B20以数字形式输出温度数据,使得温度测量更为准确和方便。
高精度:DS18B20具有较高的温度测量精度,通常为±0.5°C。单总线通信:DS18B20采用1-Wire总线协议进行通信,只需要一条数据线就可以完成通信和供电,简化了连接方式。
多种封装形式:DS18B20可提供不同的封装形式,包括TO-92、TO-220、SMD等,以适应不同的应用场景。
低功耗:DS18B20在工作时的功耗较低,适合于一些对电源要求较为严格的应用。
数字校准:DS18B20内置了温度校准寄存器,可以通过软件进行校准,提高了温度测量的准确性。
DS18B20使用的是1-Wire协议进行通讯,1-Wire是一种串行通信协议,用于在单一数据线上进行通信和供电。它由独特的通信方式和协议约定组成,广泛应用于各种数字设备和传感器之间的通信。具体协议坛友已经写了很多,就不在这里重复了。
将模块连接到开发板
使用CCS进行编程,参考坛友的编写DS18B20驱动函数
温度超限比对,蜂鸣器驱动程序
#include "ti_msp_dl_config.h"
#include <math.h>
#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; //默认保留4位小数
uint8_t temp_level[]={28,29};//三档温度报警
/**
* @brief DS18B20时钟上升沿配置
*
* @param[in] 外设端口PORTx、延时t1、延时t2
*
*/
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);
}
/**
* @brief 单总线配置为输入模式
*
* @param[in] None
*
*/
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);
}
/**
* @brief 单总线配置为输出模式
*
* @param[in] None
*
*/
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);
}
/**
* @brief 复位DS18B20
*
* @param[in] None
*
*/
void DS18B20_RESET(){
DS18B20_DQ_OUT();
DS18B20_OneWireRisingEdge_Config(PORT_TempSensor_PORT, PORT_TempSensor_PIN_TempSensor_PIN,750,60);
}
/**
* @brief 判断DS18B20是否存在
*
* @param[in] None
*
*/
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) //超时未检测到器件,返回1
return 1;
else
counters=0;
while(!(DS18B20_DQ_IN_Read())&&counters<240){
counters++;
delay_cycles(delay_us*1);
}
if(counters>240) //检测到器件但总线电平持续拉低,返回2
return 2;
else
// DL_UART_transmitData(UART_0_INST,counters);
return 0; //检测到器件且总线电平有效,返回0
}
/**
* @brief 向DS18B20写入字节数据
*
* @param[in] data字节数据
*
*/
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;
}
}
/**
* @brief 从DS18B20读取比特数据
*
* @param[in] None
*
*/
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;
}
/**
* @brief 从DS18B20读取字节数据
*
* @param[in] None
*
*/
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;
}
/**
* @brief 启用DS18B20
*
* @param[in] None
*
*/
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);
}
/**
* @brief 初始化DS18B20
*
* @param[in] None
*
*/
uint8_t DS18B20_INIT(void){
DS18B20_RESET();
return DS18B20_CHECK();
}
/**
* @brief 获取DS18B20温度数据(小数点数据)
*
* @param[in] None
*
*/
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){ //高5位为1表示负温度
temp=(~temp)+1; //将补码取反运算+1得到负温值
temp_value=temp*(-0.0625);
}
else
temp_value=temp*0.0625;
return temp_value;
}
/**
* @brief HC595时钟上升沿配置
*
* @param[in] 外设端口PORTx、延时t1、延时t2
*
*/
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);
}
/**
* @brief HC595写入字节数据
*
* @param[in] byte字节数据
*
*/
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;
}
}
/**
* @brief 数码管显示1位数字
*
* @param[in] Num_one数字,index显示位置
*
*/
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);
}
/**
* @brief 数码管显示数字处理
*
* @param[in] Num数字
*
*/
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;
}
}
/**
* @brief 数码管显示浮点数处理
*
* @param[in] Num数字,Reserved_points保留小数点位数
*
*/
void Num_LED_Segment_Process_Float(float Num,uint8_t Reserved_points){//处理数码管显示浮点数,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);
}
}
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) {
// Num_LED_Segment_Process_Float(temp,Reserved_points);
delay_cycles(delay_us*500);
}
}
/**
* @brief 定时器0中断回调函数
*
* @param[in] None
*
*/
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);
// switch (DL_TimerG_getPendingInterrupt(TIMER_0_INST)) {
// case DL_TIMER_IIDX_ZERO:
// Num_LED_Segment_Process_Float(temp,Reserved_points);
// break;
// default:
// break;
// }
}
/**
* @brief 定时器1中断回调函数
*
* @param[in] None
*
*/
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);//温度传感器不存在、异常,LED_Red不断闪烁
DL_GPIO_togglePins(PORT_LED_Red_PORT,PORT_LED_Red_PIN_LED_Red_PIN);
}
// switch (DL_TimerG_getPendingInterrupt(TIMER_0_INST)) {
// case DL_TIMER_IIDX_ZERO:
// Num_LED_Segment_Process_Float(temp,Reserved_points);
// break;
// default:
// break;
// }
}
运行结果如图