/** * @file DS18B20_ATY.c * * @param Project DEVICE_GENERAL_ATY_LIB * * @author ATY * * @copyright * - Copyright 2017 - 2025 MZ-ATY * - This code follows: * - MZ-ATY Various Contents Joint Statement - * * https://mengze.top/MZ-ATY_VCJS * - CC 4.0 BY-NC-SA - * * https://creativecommons.org/licenses/by-nc-sa/4.0/ * - Your use will be deemed to have accepted the terms of this statement. * * @brief Familiar functions of DS18B20 for all embedded device * * @version * - 1_01_220927 > ATY * -# Preliminary version, first Release * - Undone ******************************************************************************** */ #ifndef __DS18B20_ATY_C #define __DS18B20_ATY_C #include "DS18B20_ATY.h" /******************************* For user *************************************/ /******************************************************************************/ #include "DS18B20.h" #include "delay.h" #include "usart.h" u8 ROM_ID[8]; u8 Refresh_OLED_Data = 0; /******************************************* DS18B20 单总线对延时精度要求非常高!!! 本程序使用了系统嘀嗒定时器来当做精准延时。 DQ :GPIOB_7 *******************************************/ /*功能:DS18B20初始化*/ void DS18B20_Init(void) { /*1.GPIOC口初始化*/ RCC->APB2ENR |= 1 << 3; GPIOB->CRL &= 0x0FFFFFFF; GPIOB->CRL |= 0x30000000; GPIOB->ODR |= 1 << 7; /*2.检测DS18B20设备是否正常*/ switch(DS18B20_CheckDevice()) { case 0: printf("DS18B20_Init OK!\n"); break; case 1: printf("DS18B20设备响应复位信号失败!\n"); break; case 2: printf("DS18B20设备释放总线失败!\n"); break; } } /*功能:向DS18B20发送一个复位信号*/ void DS18B20_SendRestSingle(void) { /*主机发送复位信号*/ DS18B20_OutPut_Mode(); DS18B20_OUT = 0; //拉低总线480~960 us ,对 DS18B20 芯片进行复位 DelayUs(750); DS18B20_OUT = 1; DelayUs(15); //释放总线15~60 us } /* 功能:检测DS18B20存在脉冲 返回值: 0 DS18B20设备正常 1 DS18B20设备响应复位信号失败 2 DS18B20设备释放总线失败 */ u8 DS18B20_CheckReadySingle(void) { u8 cnt = 0; /*1.检测存在脉冲*/ DS18B20_InPut_Mode(); while(DS18B20_IN && cnt < 240) //等待DS18B20 拉低总线 (60~240 us 响应复位信号) { DelayUs(1); cnt++; } if(cnt > 240) return 1; /*2.检测DS18B20是否释放总线*/ cnt = 0; DS18B20_InPut_Mode(); while((!DS18B20_IN) && cnt < 240) //判断DS18B20是否释放总线(60~240 us 响应复位信号之后会释放总线) { DelayUs(1); cnt++; } if(cnt > 240) return 2; else return 0; } /* 功能:检测DS18B20设备是否正常 返回值: 0 DS18B20设备正常 1 DS18B20设备响应复位信号失败 2 DS18B20设备释放总线失败 */ u8 DS18B20_CheckDevice(void) { DS18B20_SendRestSingle();/*1.主机发送复位信号*/ return DS18B20_CheckReadySingle();/*2.检测存在脉冲*/ } /*功能:向DS18B20写一个字节数据(命令)*/ u8 BS18B20_WriteByte(u8 cmd) { u8 i = 0; DS18B20_OutPut_Mode(); for(i = 0; i < 8; i++) { DS18B20_OUT = 0; DelayUs(2); //主机拉低总线写数据时间隙2us DS18B20_OUT = cmd & 0x01; //如果该写入位为1,必须在15us之内把总线拉高,为0 保持60us即可。 DelayUs(60); //确保DS18B20已经成功读取到该位数据 DS18B20_OUT = 1; //一位发送完成 cmd >>= 1; DelayUs(2); //位间隙2us } return 0; } /*功能:从DS18B20读取一个字节数据*/ u8 DS18B20_ReadByte(void) { u8 i, data = 0; for(i = 0; i < 8; i++) { DS18B20_OutPut_Mode();//初始化为输出模式 DS18B20_OUT = 0; DelayUs(2); //主机拉低总线读数据时间隙2us DS18B20_OUT = 1; //释放总线,准备读取位数据 DS18B20_InPut_Mode(); //初始化为输入模式 DelayUs(10); //等待DS18B20的数据输出 data >>= 1; //高位补0,默认以0为准 if(DS18B20_IN) data |= 0x80; DelayUs(60); //延时确保DS18B20采样周期已经过去(非常重要) DS18B20_OUT = 1; //释放总线准备读取下一位位数据 } return data; } /* 函数功能: 读取一次DS18B20的温度数据 返 回 值: 读取的温度数据 考虑的情况: 总线上只是接了一个DS18B20的情况 */ u16 DS18B20_GetTemperature(void) { u16 temp = 0; u8 temp_H, temp_L; int intT, decT; DS18B20_CheckDevice(); //发送复位脉冲、检测存在脉冲 BS18B20_WriteByte(0xCC); //跳过ROM序列检测 BS18B20_WriteByte(0x44); //启动一次温度转换 //等待温度转换完成 while(DS18B20_ReadByte() != 0xFF){} DS18B20_CheckDevice(); //发送复位脉冲、检测存在脉冲 BS18B20_WriteByte(0xCC); //跳过ROM序列检测 BS18B20_WriteByte(0xBE); //读取温度 temp_L = DS18B20_ReadByte(); //读取的温度低位数据 temp_H = DS18B20_ReadByte(); //读取的温度高位数据 temp = temp_L | (temp_H << 8); //合成温度 intT = temp >> 4; /*合成实际温度整数部分****精度相对上面的更高*/ decT = temp & 0xF; /*合成实际温度小数部分*/ printf("温度:%d.%d ℃ \n", intT, decT); return temp; } ///*功能:从DS18B20读取温度值,多点测温*/ //u16 DS18B20_GetTemperature(void) //{ // u16 temp; // u8 TL,TH; // DS18B20_SendRestSingle(); /*1.主机发送复位信号*/ // if(DS18B20_CheckReadySingle()) return 0xFF; /*2.检测存在脉冲*/ // DS18B20_MatchROM(); /*3.匹配 ROM 指令 (仅适用于总线上有多个设备)*/ BS18B20_WriteByte(0xCC); /*3.跳跃 ROM 指令 (仅适用于总线上只有一个设备)*/ // BS18B20_WriteByte(0x44); /*4.启动温度转换*/ // while(DS18B20_ReadByte()!=0xFF); //等待温度转换成功 // DS18B20_SendRestSingle(); /*5.主机发送复位信号*/ // if(DS18B20_CheckReadySingle()) return 0xFF; /*6.检测存在脉冲*/ // DS18B20_MatchROM(); /*6.匹配 ROM 指令 (仅适用于总线上有多个设备)*/ BS18B20_WriteByte(0xCC); /*7.跳跃 ROM 指令 (仅适用于总线上只有一个设备)*/ // BS18B20_WriteByte(0xBE); /*8.发送读取温度命令*/ // // TL = DS18B20_ReadByte(); /*9.读取温度高低位、校验位*/ // TH = DS18B20_ReadByte(); // DS18B20_SendRestSingle(); /*10.主机发送复位信号,示意停止读取剩下的数据*/ // temp = TH<<8 | TL; /*11.合成温度值*/ // return temp; // temp = temp * 0.0625; /*直接合成实际温度*/ value = temp * 100 + (value > 0 ? 0.5 : -0.5); //将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入 // intT = temp >> 4; /*合成实际温度整数部分****精度相对上面的更高*/ decT = temp & 0xF; /*合成实际温度小数部分*/ ///* crc = x^8 + x^5 + x^4 + 1*/ //} /*功能:从DS18B20读取ROM信息 (ROM_ID= 28-92-AF-AC-17-13-1-F1)*/ u8 DS18B20_ReadRomInfo(void) { u8 i = 0; BS18B20_WriteByte(0x33); /*4.启动读取ROM*/ for(i = 0; i < 8; i++) { ROM_ID[i] = DS18B20_ReadByte(); } printf("ROM_ID= "); for(i = 0; i < 8; i++) { printf("%X", ROM_ID[i]); if(i == 7) printf("\n"); else printf("-"); } return 0; } /* ROM_ID[0]=0x28 ROM_ID[1]=0x92 ROM_ID[2]=0xAF ROM_ID[3]=0xAC ROM_ID[4]=0x17 ROM_ID[5]=0x13 ROM_ID[6]=0x1 ROM_ID[7]=0xF1 */ /*功能:匹配 DS18B20 ROM信息*/ u8 DS18B20_MatchROM(void) { u8 i = 0; BS18B20_WriteByte(0x55); /*4.匹配64位 ROM 信息*/ for(i = 0; i < 8; i++) { BS18B20_WriteByte(ROM_ID[i]); } return 0; } // todo: not tested #endif /* __DS18B20_ATY_C */ /******************************** End Of File *********************************/