DS18B20多ROM搜索并读取温度

来源:互联网 发布:知道qq如何 知乎 编辑:程序博客网 时间:2024/06/05 07:07

测试采用4个DS18B20挂在6m长得网线上面,使用的是5V供电,4.7K上拉,STM32驱动,

程序实现ROM搜索并分别读取每一个DS18B20的温度.




/************************************************************************************************************* * 文件名:ds18b20.c * 功能:STM32 DS18B20驱动 * 作者:cp1300@139.com * 创建时间:2012年9月17日22:45 * 最后修改时间:2012年9月17日 * 详细:需要延时函数支持 * 注意延时精度尽可能的高 * 读取的时候不要长时间的被中断,因为1wire对时间要求很严格*************************************************************************************************************/#include "system.h"#include "delay.h"#include "ds18b20.h"//PC1#define DS18B20_OUTPBout(15)#define DS18B20_INPBin(15)//DS18B20使用的是GPIOE0#define Set18b20IOout()GPIOx_Init(GPIOB,BIT15,OUT_PP,SPEED_10M);//设置DS18B20 IO为输出,#define Set18b20IOin()GPIOx_Init(GPIOB,BIT15,IN_IPU,0);//设置DS18B20 IO为上拉输入,#define Read18b20IO()((DS18B20_IN) ? 1 : 0)//读取DS18B20 IO#define Write18b20IO(x)(DS18B20_OUT = x)//写DS18B20 IO/**************************************************************************************************************************函数        :bool DS18B20_Reset(void)*功能        :复位DS18B20*参数        :无*返回        :TRUE:成功;FALSE:失败*依赖: 底层宏定义*作者        :cp1300@139.com*时间     :20120917*最后修改时间:20120917*说明        :无*************************************************************************************************************************/bool DS18B20_Reset(void){u8 i = 0;Set18b20IOout();//主机端口推挽输出模式Write18b20IO(1);Delay_US(1);Write18b20IO(0);//拉低总线480us~240usDelay_US(500); //>480US延时Write18b20IO(1);Delay_US(2);//复位完成Set18b20IOin();//主机端口浮空输入模式while(Read18b20IO())//等待低电平应答信号{i ++;Delay_US(1);if(i > 100){uart_printf("DS18B20 error!\r\n");return FALSE;//等待超时,初始化失败,返回FALSE;}}Delay_US(250);//跳过回复信号return TRUE;//检测到DS18B20,并且初始化成功}/**************************************************************************************************************************函数        :__inline u8 DS18B20_ReadBit(void)*功能        :读取DS18B20 1bit数据*参数        :无*返回        :数据,最低位有效*依赖: 底层宏定义*作者        :cp1300@139.com*时间     :20130402*最后修改时间:20130402*说明        :无*************************************************************************************************************************/__inline u8 DS18B20_ReadBit(void){u8 data = 0;Set18b20IOout();//主机端口推挽输出模式Write18b20IO(0);//拉低总线10-15usDelay_US(12);Write18b20IO(1);//释放总线Set18b20IOin();//主机端口浮空输入模式Delay_US(10);if(Read18b20IO())//读取数据,读取后大约延时40-45usdata = 0x01;Delay_US(40);return data;}/**************************************************************************************************************************函数        :u8 DS18B20_ReadData(void)*功能        :读取DS18B20数据*参数        :无*返回        :数据*依赖: 底层宏定义*作者        :cp1300@139.com*时间     :20120917*最后修改时间:20120917*说明        :无*************************************************************************************************************************/u8 DS18B20_ReadData(void){u8 i,data = 0;for(i = 0;i < 8;i ++){data >>= 1;if(DS18B20_ReadBit())data |= 0x80;}return data;}/**************************************************************************************************************************函数        :__inline void DS18B20_WriteBit(u8 bit)*功能        :向DS18B20写一位数据*参数        :数据,只发送最低位*返回        :无*依赖: 底层宏定义*作者        :cp1300@139.com*时间     :20130402*最后修改时间:20130402*说明        :无*************************************************************************************************************************/__inline void DS18B20_WriteBit(u8 bit){Set18b20IOout();//主机端口推挽输出模式   Write18b20IO(0);//拉低总线10-15usDelay_US(12);Write18b20IO(bit & 0x01);//写入数据位,保持20-45usDelay_US(30);Write18b20IO(1);//释放总线Delay_US(5);}/**************************************************************************************************************************函数        :void DS18B20_WriteData(u8 data)*功能        :向DS18B20写数据*参数        :数据*返回        :无*依赖: 底层宏定义*作者        :cp1300@139.com*时间     :20120917*最后修改时间:20120917*说明        :无*************************************************************************************************************************/void DS18B20_WriteData(u8 data){u8 i;for(i = 0;i < 8;i ++){DS18B20_WriteBit(data);data >>= 1;}}/**************************************************************************************************************************函数        :s16 DS18B20_ReadTemper(void)*功能        :读取DS18B20温度*参数        :无*返回        :温度值*依赖: 底层宏定义*作者        :cp1300@139.com*时间     :20120917*最后修改时间:20120917*说明        :温度值扩大了100倍,温度值是个有符号数.*************************************************************************************************************************/s16 DS18B20_ReadTemper(void){u8 th, tl;s16 data;if(DS18B20_Reset() == FALSE){return 0xffff;//返回错误}DS18B20_WriteData(0xcc);//跳过读序列号DS18B20_WriteData(0x44);//启动温度转换DS18B20_Reset();DS18B20_WriteData(0xcc);//跳过读序列号DS18B20_WriteData(0xbe);//读取温度tl = DS18B20_ReadData();//读取低八位th = DS18B20_ReadData(); //读取高八位data = th;data <<= 8;data |= tl;data *= 6.25;//温度值扩大100倍,精确到2位小数return data;}/**************************************************************************************************************************函数        :__inline u8 DS18B20_Read2Bit(void)*功能        :读取DS18B20 2bit数据*参数        :无*返回        :数据*依赖: 底层宏定义*作者        :cp1300@139.com*时间     :20120917*最后修改时间:20120917*说明        :无*************************************************************************************************************************/u8 DS18B20_Read2Bit(void){u8 i,data = 0;for(i = 0;i < 2;i ++){data <<= 1;if(DS18B20_ReadBit())data |= 1;}return data;}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////以下代码为多DS18B20相关#define MAXNUM 4 //定义最多有4个 DS18B20/**************************************************************************************************************************函数        :u8 DS18B20_SearchROM(u8 (*pID)[8],u8 Num)*功能        :搜索DS18B20 ROM*参数        :pID:DS18B20 ID缓冲区指针Num:DS18B20数目,必须事先知道*返回        :搜索到的DS18B20数目*依赖: 底层宏定义*作者        :cp1300@139.com*时间     :2013-04-17*最后修改时间:2013-04-17*说明        :程序必须事先知道DS18B20数目,搜索的数目只会小于这个数目代码移植于互联网*************************************************************************************************************************/u8 DS18B20_SearchROM(u8 (*pID)[8],u8 Num){ unsigned char k,l,chongtuwei,m,n;unsigned char zhan[(MAXNUM)];unsigned char ss[64];u8 num = 0;l=0;do{DS18B20_Reset();DS18B20_WriteData(0xf0);for(m=0;m<8;m++){unsigned char s=0;for(n=0;n<8;n++){k=DS18B20_Read2Bit();//读两位数据k=k&0x03;s>>=1;if(k==0x01)//01读到的数据为0 写0 此位为0的器件响应{   DS18B20_WriteBit (0);    ss[(m*8+n)]=0;}else if(k==0x02)//读到的数据为1 写1 此位为1的器件响应{s=s|0x80;DS18B20_WriteBit (1);ss[(m*8+n)]=1;}else if(k==0x00)//读到的数据为00 有冲突位 判断冲突位 {//如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1chongtuwei=m*8+n+1;if(chongtuwei>zhan[l]){DS18B20_WriteBit (0);ss[(m*8+n)]=0;zhan[++l]=chongtuwei;}else if(chongtuwei<zhan[l]){s=s|((ss[(m*8+n)]&0x01)<<7);DS18B20_WriteBit (ss[(m*8+n)]);}else if(chongtuwei==zhan[l]){s=s|0x80;DS18B20_WriteBit (1);ss[(m*8+n)]=1;l=l-1;}}else{return num;//搜索完成,//返回搜索到的个数}}pID[num][m]=s;}num=num+1;}while(zhan[l]!=0&&(num<MAXNUM));return num;//返回搜索到的个数}/**************************************************************************************************************************函数        :s16 DS18B20_ReadDesignateTemper(u8 pID[8])*功能        :读取指定ID的DS18B20温度*参数        :pID:DS18B20 ID,必须事先知道,如果不知道请启动ROM搜索*返回        :温度值*依赖: 底层宏定义*作者       :cp1300@139.com*时间     :2013-04-17*最后修改时间:2013-04-17*说明        :温度值扩大了100倍,温度值是个有符号数.*************************************************************************************************************************/s16 DS18B20_ReadDesignateTemper(u8 pID[8]){u8 th, tl;s16 data;if(DS18B20_Reset() == FALSE){return 0xffff;//返回错误}DS18B20_WriteData(0xcc);//跳过读序列号DS18B20_WriteData(0x44);//启动温度转换DS18B20_Reset();DS18B20_WriteData(0x55);//发送序列号匹配命令for(data = 0;data < 8;data ++)//发送8byte的序列号{   DS18B20_WriteData(pID[data]);}Delay_US(10);DS18B20_WriteData(0xbe);//读取温度tl = DS18B20_ReadData();//读取低八位th = DS18B20_ReadData(); //读取高八位data = th;data <<= 8;data |= tl;data *= 6.25;//温度值扩大100倍,精确到2位小数return data;} 



