要求:
1、驱动数码管,可以显示000.0-999.9的数值。
2、驱动DS_18B20数字温度计
3、驱动有源蜂鸣器,在采集到温度值达到规定高度时,这现蜂鸣器报警,低于规定值时关闭报警
硬件原理:
DS_18B20温度传感器
DS18B20是一款常用的高精度的单总线数字温度测量芯片。具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
传感器参数
测温范围为-55℃到+125℃,在-10℃到+85℃范围内误差为±0.4°。
返回16位二进制温度数值
主机和从机通信使用单总线,即使用单线进行数据的发送和接收
在使用中不需要任何外围元件,独立芯片即可完成工作。
掉电保护功能 DS18B20 内部含有 EEPROM ,通过配置寄存器可以设定数字转换精度和报警温度,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。
每个DS18B20都有独立唯一的64位-ID,此特性决定了它可以将任意多的DS18b20挂载到一根总线上,通过ROM搜索读取相应DS18B20的温度值
宽电压供电,电压2.5V~5.5V
DS18B20返回的16位二进制数代表此刻探测的温度值,其高五位代表正负。如果高五位全部为1,则代表返回的温度值为负值。如果高五位全部为0,则代表返回的温度值为正值。后面的11位数据代表温度的绝对值,将其转换为十进制数值之后,再乘以0.0625即可获得此时的温度值。
传感器引脚及原理图
DS18B20传感器的引脚及封装图如下:
DS18B20一共有三个引脚,分别是:
GND:电源地线
DQ:数字信号输入/输出端。
VDD:外接供电电源输入端。
单个DS18B20接线方式: VDD接到电源,DQ接单片机引脚,同时外加上拉电阻,GND接地
代码:
sysconfig:
GPIO
DS18B20.c
查看DS18B20的温度表示法与计算机存储正负数据的原理一致: 正数补码为寄存器存储的数据自身,负数补码为寄存器存储值按位取反后+1 #include "DS18B20.h" static void ds18b20_reset(void) //复位操作{ DS18B20_OutPut_Mode(); DS18B20_DQ_OUT(0); delay_cycles(32*750); DS18B20_DQ_OUT(1); delay_cycles(32*15); }uint8_t ds18b20_check(void) //检测数据是否传输{ uint8_t retry = 0; uint8_t rval = 0; while ((DS18B20_DQ_IN>0) && (retry < 200)) { retry++; delay_cycles(32*1); } if (retry >= 200) { rval = 1; } else { retry = 0; while (!(DS18B20_DQ_IN>0) && (retry < 240)) { retry++; delay_cycles(32*1); } if (retry >= 240) rval = 1; } return rval; } static uint8_t ds18b20_read_bit(void) { uint8_t data = 0; DS18B20_DQ_OUT(0); delay_cycles(32*2); DS18B20_DQ_OUT(1); delay_cycles(32*12); DS18B20_InPut_Mode(); if (DS18B20_DQ_IN>0) { data = 1; } delay_cycles(32*50); return data; } static uint8_t ds18b20_read_byte(void) //读取数据{ uint8_t i, b, data = 0; for (i = 0; i < 8; i++) { b = ds18b20_read_bit(); data |= b << i; } return data; } static void ds18b20_write_byte(uint8_t data) //写入数据{ uint8_t j; for (j = 1; j <= 8; j++) { if (data & 0x01) { DS18B20_DQ_OUT(0); /* Write 1 */ delay_cycles(32*2); DS18B20_DQ_OUT(1); delay_cycles(32*50); } else { DS18B20_DQ_OUT(0); /* Write 0 */ delay_cycles(32*50); DS18B20_DQ_OUT(1); delay_cycles(32*2); } data >>= 1; /* 右移,获取高一位数据 */ } } static void ds18b20_start(void) //开始构建{ ds18b20_reset(); ds18b20_check(); ds18b20_write_byte(0xcc); ds18b20_write_byte(0x44); } uint8_t ds18b20_init(void) //初始化{ ds18b20_reset(); return ds18b20_check(); }
short ds18b20_get_temperature(void) //转换为温度{ uint8_t flag = 1; /* 默认温度为正数 */ uint8_t TL, TH; short temp; ds18b20_start(); ds18b20_reset(); ds18b20_check(); ds18b20_write_byte(0xcc); ds18b20_write_byte(0xbe); TL = ds18b20_read_byte(); TH = ds18b20_read_byte(); if (TH > 7) { TH = ~TH; TL = ~TL; flag = 0; /* 温度为负 */ } temp = TH; /* 获得高八位 */ temp <<= 8; temp += TL; /* 获得底八位 */ /* 转换成实际温度 */ if (flag == 0) { temp = (double)(temp+1) * 0.625; temp = -temp; } else { temp = (double)temp * 0.625; } return temp; }
DS18B20.h
#ifndef DS_18B20_H_ #define DS_18B20_H_ #include "ti_msp_dl_config.h" #define DS18B20_OutPut_Mode() {DL_GPIO_initDigitalOutput(HC595_DS18B20_IOMUX);} #define DS18B20_InPut_Mode() {DL_GPIO_initDigitalInput(HC595_DS18B20_IOMUX);} #define DS18B20_DQ_IN DL_GPIO_readPins(HC595_PORT,HC595_DS18B20_PIN) #define DS18B20_DQ_OUT(x) ((x)?(DL_GPIO_setPins(HC595_PORT, HC595_DS18B20_PIN)) : (DL_GPIO_clearPins(HC595_PORT, HC595_DS18B20_PIN))) uint8_t ds18b20_init(void); uint8_t ds18b20_check(void); short ds18b20_get_temperature(void);// 读取温度 #endif /* DS_18B20_H_ */主函数:
#include "ti_msp_dl_config.h" #include "DS18B20.h"uint8_t Disp_DX[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x77, 0x83, 0xC6, 0xA1, 0x86, 0x8E, 0xFF, 0xBF }; // 数码管模块的显示位置,自左向右 uint8_t Disp_PX[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; #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 SCLK_1 DL_GPIO_setPins(HC595_PORT, HC595_SCLK_PIN) uint8_t TimerCnt; uint32_t TmpVal; void Display_Out() { HC595_RCK(0); HC595_RCK(1); } void HC595_WriteData(uint8_t data) { uint8_t i; for(i = 0; i < 8; i++) { if((data & 0x80)>0){ HC595_DAT(1); } else { HC595_DAT(0); } data <<= 1; HC595_CLK(0); HC595_CLK(1); } } 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_Data(uint16_t dataH, uint16_t dataL) { uint16_t tempH,tempL; uint8_t num_q, num_b,num_s,num_g; tempL = dataL; num_q = tempL/1000; num_b = tempL/100%10; num_s = tempL/10%10; num_g = tempL%10; HC595_SEND_DATA(Disp_DX[num_q],3); HC595_SEND_DATA(Disp_DX[num_b],2); HC595_SEND_DATA(Disp_DX[num_s],1); HC595_SEND_DATA(Disp_DX[num_g],0); tempH = dataH; num_q = tempH/1000; num_b = tempH/100%10; num_s = tempH/10%10 ; num_g = tempH%10; HC595_SEND_DATA(Disp_DX[num_q],7); HC595_SEND_DATA(Disp_DX[num_b],6); HC595_SEND_DATA(Disp_DX[num_s] ,5); HC595_SEND_DATA(Disp_DX[num_g],4); } void Disp_Temp(uint16_t dataL) { uint16_t tempH,tempL; uint8_t num_q, num_b,num_s,num_g; tempL = dataL; num_q = tempL/1000; num_b = tempL/100%10; num_s = tempL/10%10; num_g = tempL%10; HC595_SEND_DATA(Disp_DX[num_q],3); HC595_SEND_DATA(Disp_DX[num_b],2); HC595_SEND_DATA(Disp_DX[num_s] & 0x7F,1); HC595_SEND_DATA(Disp_DX[num_g],0); } int main(void) { short temperature; TmpVal = 400; SYSCFG_DL_init(); while (1) { TmpVal++; if(TmpVal >= 80000) { temperature = ds18b20_get_temperature(); TmpVal = 0; if(temperature>230){ DL_TimerG_setCaptureCompareValue(PWM_0_INST, 2500, DL_TIMER_CC_0_INDEX); } else{ DL_TimerG_setCaptureCompareValue(PWM_0_INST, 0, DL_TIMER_CC_0_INDEX); } } Disp_Temp(temperature); } } void TIMER_0_INST_IRQHandler(void) { switch(DL_Timer_getPendingInterrupt(TIMER_0_INST)){ case DL_TIMER_IIDX_ZERO: { TmpVal --; if(TmpVal == 0) { TmpVal = 4; } } break; default: break; } }
实现效果: