项目概述-任务目标
1.采集DS18B20芯片温湿度数据
2.数码管显示实际温度数值
3.温度超过阈值,通过蜂鸣器报警
先上硬件框图
软件原理
1.DS18B20属于单总线协议,这里有一些简要描述(来源芯片数据手册)
作为电子工程师一定要熟练查看芯片的datasheet,原厂的资料一般比较全面
DS18B20采用单总线协议,通过一个单线端口通信。当全部器件经由一个三态端口或者开漏端口与总线连接的时 候,控制线需要连接一个弱上拉电阻。在这个总线系统中,微处理器(主器件)依靠每个器件独有的64位片序列号辨 认总线上的器件和记录总线上的器件地址。由于每个装置有一个唯一的片序列号,总线可以连接的器件数量实际上是 无限的。单总线协议,包括指令的详细解释和“时序”见单总线系统节。 DS18B20的另一个功能是可以在没有外部电源供电的情况下工作。当总线处于高电平状态,DQ与上拉电阻连接 通过单总线对器件供电。同时处于高电平状态的总线信号对内部电容(Cpp)充电,在总线处于低电平状态时,该电 容提供能量给器件,该提供能量的方式成为“寄生电源”。当然DS18B20可以通过VDD管脚连接外部电源供电。
DS18B20的核心功能是它的直接数字温度传感器。温度传感器的精度为用户可编程的9,10,11或12位。温度分 辨率分别为0.5℃、0.25℃、0.125℃和0.0625℃。芯片在上电状态下默认的精度为12位。DS18B20启动后保持低功耗 等待状态;当需要执行温度测量和AD转换时,总线控制器必须发出[44h]命令。在那之后,产生的温度数据以两个字节的形式被存储到温度寄存器中,DS18B20继续保持等待状态。DS18B20由外部电源供电时,总线控制器在温度转换 指令之后发起“读时序”,DS18B20正在温度转换中返回0,转换结束返回1。如果DS18B20由 寄生电源供电,除非在进入温度转换时总线被一个强上拉拉高,否则将不会有返回值。
DS18B20工作步骤 数码管原理在课程2相关帖子中已经详细介绍,这里就不过多提及了
3.蜂鸣器原理
蜂鸣器分有源和无源两种
我们手里的始于有源蜂鸣器,只需低电平就能驱动发声
!!!蜂鸣器电源接3.3V,不要接5V,接5V会一直响,这里要注意!!!
软件配置
DS18B20配置
数码管配置
蜂鸣器配置
关键软件代码
#include "ti/driverlib/dl_gpio.h" #include "ti/driverlib/m0p/dl_core.h" #include "ti_msp_dl_config.h" #include <stdint.h> #define DS18B20_DQ_OUTH DL_GPIO_setPins(GPIO_TEMP_PORT, GPIO_TEMP_PIN_DQ_PIN) #define DS18B20_DQ_OUTL DL_GPIO_clearPins(GPIO_TEMP_PORT, GPIO_TEMP_PIN_DQ_PIN) #define DS18B20_DQ_READ DL_GPIO_readPins(GPIO_TEMP_PORT, GPIO_TEMP_PIN_DQ_PIN) #define DS18B20_DQ_IN DL_GPIO_initDigitalInput(GPIO_TEMP_PIN_DQ_IOMUX);DL_GPIO_disableOutput(GPIO_TEMP_PORT, GPIO_TEMP_PIN_DQ_PIN) #define DS18B20_DQ_OUT DL_GPIO_initDigitalOutput(GPIO_TEMP_PIN_DQ_IOMUX);DL_GPIO_enableOutput(GPIO_TEMP_PORT, GPIO_TEMP_PIN_DQ_PIN) /* 数码管相关宏定义 */ #define HC595_PORT (GPIO_HC595_PORT) #define HC595_DIO_PIN (GPIO_HC595_HC595_DIO_PIN) #define HC595_SCLK_PIN (GPIO_HC595_HC595_SCLK_PIN) #define HC595_RCLK_PIN (GPIO_HC595_HC595_RCLK_PIN) uint8_t Disp_DX[ 16 ]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //段显 uint8_t Disp_PX[ 8 ]={1,2,3,4,5,6,7,8}; //片选 #define DigitPoint 0x7F //小数点 #define HC595_DAT(x) ((x)?(DL_GPIO_setPins(HC595_PORT, HC595_DIO_PIN)) : (DL_GPIO_clearPins(HC595_PORT, HC595_DIO_PIN))) #define HC595_CLK(x) ((x)?(DL_GPIO_setPins(HC595_PORT, HC595_SCLK_PIN)) : (DL_GPIO_clearPins(HC595_PORT, HC595_SCLK_PIN))) #define HC595_RCK(x) ((x)?(DL_GPIO_setPins(HC595_PORT, HC595_RCLK_PIN)) : (DL_GPIO_clearPins(HC595_PORT, HC595_RCLK_PIN))) /* 蜂鸣器相关宏定义 */ #define BeepON DL_GPIO_clearPins(GPIO_BEEP_PORT, GPIO_BEEP_PIN_BEEP_PIN); #define BeepOFF DL_GPIO_setPins(GPIO_BEEP_PORT, GPIO_BEEP_PIN_BEEP_PIN); #define delay_us_cycle 32 uint8_t TimerCnt = 0; uint16_t TmpVal = 999; float realTemp = 0.0; uint16_t testData = 0; /* 温湿度芯片相关功能函数 */ /* 延时函数 */ void inline delay_us(uint16_t us) { do{ delay_cycles(delay_us_cycle); }while (us --); } /* 复位芯片 */ static void DS18B20_Rst(void) { DS18B20_DQ_OUT; DS18B20_DQ_OUTL; /* 拉低DQ,复位 */ delay_us(750); /* 拉低750us */ DS18B20_DQ_OUTH; /* DQ=1, 释放复位 */ delay_us(15); /* 延迟15US */ } /* 检查总线上是否存在温度芯片 */ uint8_t DS18B20_Check(void) { uint8_t retry = 0; DS18B20_DQ_IN; while (DS18B20_DQ_READ && retry < 200) { retry++; delay_us(1); }; if (retry >= 200) return 1; else retry = 0; while (!DS18B20_DQ_READ && retry < 240) { retry++; delay_us(1); }; if (retry >= 240) return 1; return 0; } /* 芯片初始化 */ uint8_t DS18B20_Init(void) { DS18B20_Rst(); return DS18B20_Check(); } /* 读取单bit数据 */ uint8_t DS18B20_Read_Bit(void) // read one bit { DS18B20_DQ_OUT; uint8_t data; DS18B20_DQ_OUTL; delay_cycles(2 * 32); DS18B20_DQ_OUTH; delay_cycles(12 * 32); DS18B20_DQ_IN; if (DS18B20_DQ_READ) data = 1; else data = 0; delay_cycles(50 * 32); return data; } /* 读取一字节数据 */ uint8_t DS18B20_Read_Byte(void) // read one byte { uint8_t i, j, dat; dat = 0; for (i = 1; i <= 8; i++) { j = DS18B20_Read_Bit(); dat = (j << 7) | (dat >> 1); } return dat; } /* 写入一字节数据 */ void DS18B20_Write_Byte(uint8_t dat) { uint8_t j; uint8_t testb; DS18B20_DQ_OUT; for (j = 1; j <= 8; j++) { testb = dat & 0x01; dat = dat >> 1; if (testb) { DS18B20_DQ_OUTL; // Write 1 // delay_cycles(2 * 32); delay_us(2); DS18B20_DQ_OUTH; // delay_cycles(60 * 32); delay_us(60); } else { DS18B20_DQ_OUTL; // Write 0 // delay_cycles(60 * 32); delay_us(60); DS18B20_DQ_OUTH; // delay_cycles(2 * 32); delay_us(12); } } } /* 启动芯片 */ void DS18B20_Start(void) // ds1820 start convert { DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc); // skip rom DS18B20_Write_Byte(0x44); // convert } float DS18B20_Get_Temp(void) { uint8_t temp; uint8_t TL, TH; int16_t tem; float fValue = 0.0; 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; // 获得底八位 fValue = (float)tem * 0.0625; // 转换 if (temp) return fValue; // 返回温度值 else return -fValue; } /* 数码管相关功能函数 */ /* 开启数码管输出 */ void Display_Out() { HC595_RCK(0); delay_cycles(100); HC595_RCK(1); delay_cycles(100); } /* 串行数据写入 */ void HC595_WriteData(uint8_t data) { uint8_t i; for(i = 0; i < 8; i++) { if(data&0x80) { HC595_DAT(1); } else { HC595_DAT(0); } data <<=1; delay_cycles(100); HC595_CLK(0); delay_cycles(100); HC595_CLK(1); delay_cycles(100); } } /* 按位点亮数码管 */ void HC595_SEND_DATA(uint8_t disp_num, uint8_t disp_bit) { HC595_WriteData(disp_num); HC595_WriteData(1<<disp_bit); Display_Out(); } void Disp_Temp(float tempValue) { uint16_t tempShow; uint8_t num_q, num_b, num_s,num_g; tempShow = tempValue; num_q = tempShow/1000%10; num_b = tempShow/100%10; num_s = tempShow/10%10; num_g = tempShow%10; if (num_q) { HC595_SEND_DATA(Disp_DX[num_q],7); } if (num_q || num_b) { HC595_SEND_DATA(Disp_DX[num_b],6); } if (num_q || num_b || num_s) { HC595_SEND_DATA(Disp_DX[num_s],5); } uint8_t disData = Disp_DX[num_g] & 0x7F; //添加小数点 HC595_SEND_DATA(disData,4); tempShow = (tempValue - (float)tempShow) * 10000.0; num_q = tempShow/1000%10; num_b = tempShow/100%10; num_s = tempShow/10%10; num_g = tempShow%10; if (tempValue) { HC595_SEND_DATA(Disp_DX[num_q],3); } if (tempValue || num_b) { HC595_SEND_DATA(Disp_DX[num_b],2); } if (tempValue || num_b || num_s) { HC595_SEND_DATA(Disp_DX[num_s],1); } HC595_SEND_DATA(Disp_DX[num_g],0); } void TIMER_0_INST_IRQHandler(void) { switch(DL_Timer_getPendingInterrupt(TIMER_0_INST)){ case DL_TIMER_IIDX_ZERO: TimerCnt ++; if(TimerCnt >= 25) { TimerCnt = 0; realTemp = DS18B20_Get_Temp();//温度数据一秒读取一次 /* 温度判断 超过30读告警 */ if (realTemp > 30.0) { BeepON; } else { BeepOFF; } } break; default: break; } } int main(void) { /* Power on GPIO, initialize pins as digital outputs */ SYSCFG_DL_init(); DL_GPIO_setPins(GPIO_BEEP_PORT, GPIO_BEEP_PIN_BEEP_PIN); NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); while (1) { Disp_Temp(realTemp); } }
运行效果图: