STM32F1与STM32CubeIDE编程实例-DS18B20温度传感器驱动 DS18B20温度传感器驱动 文章目录
1、DS18B20介绍 DS18B20 是一种温度传感器,它提供 9 位到 12 位的温度读数。 该传感器的通信可以通过单线总线(One-Wire,1-Wire)协议完成,该协议使用一条数据线与内部微处理器进行通信。
本文将介绍如何在STM32CubeIDE中驱动DS18B20。
由于DS18B20的数据通信方式为One-Wire,请参考前面与One-Wire总线相关文章:
在前面的文章中,对DS18B20作为详细的介绍,请参考:
2、DS18B20配置
DS18B20引脚配置如下:
One-Wire总线时序延时使用DWT实现,请参考前面文章:
3、DS18B20驱动实现 1)基本定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 // ds18b20.h #ifndef \_DS18B20\_H #define \_DS18B20\_H #include "onewire/onewire.h" // DS18B20配置 #define \_DS18B20\_MAX\_SENSORS 4 #define \_DS18B20\_GPIO DS18B20\_GPIO\_Port #define \_DS18B20\_PIN DS18B20\_Pin //#define \_DS18B20\_USE\_CRC // // DS18B20传感器定义 // typedef struct { uint8\_t Address[8]; float Temperature; uint8\_t ValidDataFlag; } Ds18b20Sensor_t; #define DS18B20\_FAMILY\_CODE 0x28 #define DS18B20\_CMD\_ALARMSEARCH 0xEC #define DS18B20\_CMD\_CONVERTTEMP 0x44 #define DS18B20\_STEP\_12BIT 0.0625 #define DS18B20\_STEP\_11BIT 0.125 #define DS18B20\_STEP\_10BIT 0.25 #define DS18B20\_STEP\_9BIT 0.5 #define DS18B20\_RESOLUTION\_R1 6 // 分辨率位 R1 #define DS18B20\_RESOLUTION\_R0 5 // 分辨率位 R0 #ifdef \_DS18B20\_USE\_CRC #define DS18B20\_DATA\_LEN 9 #else #define DS18B20\_DATA\_LEN 5 #endif // DS18B20分辨率 typedef enum { DS18B20_Resolution_9bits = 9, DS18B20_Resolution_10bits = 10, DS18B20_Resolution_11bits = 11, DS18B20_Resolution_12bits = 12 } DS18B20_Resolution_t; // DS18B20初始化 void DS18B20\_Init(DS18B20_Resolution_t resolution); // DS18B20设置 uint8\_t DS18B20\_GetResolution(uint8\_t number); // Get the sensor resolution uint8\_t DS18B20\_SetResolution(uint8\_t number, DS18B20_Resolution_t resolution); // Set the sensor resolution // 启动单个传感器转换 uint8\_t DS18B20\_Start(uint8\_t number); // 启动所有传感器转换 void DS18B20\_StartAll(void); // 读取单个传感器 uint8\_t DS18B20\_Read(uint8\_t number, float\* destination); // 读取所有传感器 void DS18B20\_ReadAll(void); // 检查ROM地址是否为DS18B20系列 uint8\_t DS18B20\_Is(uint8\_t\* ROM); // 检查所有传感器是否转换完成 uint8\_t DS18B20\_AllDone(void); // 从“number”位置获取传感器的 ROM void DS18B20\_GetROM(uint8\_t number, uint8\_t\* ROM); // 将 ROM 写入传感器表中的“number”位置 void DS18B20\_WriteROM(uint8\_t number, uint8\_t\* ROM); // 查询连接数量 uint8\_t DS18B20\_Quantity(void); // 查询当前温度值,如果读取的数据无效,则返回 0 uint8\_t DS18B20\_GetTemperature(uint8\_t number, float\* destination); #endif
2)DS18B20初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void DS18B20\_Init(DS18B20_Resolution_t resolution) { uint8\_t next = 0, i = 0, j; OneWire\_Init(&OneWire, DS18B20_GPIO_Port, DS18B20_Pin); // 初始化One-Wire总线 next = OneWire\_First(&OneWire); // 查询第一个设备 // 查询总线上所有设备 while(next) { TempSensorCount++; OneWire\_GetFullROM(&OneWire, (uint8\_t\*)&ds18b20[i++].Address); // 获取下一个传感器的ROM next = OneWire\_Next(&OneWire); if(TempSensorCount >= _DS18B20_MAX_SENSORS) // 不允许超过设置的最大值的传感器 break; } for(j = 0; j < i; j++) { DS18B20\_SetResolution(j, resolution); // 设置分辨率 DS18B20\_StartAll(); // 启动所有传感器转换 } }
3)DS18B20启动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // 启动指定传感器 uint8\_t DS18B20\_Start(uint8\_t number) { if( number >= TempSensorCount) // 大于最大限制数量,无效 return 0; if (!DS18B20\_Is((uint8\_t\*)&ds18b20[number].Address)) // 检查传感器是否为DS18B20系列 return 0; OneWire\_Reset(&OneWire); // 重置One-Wire总线 OneWire\_SelectWithPointer(&OneWire, (uint8\_t\*)ds18b20[number].Address); // 通过ROM查询设备 OneWire\_WriteByte(&OneWire, DS18B20_CMD_CONVERTTEMP); // 向总线发送开始转换命令 return 1; } // // 启动所有传感器 // void DS18B20\_StartAll() { OneWire\_Reset(&OneWire); // 重置总线 OneWire\_WriteByte(&OneWire, ONEWIRE_CMD_SKIPROM); // Skip ROM 命令 OneWire\_WriteByte(&OneWire, DS18B20_CMD_CONVERTTEMP); // 启动所有设备转换 }
4)DS18B20数据读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 // // 启动所有传感器 // void DS18B20\_StartAll() { OneWire\_Reset(&OneWire); // 重置总线 OneWire\_WriteByte(&OneWire, ONEWIRE_CMD_SKIPROM); // Skip ROM 命令 OneWire\_WriteByte(&OneWire, DS18B20_CMD_CONVERTTEMP); // 启动所有设备转换 } // // 读取单个传感器 // uint8\_t DS18B20\_Read(uint8\_t number, float \*destination) { if( number >= TempSensorCount) // 超过最大限制数量,无效 return 0; uint16\_t temperature; uint8\_t resolution; float result; uint8\_t i = 0; uint8\_t data[DS18B20_DATA_LEN]; #ifdef \_DS18B20\_USE\_CRC uint8\_t crc; #endif if (!DS18B20\_Is((uint8\_t\*)&ds18b20[number].Address)) // 检查是否为DS18B20系列传感器 return 0; if (!OneWire\_ReadBit(&OneWire)) // 检查总线是否释放 return 0; // 转换未完成,表示总线处于忙状态 OneWire\_Reset(&OneWire); // 重置总线 OneWire\_SelectWithPointer(&OneWire, (uint8\_t\*)&ds18b20[number].Address); // 通过ROM选择传感器 OneWire\_WriteByte(&OneWire, ONEWIRE_CMD_RSCRATCHPAD); // 发送数据读取命令 for (i = 0; i < DS18B20_DATA_LEN; i++) // 读取暂存器数据 data[i] = OneWire\_ReadByte(&OneWire); #ifdef \_DS18B20\_USE\_CRC crc = OneWire\_CRC8(data, 8); // CRC计算 if (crc != data[8]) return 0; // CRC无效 #endif temperature = data[0] | (data[1] << 8); // 16位温度数据 OneWire\_Reset(&OneWire); //重置总线 resolution = ((data[4] & 0x60) >> 5) + 9; // 传感器的分辨率来自暂存器的字节 4 switch (resolution) // 由于分辨率检查正确的值 { case DS18B20_Resolution_9bits: result = temperature\*(float)DS18B20_STEP_9BIT; break; case DS18B20_Resolution_10bits: result = temperature\*(float)DS18B20_STEP_10BIT; break; case DS18B20_Resolution_11bits: result = temperature\*(float)DS18B20_STEP_11BIT; break; case DS18B20_Resolution_12bits: result = temperature\*(float)DS18B20_STEP_12BIT; break; default: result = 0xFF; } \*destination = result; return 1; // 温度值有效 }
5)DS18B20转换分辨率查询与设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 uint8\_t DS18B20\_GetResolution(uint8\_t number) { if( number >= TempSensorCount) return 0; uint8\_t conf; if (!DS18B20\_Is((uint8\_t\*)&ds18b20[number].Address)) return 0; OneWire\_Reset(&OneWire); // 重置总线 OneWire\_SelectWithPointer(&OneWire, (uint8\_t\*)&ds18b20[number].Address); // 通过ROM查询设备 OneWire\_WriteByte(&OneWire, ONEWIRE_CMD_RSCRATCHPAD); // 发送读取暂存器命令 OneWire\_ReadByte(&OneWire); OneWire\_ReadByte(&OneWire); OneWire\_ReadByte(&OneWire); OneWire\_ReadByte(&OneWire); conf = OneWire\_ReadByte(&OneWire); // 寄存器 5 是带分辨率的配置寄存器 conf &= 0x60; // 屏蔽两个分辨率位 conf >>= 5; // 向左移动 conf += 9; // 获取分辨率位数的结果 return conf; } uint8\_t DS18B20\_SetResolution(uint8\_t number, DS18B20_Resolution_t resolution) { if( number >= TempSensorCount) return 0; uint8\_t th, tl, conf; if (!DS18B20\_Is((uint8\_t\*)&ds18b20[number].Address)) return 0; OneWire\_Reset(&OneWire); // 重置总线 OneWire\_SelectWithPointer(&OneWire, (uint8\_t\*)&ds18b20[number].Address); // 通过ROM查询设备 OneWire\_WriteByte(&OneWire, ONEWIRE_CMD_RSCRATCHPAD); //发送读取暂存器命令 OneWire\_ReadByte(&OneWire); OneWire\_ReadByte(&OneWire); th = OneWire\_ReadByte(&OneWire); // 从温度警报字节开始写入暂存器 tl = OneWire\_ReadByte(&OneWire); conf = OneWire\_ReadByte(&OneWire); if (resolution == DS18B20_Resolution_9bits) // 分辨率设置 { conf &= ~(1 << DS18B20_RESOLUTION_R1); conf &= ~(1 << DS18B20_RESOLUTION_R0); } else if (resolution == DS18B20_Resolution_10bits) { conf &= ~(1 << DS18B20_RESOLUTION_R1); conf |= 1 << DS18B20_RESOLUTION_R0; } else if (resolution == DS18B20_Resolution_11bits) { conf |= 1 << DS18B20_RESOLUTION_R1; conf &= ~(1 << DS18B20_RESOLUTION_R0); } else if (resolution == DS18B20_Resolution_12bits) { conf |= 1 << DS18B20_RESOLUTION_R1; conf |= 1 << DS18B20_RESOLUTION_R0; } OneWire\_Reset(&OneWire); // 重置总线 OneWire\_SelectWithPointer(&OneWire, (uint8\_t\*)&ds18b20[number].Address); OneWire\_WriteByte(&OneWire, ONEWIRE_CMD_WSCRATCHPAD); OneWire\_WriteByte(&OneWire, th); // 将 3 个字节写入暂存器 OneWire\_WriteByte(&OneWire, tl); OneWire\_WriteByte(&OneWire, conf); OneWire\_Reset(&OneWire); // Reset the bus OneWire\_SelectWithPointer(&OneWire, (uint8\_t\*)&ds18b20[number].Address); OneWire\_WriteByte(&OneWire, ONEWIRE_CMD_CPYSCRATCHPAD); // 将暂存器复制到 EEPROM return 1; } uint8\_t DS18B20\_Is(uint8\_t\* ROM) { if (\*ROM == DS18B20_FAMILY_CODE) //检查是否为DS18B20传感器 return 1; return 0; } uint8\_t DS18B20\_AllDone(void) { return OneWire\_ReadBit(&OneWire); // 检查所有设备转换是否完成 } void DS18B20\_ReadAll(void) { uint8\_t i; if (DS18B20\_AllDone()) { for(i = 0; i < TempSensorCount; i++) { ds18b20[i].ValidDataFlag = 0; if (DS18B20\_Is((uint8\_t\*)&ds18b20[i].Address)) { ds18b20[i].ValidDataFlag = DS18B20\_Read(i, &ds18b20[i].Temperature); } } } } void DS18B20\_GetROM(uint8\_t number, uint8\_t\* ROM) { if( number >= TempSensorCount) number = TempSensorCount; uint8\_t i; for(i = 0; i < 8; i++) ROM[i] = ds18b20[number].Address[i]; } void DS18B20\_WriteROM(uint8\_t number, uint8\_t\* ROM) { if( number >= TempSensorCount) return; uint8\_t i; for(i = 0; i < 8; i++) ds18b20[number].Address[i] = ROM[i]; } uint8\_t DS18B20\_Quantity(void) { return TempSensorCount; }
6)温度读取
1 2 3 4 5 6 7 8 9 10 uint8\_t DS18B20\_GetTemperature(uint8\_t number, float\* destination) { if(!ds18b20[number].ValidDataFlag) return 0; \*destination = ds18b20[number].Temperature; return 1; }
4、主程序 在main.c文件中添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 /\* Private includes ----------------------------------------------------------\*/ /\* USER CODE BEGIN Includes \*/ #include "onewire/onewire.h" #include "ds18b20/ds18b20.h" #include "dwt/dwt\_delay.h" #include <stdio.h> /\* USER CODE END Includes \*/ /\* Private typedef -----------------------------------------------------------\*/ /\* USER CODE BEGIN PTD \*/ float temperature; /\* USER CODE END PTD \*/ int main(void) { /\* USER CODE BEGIN 1 \*/ /\* USER CODE END 1 \*/ /\* MCU Configuration--------------------------------------------------------\*/ /\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/ HAL\_Init(); /\* USER CODE BEGIN Init \*/ /\* USER CODE END Init \*/ /\* Configure the system clock \*/ SystemClock\_Config(); /\* USER CODE BEGIN SysInit \*/ /\* USER CODE END SysInit \*/ /\* Initialize all configured peripherals \*/ MX\_GPIO\_Init(); MX\_USART1\_UART\_Init(); /\* USER CODE BEGIN 2 \*/ printf("\*\*\*\*DS18B20\*\*\*\*\r\n"); dwt\_init(); DS18B20\_Init(DS18B20_Resolution_12bits); HAL\_GPIO\_WritePin(DS18B20_GPIO_Port, DS18B20_Pin, 0); /\* USER CODE END 2 \*/ /\* Infinite loop \*/ /\* USER CODE BEGIN WHILE \*/ while (1) { /\* USER CODE END WHILE \*/ /\* USER CODE BEGIN 3 \*/ DS18B20\_ReadAll(); HAL\_GPIO\_WritePin(TEST_GPIO_Port, TEST_Pin, 1); DS18B20\_StartAll(); HAL\_GPIO\_WritePin(TEST_GPIO_Port, TEST_Pin, 0); uint8\_t ROM_tmp[8]; uint8\_t i; for (i = 0; i < DS18B20\_Quantity(); i++) { if (DS18B20\_GetTemperature(i, &temperature)) { DS18B20\_GetROM(i, ROM_tmp); printf("%d. ROM: %X%X%X%X%X%X%X%X Temp: %f\n\r", i, ROM_tmp[0], ROM_tmp[1], ROM_tmp[2], ROM_tmp[3], ROM_tmp[4], ROM_tmp[5], ROM_tmp[6], ROM_tmp[7], temperature); } } HAL\_Delay(1000); HAL\_GPIO\_TogglePin(LED_GPIO_Port, LED_Pin); } /\* USER CODE END 3 \*/ }
文章来源: https://iotsmart.blog.csdn.net/article/details/125271066
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!