前言
One-wire总线使用一根并联总线完成对于多个设备的访问,通过上拉的OD门实现多设备的读写操作,通过ID区别设备,通过CRC5完成数据校验。常见对于one-wire总线的操作代码主要使用包含基础循环的延时函数实现位读写时序控制,进而实现总线读写(字节读写)。这也产生了以下的问题:
1. 浪费了大量的MCU时钟周期做等待。
2. 在不同编译器优化级别下,设定的延时计数值常量有可能产生不精确的延时。
3. 需要针对时序设定每个状态机的延时参数,参数调整复杂且不稳定。
4. 延时容易被中断任务介入,导致延时不准确,程序功能不稳定
本节将带领大家用单片机的串口实现OneWire总线操作,将stm32的串口的TX引脚与RX引脚短接后与1-Wire总线相连,其理论实现原理如下:
1) 总线复位
1-wrie总线复位时序图
使用9600-8-N-1的UART配置,在TX引脚发送0XF0并在RX引脚读取返回0X10~0X90实现总线复位时序。返回其他值标示总线上无设备挂载。
2) 总线位读操作
1-wrie总线读时序图
使用115200-8-N-1的UART配置,在TX引脚发送0XFF并在RX引脚读取返回0XFF(表示读取bit为1)或其他(表示读取为0)实现总线读时序。
3) 总线位写操作
1-wrie总线读时序图
使用115200-8-N-1的UART配置,在TX引脚发送0XFF并在RX引脚读取返回0XFF(表示写入bit为1)或发送0X00并返回0X00(表示写入为0)实现总线位写时序。
4)DMA方式实现One-wire总线读写实现
除了复位操作外,对于one-wire总线的操作通常以1个字节为读写单位,即连续的8个位操作。如果由用户代码实现多位操作,则需要用户代码不断响应UART中断函数,实现对于UART发送、接收数据寄存器的读写。这会导致代码复杂且打断系统其它操作。而采用DMA方式则很容易实现one-wire总线8bit数据的连续读写。其具体实现原理如下:
a. 设定一个宽度为byte容量为8的缓冲。UART的TX/RX DMA传输存储器地址都指向此缓冲。
b. 对于byte写操作,将要写入的byte通过上述的位写操作将每一bit转换成发送数据byte顺序存入缓冲,启动两个DMA,通过等待RX DMA的完成标志(TC)完成一次写操作。
c. 对于byte读操作,将0xFF连续8次存入缓冲,启动两个DMA,通过等待RX DMA完成标志(TC)完成一次读操作,读取的数据通过上述的位读操作,将bit转换成输出的byte数据。
下面开始具体实现!!
示例详解
基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c8t6, 使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。
本示例所用的最小系统板原理图:
-
- 从本节开始,关于CUBEMX工具及KEIL工具的操作将不再细讲,如果还有不熟悉的可以查看之前的教程文档。下面直接介绍工程配置:
-
-
- 系统时钟树
-
-
-
- 串口配置
-
开启发送DMA
开启中断
同时可以在后面生成代码时高级选项中可以勾选不生成代码:
-
-
- 引脚配置
-
-
- 工程代码
- 加入事先准备好的OneWire.c及.h文件到工程(头文件放在inc文件夹下即可):
- 工程代码
同时在usart.c源文件中加入一个函数,并在头文件中申明函数:
-
-
- 在main.c 中加入如下图所示代码
-
-
- 接上DS18B20温度传感器看一下效果,记理将PA9,PA10引脚短接,仿真查看程序运行结果:
全速运行后可以看到变找到一个DS18B20设备,ROM为:28 2a fa df 0a 00 00 8d,当前温度为27.5度(下图显示2750是放大100倍后的温度)。
可以看到程序功能正常,再来看看用串口实现OneWire总线的代码:
是不是很简单,很清爽!!
OK,本期实验完成!下期见!同时如果大家有什么疑问或是有想了解的其它内容,也欢迎大家留言!!最后喜欢这个公众号的同学们记得加关注了,每天都会有技术干货推出!!
文中资料下载,在公众号里给十三发消息:
下载|STM32进阶教程 20
关注十三公众号