#ifndef DS18B20_H_#define DS18B20_H_//DS18B20指令typedef enum {SEARCH_ROM=0xf0,//搜索ROM指令READ_ROM=0x33,//读取ROM指令MATH_ROM=0x55,//匹配ROM指令SKIP_ROM=0xcc,//忽略ROM指令ALARM_SEARCH=0xec,//报警索索指令CONVERT_T=0x44,//温度转换指令WRITE_SCRATCHPAD=0x4e,//写暂存器指令READ_SCRATCHPAD=0xbe,//读取暂存器指令COPY_SCRATCHPAD=0x48,//拷贝暂存器指令RECALL_E2=0xb8,//召回EEPROM指令READ_POWER_SUPPLY=0xb4,//读取电源模式指令} DS18B20_CMD;//DS18B20 ROM编码typedef struct{ u8DS18B20_CODE;//DS18B20单总线编码:0x19u8SN_1;//序列号第1字节u8SN_2;//序列号第2字节u8SN_3;//序列号第3字节u8SN_4;//序列号第4字节u8SN_5;//序列号第5字节u8SN_6;//序列号第6字节u8crc8;//CRC8校验码} DS18B20_ROM_CODE;#define DS18B20_Init()(DeviceClockEnable(DEV_GPIOB,ENABLE))//使能GPIOB时钟s16 DS18B20_ReadTemper(void);//读取DS18B20温度void DS18B20_WriteData(u8 data);u8 DS18B20_SearchROM(u8 (*pID)[8],u8 Num);//搜索ROM;s16 DS18B20_ReadDesignateTemper(u8 pID[8]);//读取指定ID的DS18B20温度#endif /*DS18B20_H_*/




#define DS18B20_NUM4u8 ID_Buff[DS18B20_NUM][8];int main(void){OS_CPU_SR  cpu_sr;s16 temp;u8 buff[16];u8 i,j,num;SYSTEM_ClockInit(9);//初始化系统时钟72MHzJTAG_Set(SWD_ENABLE);//只开启SWD调试模式DevInit();uart_printf("start system ...\r\n\r\n");num = DS18B20_SearchROM(ID_Buff,DS18B20_NUM);uart_printf("总线上实际挂载DS18B20数量: %d\r\n",DS18B20_NUM);uart_printf("搜索到的DS18B20数量: %d\r\n",num);for(i = 0;i < num;i ++){uart_printf("\r\n DS18B20 No%d ID: ",i);for(j = 0;j < 8;j ++){uart_printf("%02X ",ID_Buff[i][j]);}}i = 0;while(1){LED1 = ~LED1;Delay_MS(1000);temp = DS18B20_ReadDesignateTemper(ID_Buff[i ++]);uart_printf("\r\n DS18B20 No%d Temp:%d ",i,temp);if(i == 4){ i = 0;uart_printf("\r\n");}}}



结果