历史上的今天
今天是:2024年11月25日(星期一)
2019年11月25日 | 利用AVR单片机设计的DS18B20测温程序
2019-11-25 来源:51hei
/********************************
DS18B20测温程序
文件名:main.c
编译:WinAVR-20070122
硬件环境:CA-M8X 打开的开关如下
S6(1,2,5,6,7) - 外部4MHz晶振和595接口
J8(EN-SEG) - 数码管显示允许
S7(4) - 连接PC1 与DS18B20数据口
(在CA-M8X 上DS18B20为非总线供电)
*******************************/
#include #include #include #include "seg.h" //声明数码管显示接口函数 #define CLR_1WIRE_BUS DDRC|=_BV(PC1) //设置为输出,此时由于PORTC1是低所以输出低 #define SET_1WIRE_BUS DDRC&=~_BV(PC1)//设置为输入,此时由于PORTC1是低所以程高阻,又因为外部有上拉电阻所以相当于设置总线为高 #define GET_1WIRE_BUS PINC&_BV(PC1) #define DS18B20_READ_ROM 0x33 #define DS18B20_MATCH_ROM 0X55 #define DS18B20_SKIP_ROM 0XCC #define DS18B20_SEARCH_ROM 0XF0 #define DS18B20_ALARM_SEARCH_ROM 0XEC #define DS18B20_WRITE_RAM 0X40 #define DS18B20_READ_RAM 0XBE #define DS18B20_COPY_RAM 0X48 #define DS18B20_CONVERT_TEM 0X44 #define DS18B20_EECALL_EEPROM 0XB8 #define DS18B20_READ_POWER_SUPPLY 0XB4 //总线端口初始化 void BusInit(void) { PORTC&=~_BV(PC1);//此口总保持低 DDRC&=~_BV(PC1); //初始化为输入,用外部上拉电阻保持总线的高电平 } //由于系统时钟为4MHz,一个_delay_loop_2正好延时一us #define DelayUs(x) _delay_loop_2(x) void DelayMs(uint16_t t) { uint16_t i; for(i=0;i } //单总线复位 uint8_t ds18b20_reset(void) { uint8_t ret=0; CLR_1WIRE_BUS; DelayUs(500); //拉低总线至少480us SET_1WIRE_BUS; DelayUs(100);//释放总线后等待15-60us if((GET_1WIRE_BUS)==0)//检测到DS18B20把总线拉低 ret=1; //复位成功 DelayUs(1000);//等待器件释放总线 return ret; } //单总线读一字节 uint8_t ds18b20_read(void) { uint8_t data=0; uint8_t i=0; for(i=0;i<8;i++) { data>>=1; CLR_1WIRE_BUS; DelayUs(2);//此时>1us SET_1WIRE_BUS; DelayUs(4);//此时<15us if(GET_1WIRE_BUS) data|=0x80; DelayUs(60);//此时>60us } return(data); } //单总线写一字节 void ds18b20_write(uint8_t data) { uint8_t i=0; for(i=0;i<8;i++) { if(data&0x01) { CLR_1WIRE_BUS; DelayUs(8);//8us SET_1WIRE_BUS; DelayUs(55);//55us } else { CLR_1WIRE_BUS; DelayUs(55);//55us SET_1WIRE_BUS; DelayUs(20);//8us } data>>=1; } } //执行转换 uint8_t Ds18b20Convert(uint8_t *t) { //发送转换命令 if(ds18b20_reset()==0) return 0; ds18b20_write(DS18B20_SKIP_ROM); //忽略地址匹配,总线上只有一个器件时,或对总线所有器件操作 ds18b20_write(DS18B20_CONVERT_TEM);//开始转换命令 //等待转换完成,ds18b20默认转换精度为12位,此时最大转换时间为750ms DelayMs(1000); //读温度字节 if(ds18b20_reset()==0) return 0; ds18b20_write(DS18B20_SKIP_ROM); //忽略地址匹配 ds18b20_write(DS18B20_READ_RAM); //读RAM命令 t[0]=ds18b20_read(); t[1]=ds18b20_read(); return 1; } //根据DS18B20中读的温度字节,计算实际温度值 int8_t GetTemperature(uint8_t *t) { int8_t ret; uint32_t val; uint16_t tmp=(t[1]*256)+t[0]; uint8_t sflag=0; if((t[1]&0xf8)==0xf8) //若负温度,从补码转换(取反加一) { sflag=1; tmp=~tmp; tmp++; } tmp&=0x07ff; //确保前5位为0 //乘0.0625操作,为此本函数只适用于DS18B20 12位转换(默认)时 val=((uint32_t)tmp)*625; val/=10000; ret=(int8_t)val; if(sflag) ret|=0x80;//变负数 return ret; } //测试主函数 int main(void) { uint8_t tmp[2];//保存温度字节 int8_t tval; //保存温度值 SegInit();//数码管初始化 SegNumberOut(0,0);//显示 0 BusInit(); //单总线I/O口初始化 while(1) { if(Ds18b20Convert(tmp))//如果转换成功 { tval=GetTemperature(tmp);//计算实际温度值 if(tval>=0) SegNumberOut(tval,0);//十进制显示温度值 else SegNumberOut(0,0);//数码管无法显示负数,只能显示0 } } return 0; } seg.c文件: /******************************** 74HC95驱动的数码管显示模块 文件名:seg.c 编译:WinAVR-20070122 硬件环境:CA-M8X 打开的开关如下 S6(1,2,5,6,7) - 外部4MHz晶振和595接口 J8(EN-SEG) - 数码管显示允许 芯艺设计室 2004-2007 版权所有 转载请保留本注释在内的全部内容 WEB: http://www.chipart.cn Email: changfutong@sina.com *******************************/ #include #include #include #include "seg.h" #define SER_PORT PORTD #define SER_DAT PD4 #define SER_RCK PD5 #define SER_SCK PD6 //显示码(可从chipart.cn下载生成工具) static uint8_t g_aDisplayBuf[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //向595 写一字节 static void ser_out(uint8_t dat) { uint8_t i; for(i=0;i<8;i++) { if(dat&0x80) SER_PORT|=_BV(SER_DAT); else SER_PORT&=~_BV(SER_DAT); //产生移位脉冲 SER_PORT|=_BV(SER_SCK); SER_PORT&=~_BV(SER_SCK); dat<<=1; } } //数码管显示数(0~255) //num :显示的数 hex:是否用十六进制显示 void SegNumberOut(uint8_t num,uint8_t hex) { uint8_t buf[2];//发送显示码缓冲区 uint8_t temp; if(hex) //十六进制 { buf[0]=g_aDisplayBuf[num>>4];//高位 buf[1]=g_aDisplayBuf[num&0x0f];//低位 } else//十进制 { buf[1]=g_aDisplayBuf[num%10]; temp=num%100; buf[0]=g_aDisplayBuf[temp/10]; temp=num/100; if(temp>0) buf[1]|=0x80; //第一个数码管小数点表示百位1 if(temp>1) buf[0]|=0x80;//两个数码管小数点表示百位2 } //串行发送数据 ser_out(buf[0]); ser_out(buf[1]); //产生锁存脉冲 SER_PORT|=_BV(SER_RCK); SER_PORT&=~_BV(SER_RCK); } void SegInit(void) { //595控制I/O初始化 DDRD=_BV(SER_DAT)|_BV(SER_SCK)|_BV(SER_RCK); SER_PORT&=~_BV(SER_SCK); SER_PORT&=~_BV(SER_RCK); }
史海拾趣
|
先楫官方工程师干货:HPM6000电源管理系统功能和特性、功耗实测 作者:先楫应用工程师全立 本文介绍了HPM6000电源管理系统功能和特性,低功耗管理系统的功能和特性,低功耗应用开发的示例,最后基于HPM6300EVK开发板测试验证了HPM6300 MCU在各个电源模式下的功耗指标,方便用户快速评估和上 ...… 查看全部问答> |
|
EEPROM擦写频率 EEPROM擦写频率怎么理解?怎么根据擦写频率选择EEPROM还是flash?比如如下这个案列 每100ms采集一次数据,每秒存20个字节(实际使用清空EEPROM存储的数据是每周清除三次,这个是否也是擦写频率的一种?) ...… 查看全部问答> |
|
本帖最后由 毛球大大 于 2022-11-9 19:51 编辑 作为第四次工业革命的重要基石,工业互联网为产业数字化提供了关键基础设施支撑和产业生态基础,成为数字经济创新发展的关键支撑。工业互联网的应用场景正在由销售、物流等 ...… 查看全部问答> |
|
Qorvo:新的 “Matter” 协议是智能家居物联网市场增长的关键 预计今年晚些时候,连接物联网设备的新 Matter 标准将最终确定。如果您正在研究任何类型的智能家居解决方案,那么您有充分的理由对新的 “Matter”协议将为 Wi-Fi (和其他连接技术)带来的改变感到兴奋。 Qorvo 表示,“ ...… 查看全部问答> |
|
什么是Matter Matter 是智能家居无线连接技术的一种开放标准协议,可使家庭设备可以与任何经过Matter认证的Matter生态系统产品互联互通。 Matter技术小解 Matter是一个应用层规范,能够在任何支持IPv6的设备上运行。最初规范中支持的网络 ...… 查看全部问答> |
|
反射系数Γ,回波损耗RL和电压驻波比VSWR。但是这三个名词描述的其实是一个意思:反射波和入射波之间的关系。 反射系数Γ,回波损耗RL和电压驻波比VSWR之间的关系如下: 既然是一个意思,居然用了三个名词来描述,也足见反射在射频设 ...… 查看全部问答> |
|
看到eeworld负责人发的e络盟有活动,赶紧上去看看,果然有活动,刚好最近DIY有需要用到电容,就买了几颗1000uF 35V和680uF 25V的电容,都是PANASONIC的,SF快递上海仓发货,三天就到了,非常快,哈哈,生命在于折腾,生命不息,折腾不止 &nb ...… 查看全部问答> |
|
micropython新书《用 MicroPython 开发 Raspberry Pi Pico W》 本周发布了一本新书:用 MicroPython 开发 Raspberry Pi Pico W :Miguel Grinberg 用 Python 编程数字电路的简要介绍 欢迎阅读《用于 Raspberry Pi Pico W 的 MicroPython》,这本书将向您介绍令人兴奋的微控制器和小型互 ...… 查看全部问答> |
|
Pimoroni银河独角兽开发板有一个巨大的 53 x 11 (583) RGB LED 矩阵,带有放大器和扬声器,核心是运行 Pimoroni 的 MicroPython 分支的 Raspberry Pi Pico W。 LED 可以在 14 位精度下以 300 fps 刷新。 技术指标: ...… 查看全部问答> |
|
Q、隔离型与非隔离型产品有何不同? A、隔离型的一次侧(AC线路)和二次侧(DC输出)是分离的,因此触电风险更低。而非隔离型的一次侧和二次侧是连接的,因此有触电的风险。 有些应用需要隔离型,有些则不需要。 Q、将IC的“NC ...… 查看全部问答> |




