衡山派开发板DS18B20单总线温度传感器移植与RT-Thread驱动详解
衡山派开发板DS18B20单总线温度传感器移植与RT-Thread驱动详解最近在做一个环境监控的小项目需要用到温度传感器。DS18B20这个老牌的数字温度传感器因为其单总线通信、精度高、支持多点组网的特点在很多场合都很好用。这次我把它移植到了衡山派HSPI-D133EBS开发板上并且在RT-Thread实时操作系统下跑了起来。整个过程踩了一些坑也总结了一些经验今天就把这个完整的移植过程分享给大家手把手教你从零开始搞定DS18B20。1. 认识DS18B20单总线的魅力DS18B20是一款非常经典的数字温度传感器咱们先来了解一下它的特点这样后面写驱动的时候心里才有底。核心特性高精度测量分辨率可以从9位到12位编程设置对应的温度增量分别是0.5°C、0.25°C、0.125°C和0.0625°C。上电默认就是最精细的12位。宽量程能测量-55°C到125°C的温度大部分场景都够用了。单总线通信这是它最大的亮点只需要一根数据线加上地线就能和单片机通信大大节省了IO口。一根线上甚至可以挂多个DS18B20因为它们每个都有全球唯一的64位序列号。寄生供电它甚至可以直接从数据线上“偷电”工作连电源线都省了不过为了稳定一般还是建议单独供电。通信原理说人话版你可以把单总线想象成一条“喊话”的线。主机我们的开发板和从机DS18B20都连在这条线上大家轮流说话。为了保证不乱套有一套严格的“时序”规则比如主机喊完要等多久从机才能回答。驱动代码的核心就是精确地模拟出这套时序。2. 移植前的准备工作2.1 硬件连接首先得把模块和开发板连起来。DS18B20模块一般就三个引脚VCC、GND、DQ数据线。接线表模块引脚衡山派开发板引脚说明VCC3.3V 或 5V电源正极接3.3V或5V都可以模块兼容。GNDGND电源地。DQPE.14单总线数据引脚。注意代码里默认用的是PE.14如果你想换其他引脚后面需要修改代码。提示如果你用的是带引脚的模块直接杜邦线连接即可。如果是探头式的注意正负极不要接反。2.2 获取驱动代码与资料原始资料里提供了完整的驱动代码包。你需要去立创开发板的资料下载中心wiki.lckfb.com找到“模块移植资料下载”部分下载DS18B20对应的压缩包。下载后你会得到一个驱动代码文件夹。咱们需要把它放到工程目录的特定位置你的工程路径\luban-lite\application\rt-thread\helloworld\user-bsp\如果找不到user-bsp这个文件夹说明你还没有进行模块移植的前置配置。需要先参考官方手册的“手册使用必要操作”章节进行设置。3. 代码移植与工程配置3.1 将驱动文件加入工程把下载的驱动代码文件夹例如ds18b20-temp-sensor整个复制到上面说的user-bsp目录下。这个文件夹里通常包含以下几个关键文件bsp_ds18b20.c/bsp_ds18b20.h 传感器底层驱动。test_ds18b20_temp_sensor.c 测试线程和命令行示例。Kconfig 菜单配置选项。SConscript 构建脚本。3.2 修改Kconfig文件为了让我们的新模块出现在RT-Thread的配置菜单里需要修改工程的总Kconfig文件。用VSCode打开工程找到这个文件application\rt-thread\helloworld\Kconfig在文件的末尾#endif语句的前面添加下面这行# DS18B20温度传感器 source application/rt-thread/helloworld/user-bsp/ds18b20-temp-sensor/Kconfig这行代码的作用是告诉构建系统“嘿这里还有一个子目录的配置需要加载进来”。3.3 使用 menuconfig 启用模块接下来咱们要通过图形化界面来启用这个模块。双击工程根目录下的win_env.bat脚本打开RT-Thread的Env工具。在Env命令行中输入以下命令查看所有可用的默认配置scons --list-def找到咱们衡山派开发板对应的配置通常是d13x_JLC_rt-thread_helloworld。输入命令应用它假设它在列表中是第7个scons --apply-def7或者直接用名字scons --apply-defd13x_JLC_rt-thread_helloworld_defconfig输入命令进入配置菜单scons --menuconfig在菜单中用方向键找到Porting code using the LCKFB module这个大类按回车进入。在里面找到Using DS18B20 temperature sensor选项按Y键选中它前面会出现一个*号。最后左右键选择Save保存配置然后退出菜单。3.4 编译与烧录配置保存好后就可以编译了。在Env命令行中输入scons或者使用多核编译加快速度数字16表示使用的核心数可根据自己电脑调整scons -j16编译成功后在\luban-lite\output\d13x_JLC_rt-thread_helloworld\images目录下会生成一个.img的镜像文件。接下来按照衡山派开发板的镜像烧录教程把这个文件烧录到开发板中即可。4. 驱动代码深度解析移植的核心在于理解驱动代码。咱们打开bsp_ds18b20.c掰开揉碎了看。4.1 引脚定义与宏代码开头定义了数据引脚并封装了几个操作宏让读写时序更清晰。#define DS18B20_DQ_PIN_NAME PE.14 // 数据引脚接在PE14 static rt_base_t DS18B20_DQ_Pin; // 引脚句柄 // 几个好用的宏定义 #define DQ_OUT() rt_pin_mode(DS18B20_DQ_Pin, PIN_MODE_OUTPUT) // 设置引脚为输出 #define DQ_IN() rt_pin_mode(DS18B20_DQ_Pin, PIN_MODE_INPUT_PULLUP) // 设置引脚为上拉输入 #define DQ_GET() rt_pin_read(DS18B20_DQ_Pin) // 读取引脚电平 #define DQ(x) rt_pin_write(DS18B20_DQ_Pin, (x ? PIN_HIGH : PIN_LOW)) // 输出高低电平注意如果你想更换数据引脚只需修改DS18B20_DQ_PIN_NAME这个宏比如改成PA.01。4.2 单总线时序的“翻译官”DS18B20通信全靠精确的时序。驱动里的几个函数就是这些时序的“翻译官”。初始化检测器件DS18B20_Check这个过程就像是主机喊一声“喂有人在吗”然后等待从机回应“在”。主机把总线拉低至少480us大声喊“喂”。主机释放总线转为接收状态松开手准备听。DS18B20如果存在会在15-60us内把总线拉低60-240us作为应答回应“在”。DS18B20释放总线通信线路恢复空闲。写一个位DS18B20_Write_Byte内部逻辑写“1”主机拉低总线约2us然后释放并保持高电平至少60us。 写“0”主机拉低总线并保持至少60us然后释放。读一个位DS18B20_Read_Byte内部逻辑主机拉低总线至少1us然后释放。主机迅速切换到输入模式并在约15us后采样总线电平。此时DS18B20会控制总线电平低电平代表“0”高电平代表“1”。整个读时隙至少需要60us两次读操作之间至少需要1us恢复时间。4.3 核心功能函数理解了底层时序上层函数就很好懂了。// 启动一次温度转换 void DS18B20_Start(void) { DS18B20_Check(); // 先检查设备在不在 DS18B20_Write_Byte(0xcc); // 发送“跳过ROM”命令对总线上所有设备操作 DS18B20_Write_Byte(0x44); // 发送“开始温度转换”命令 }0xCC是“跳过ROM”命令适用于总线上只有一个DS18B20的情况省去了查询64位地址的步骤。0x44命令告诉传感器“开始测量温度吧”。// 读取温度值 float DS18B20_Read(void) { DS18B20_Start(); // 先启动转换 rt_thread_mdelay(750); // 等待转换完成12位精度需要750ms DS18B20_Check(); DS18B20_Write_Byte(0xcc); // 跳过ROM DS18B20_Write_Byte(0xbe); // 发送“读取暂存器”命令 dataL DS18B20_Read_Byte(); // 读温度低字节 dataH DS18B20_Read_Byte(); // 读温度高字节 temp (dataH 8) dataL; // 合成16位数据 // 温度计算寄存器值 * 分辨率(0.0625) if(dataH 0X80) { // 最高位为1温度是负数 temp (~temp) 1; // 取补码 value temp * (-0.0625); } else { value temp * 0.0625; } return value; }0xBE是读取命令。读回来的两个字节就是温度寄存器。这里有个关键点DS18B20转换温度需要时间12位精度下最长需要750ms所以启动转换后必须等待足够时间再去读。原始示例代码里省略了等待实际使用时一定要加否则读到的可能是上一次的数据。4.4 在RT-Thread中创建测试线程驱动写好了怎么在RT-Thread里用起来呢看test_ds18b20_temp_sensor.c这个文件。它创建了一个独立的线程来周期性地读取温度static void ds18b20_thread_entry(void *param) { DS18B20_Init(); // 初始化传感器 while(1) { float temperature DS18B20_Read(); // 读取温度 if( temperature 0 ) { // 将浮点数转换为整数和小数部分打印 uint32_t value temperature * 100.0f; rt_kprintf(Temperature %d.%02d C\n, value/100, value%100); } rt_thread_mdelay(2000); // 每2秒读一次 } }更重要的是它通过MSH_CMD_EXPORT宏将启动和停止线程的函数导出为了系统命令。MSH_CMD_EXPORT(test_ds18b20_temp_sensor, run DS18B20 temp sensor); MSH_CMD_EXPORT(test_exit_ds18b20_temp_sensor, quit DS18B20);这样在系统启动后你只需要在串口终端Finsh/MSH里输入test_ds18b20_temp_sensor这个温度读取线程就跑起来了。输入test_exit_ds18b20_temp_sensor就能停止它。非常方便调试和测试。5. 上机验证与调试按照串口调试教程用USB转TTL模块连接衡山派开发板的调试串口。给开发板上电打开串口终端软件如Putty、MobaXterm等波特率设置为115200。看到RT-Thread的系统启动日志和命令行提示符msh 后输入命令启动温度读取test_ds18b20_temp_sensor小技巧输入test后按TAB键系统会自动补全命令。如果一切正常终端里会每隔2秒打印出当前的温度值格式类似Temperature 25.62 C。常见问题排查一直打印初始化失败或读取失败首先检查硬件连接VCC、GND、DQ三根线是否接对、接牢。然后用万用表量一下DQ引脚电压在空闲时应该是高电平3.3V或5V。读数全是0或者85读数85是DS18B20的上电默认值说明通信可能成功了但温度转换命令没执行或没等到转换完成就读取了。务必确保在DS18B20_Start()后添加足够的延时如rt_thread_mdelay(750)。读数跳动大可能是电源噪声或总线干扰。尝试在DQ引脚和VCC之间加一个4.7kΩ的上拉电阻如果模块上没有的话并确保电源稳定。好了关于在衡山派开发板和RT-Thread上移植DS18B20的整个过程就讲完了。从硬件连接到时序理解再到代码移植和系统集成希望这个详细的教程能帮你顺利把DS18B20用起来。在实际项目中你可以把这个读取线程的优先级设低一点让它安静地在后台工作把读到的温度值放到一个全局变量或者通过消息队列发给其他任务处理非常灵活。