├── .github └── FUNDING.yml ├── README.md ├── SConscript ├── dht11_sample.c ├── sensor_dallas_dht11.c └── sensor_dallas_dht11.h /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://github.com/murphyzhao/Sponsorships 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DHT11 数字温湿度传感器 2 | 3 | ## 简介 4 | 5 | DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有枀高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个 NTC 测温元件,幵与一个高性能 8 位单片机相连接,对外提供单总线通讯接口。更多 DHT11 的使用说明请参考 DHT11 厂家数据手册。 6 | 7 | ## 注意事项 8 | 9 | DHT11 是采用单总线通讯的传感器,本软件包采用 GPIO 模拟单总线时序。DHT11 的一次完整读时序需要 20ms,时间过长,故无法使用关中断或者关调度的方式实现独占 CPU 以保证时序完整正确。因此可能出现读取数据失败的情况,请用户注意。 10 | 11 | ## 联系人信息 12 | 13 | 维护人: 14 | 15 | - 维护:[MurphyZhao](https://github.com/murphyzhao) 16 | - 主页:https://github.com/murphyzhao/dht11_rtt 17 | -------------------------------------------------------------------------------- /SConscript: -------------------------------------------------------------------------------- 1 | from building import * 2 | 3 | # get current dir path 4 | cwd = GetCurrentDir() 5 | 6 | src = [] 7 | inc = [cwd] 8 | 9 | src += ['sensor_dallas_dht11.c'] 10 | 11 | if GetDepend(['PKG_USING_DHT11_SAMPLE']): 12 | src += ['dht11_sample.c'] 13 | 14 | group = DefineGroup('dht11', src, depend = ['PKG_USING_DHT11'], CPPPATH = inc) 15 | Return('group') 16 | -------------------------------------------------------------------------------- /dht11_sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2018, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-08-01 LuoGong the first version. 9 | * 2019-08-15 MurphyZhao add lock and modify code style 10 | */ 11 | 12 | #include 13 | #include 14 | #include "sensor.h" 15 | #include "sensor_dallas_dht11.h" 16 | #include "drv_gpio.h" 17 | 18 | /* Modify this pin according to the actual wiring situation */ 19 | #define DHT11_DATA_PIN GET_PIN(B, 12) 20 | 21 | static void read_temp_entry(void *parameter) 22 | { 23 | rt_device_t dev = RT_NULL; 24 | struct rt_sensor_data sensor_data; 25 | rt_size_t res; 26 | rt_uint8_t get_data_freq = 1; /* 1Hz */ 27 | 28 | dev = rt_device_find("temp_dht11"); 29 | if (dev == RT_NULL) 30 | { 31 | return; 32 | } 33 | 34 | if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) 35 | { 36 | rt_kprintf("open device failed!\n"); 37 | return; 38 | } 39 | 40 | rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)(&get_data_freq)); 41 | 42 | while (1) 43 | { 44 | res = rt_device_read(dev, 0, &sensor_data, 1); 45 | 46 | if (res != 1) 47 | { 48 | rt_kprintf("read data failed! result is %d\n", res); 49 | rt_device_close(dev); 50 | return; 51 | } 52 | else 53 | { 54 | if (sensor_data.data.temp >= 0) 55 | { 56 | uint8_t temp = (sensor_data.data.temp & 0xffff) >> 0; // get temp 57 | uint8_t humi = (sensor_data.data.temp & 0xffff0000) >> 16; // get humi 58 | rt_kprintf("temp:%d, humi:%d\n" ,temp, humi); 59 | } 60 | } 61 | 62 | rt_thread_delay(1000); 63 | } 64 | } 65 | 66 | static int dht11_read_temp_sample(void) 67 | { 68 | rt_thread_t dht11_thread; 69 | 70 | dht11_thread = rt_thread_create("dht_tem", 71 | read_temp_entry, 72 | RT_NULL, 73 | 1024, 74 | RT_THREAD_PRIORITY_MAX / 2, 75 | 20); 76 | if (dht11_thread != RT_NULL) 77 | { 78 | rt_thread_startup(dht11_thread); 79 | } 80 | 81 | return RT_EOK; 82 | } 83 | INIT_APP_EXPORT(dht11_read_temp_sample); 84 | 85 | static int rt_hw_dht11_port(void) 86 | { 87 | struct rt_sensor_config cfg; 88 | 89 | cfg.intf.user_data = (void *)DHT11_DATA_PIN; 90 | rt_hw_dht11_init("dht11", &cfg); 91 | 92 | return RT_EOK; 93 | } 94 | INIT_COMPONENT_EXPORT(rt_hw_dht11_port); 95 | -------------------------------------------------------------------------------- /sensor_dallas_dht11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2018, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-08-01 LuoGong the first version. 9 | * 2019-08-15 MurphyZhao add lock and modify code style 10 | * 11 | */ 12 | 13 | #include "sensor_dallas_dht11.h" 14 | #include 15 | #include 16 | #include "sensor.h" 17 | #include "board.h" 18 | #include 19 | 20 | #define SENSOR_DEBUG 21 | #define DBG_TAG "sensor.dht11" 22 | 23 | #ifdef SENSOR_DEBUG 24 | #define DBG_LVL DBG_LOG 25 | #else 26 | #define DBG_LVL DBG_ERROR 27 | #endif /* SENSOR_DEBUG */ 28 | #include 29 | 30 | #define SENSOR_TEMP_RANGE_MAX (100) 31 | #define SENSOR_TEMP_RANGE_MIN (0) 32 | #define SENSOR_HUMI_RANGE_MAX (100) 33 | #define SENSOR_HUMI_RANGE_MIN (0) 34 | 35 | #ifndef RT_USING_PIN 36 | #error "Please enable RT_USING_PIN" 37 | #endif 38 | 39 | #ifndef RT_SENSOR_VENDOR_DALLAS 40 | #define RT_SENSOR_VENDOR_DALLAS (7u) 41 | #endif 42 | 43 | #ifndef rt_hw_us_delay 44 | RT_WEAK void rt_hw_us_delay(rt_uint32_t us) 45 | { 46 | rt_uint32_t delta; 47 | 48 | us = us * (SysTick->LOAD / (1000000 / RT_TICK_PER_SECOND)); 49 | delta = SysTick->VAL; 50 | 51 | while (delta - SysTick->VAL < us) continue; 52 | } 53 | #endif 54 | 55 | static void dht11_reset(rt_base_t pin) 56 | { 57 | rt_pin_mode(pin, PIN_MODE_OUTPUT); 58 | 59 | rt_pin_write(pin, PIN_LOW); 60 | rt_thread_mdelay(20); /* 20ms */ 61 | 62 | rt_pin_write(pin, PIN_HIGH); 63 | rt_hw_us_delay(30); /* 30us*/ 64 | } 65 | 66 | static uint8_t dht11_check(rt_base_t pin) 67 | { 68 | uint8_t retry = 0; 69 | rt_pin_mode(pin, PIN_MODE_INPUT); 70 | 71 | while (rt_pin_read(pin) && retry < 100) 72 | { 73 | retry++; 74 | rt_hw_us_delay(1); 75 | } 76 | 77 | if(retry >= 100) 78 | { 79 | return CONNECT_FAILED; 80 | } 81 | 82 | retry = 0; 83 | while (!rt_pin_read(pin) && retry < 100) 84 | { 85 | retry++; 86 | rt_hw_us_delay(1); 87 | }; 88 | 89 | if(retry >= 100) 90 | { 91 | return CONNECT_FAILED; 92 | } 93 | 94 | return CONNECT_SUCCESS; 95 | } 96 | 97 | static uint8_t dht11_read_bit(rt_base_t pin) 98 | { 99 | uint8_t retry = 0; 100 | while (rt_pin_read(pin) && retry < 100) 101 | { 102 | retry++; 103 | rt_hw_us_delay(1); 104 | } 105 | retry = 0; 106 | 107 | while (!rt_pin_read(pin) && retry < 100) 108 | { 109 | retry++; 110 | rt_hw_us_delay(1); 111 | } 112 | 113 | rt_hw_us_delay(40); 114 | if(rt_pin_read(pin)) 115 | return 1; 116 | return 0; 117 | } 118 | 119 | static uint8_t dht11_read_byte(rt_base_t pin) 120 | { 121 | uint8_t i, dat = 0; 122 | 123 | for (i = 1; i <= 8; i++) 124 | { 125 | dat <<= 1; 126 | dat |= dht11_read_bit(pin); 127 | } 128 | 129 | return dat; 130 | } 131 | 132 | static uint8_t dht11_read_Data(rt_base_t pin,uint8_t *temp,uint8_t *humi) 133 | { 134 | uint8_t i, buf[5]; 135 | dht11_reset(pin); 136 | 137 | if(dht11_check(pin) == 0) 138 | { 139 | for(i=0; i<5; i++) /* read 40 bits */ 140 | { 141 | buf[i] = dht11_read_byte(pin); 142 | } 143 | 144 | if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) 145 | { 146 | *humi = buf[0]; 147 | *temp = buf[2]; 148 | } 149 | } 150 | else 151 | { 152 | return 1; 153 | } 154 | 155 | return 0; 156 | } 157 | 158 | uint8_t dht11_init(rt_base_t pin) 159 | { 160 | uint8_t ret = 0; 161 | 162 | dht11_reset(pin); 163 | ret = dht11_check(pin); 164 | if (ret != 0) 165 | { 166 | dht11_reset(pin); 167 | ret = dht11_check(pin); 168 | } 169 | 170 | return ret; 171 | } 172 | 173 | int32_t dht11_get_temperature(rt_base_t pin) 174 | { 175 | static int32_t temOLD = 0; 176 | uint8_t humi=0, temp = 0; 177 | int32_t temNEW; 178 | 179 | dht11_read_Data(pin, &temp, &humi); 180 | 181 | temNEW = (humi << 16)|(temp<<0); 182 | 183 | if((temNEW != temOLD) && (temNEW !=0)) 184 | { 185 | temOLD = temNEW; 186 | } 187 | return temOLD; 188 | } 189 | 190 | static rt_size_t dht11_polling_get_data(rt_sensor_t sensor, struct rt_sensor_data *data) 191 | { 192 | rt_int32_t temperature_humidity; 193 | temperature_humidity = dht11_get_temperature((rt_base_t)sensor->config.intf.user_data); 194 | data->data.temp = temperature_humidity; 195 | data->timestamp = rt_sensor_get_ts(); 196 | return 1; 197 | } 198 | 199 | static rt_size_t dht11_fetch_data(struct rt_sensor_device *sensor, void *buf, rt_size_t len) 200 | { 201 | RT_ASSERT(buf); 202 | 203 | if (sensor->config.mode == RT_SENSOR_MODE_POLLING) 204 | { 205 | return dht11_polling_get_data(sensor, buf); 206 | } 207 | 208 | return 0; 209 | } 210 | 211 | static rt_err_t dht11_control(struct rt_sensor_device *sensor, int cmd, void *args) 212 | { 213 | return RT_EOK; 214 | } 215 | 216 | static struct rt_sensor_ops sensor_ops = 217 | { 218 | dht11_fetch_data, 219 | dht11_control 220 | }; 221 | 222 | static struct rt_sensor_device dht11_dev; 223 | int rt_hw_dht11_init(const char *name, struct rt_sensor_config *cfg) 224 | { 225 | rt_err_t result = RT_EOK; 226 | rt_sensor_t sensor = &dht11_dev; 227 | 228 | rt_memset(sensor, 0x0, sizeof(struct rt_sensor_device)); 229 | 230 | if (!dht11_init((rt_base_t)cfg->intf.user_data)) 231 | { 232 | sensor->module = rt_calloc(1, sizeof(struct rt_sensor_module)); 233 | if (sensor->module == RT_NULL) 234 | { 235 | LOG_E("Memory error."); 236 | result = -RT_ENOMEM; 237 | goto __exit; 238 | } 239 | 240 | sensor->info.type = RT_SENSOR_CLASS_TEMP ; 241 | sensor->info.vendor = RT_SENSOR_VENDOR_DALLAS; 242 | sensor->info.model = "DHT11"; 243 | sensor->info.unit = RT_SENSOR_UNIT_DCELSIUS; 244 | sensor->info.intf_type = RT_SENSOR_INTF_ONEWIRE; 245 | sensor->info.range_max = SENSOR_TEMP_RANGE_MAX; 246 | sensor->info.range_min = SENSOR_TEMP_RANGE_MIN; 247 | sensor->info.period_min = 100; /* Read ten times in 1 second */ 248 | 249 | sensor->config = *cfg; 250 | sensor->ops = &sensor_ops; 251 | 252 | /* dht11 sensor register */ 253 | result = rt_hw_sensor_register(sensor, name, RT_DEVICE_FLAG_RDONLY, RT_NULL); 254 | if (result != RT_EOK) 255 | { 256 | LOG_E("device register err code: %d", result); 257 | goto __exit; 258 | } 259 | } 260 | else 261 | { 262 | LOG_E("dht11 init failed"); 263 | result = -RT_ERROR; 264 | goto __exit; 265 | } 266 | return RT_EOK; 267 | 268 | __exit: 269 | if (sensor->module) 270 | rt_free(sensor->module); 271 | return result; 272 | } 273 | -------------------------------------------------------------------------------- /sensor_dallas_dht11.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2018, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-08-01 LuoGong the first version. 9 | * 2019-08-15 MurphyZhao add lock and modify code style 10 | * 11 | */ 12 | 13 | #ifndef __DHT11_H__ 14 | #define __DHT11_H__ 15 | 16 | #include 17 | #include "sensor.h" 18 | 19 | #define CONNECT_SUCCESS 0 20 | #define CONNECT_FAILED 1 21 | 22 | struct dht11_device 23 | { 24 | rt_base_t pin; 25 | rt_mutex_t lock; 26 | }; 27 | typedef struct dht11_device *dht11_device_t; 28 | 29 | uint8_t dht11_init(rt_base_t pin); 30 | int32_t dht11_get_temperature(rt_base_t pin); 31 | int rt_hw_dht11_init(const char *name, struct rt_sensor_config *cfg); 32 | 33 | #endif /* __DS18B20_H_ */ 34 | 35 | 36 | --------------------------------------------------------------------------------