打印
[其他ST产品]

STM32基于onewire单总线的数据抽象实例

[复制链接]
179|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jcky001|  楼主 | 2023-10-27 14:40 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 jcky001 于 2023-10-27 14:50 编辑

1.前言onewire(单总线) 是DALLAS公司推出的外围串行扩展总线技术总线,顾名思义,它是采用一根信号线进行通信,既传输时钟信号又传输数据,而且能够进行双向通信,具有节省I/O口线、资源结构简单、成本低廉、便于总线扩展和维护等诸多优点。
常用到单总线的器件,一般是温度传感器、EEPROM、唯一序列号芯片等,如DS18B20、DS2431。在使用单总线时,往往很少CPU会提供硬件单总线,几乎都是根据单总线标准的时序图,通过普通IO翻转模拟实现单总线。而在模式实现时序图的过程中,需要根据CPU时钟频率等条件进行时序时间计算,如果更换CPU后,需要重新计算时序时间,如果时序代码和器件外设控制代码集成在一起,则代码改动比较大。或者同一CPU需要模拟多根单总线时,传统的“复制”方式使得程序显得累赘,还增加ROM占用空间。因此,可以利用“函数指针”的方式,将时序部分抽象出来,达到“复用”代码的效果,减少重复代码编写。

2.onewire 抽象
2.1 onewire 结构体
onewire结构体主要是对与CPU底层相关的操作抽象分离,调用时只需将该结构体地址(指针)作为函数入口参数,通过该指针实现对底层函数的回调。该结构体我们命名为“struct ops_onewire_dev”,其原型如下:



其中: 1)set_sdo:IO输出1bit,包括时钟和数据。
2)get_sdo:IO输入1bit,包括时钟和数据。


3)delayus:时序延时函数,根据CPU频率进行计算。回调函数相关文章:C语言技巧之回调函数
2.2 onewire 对外接口


1)分别为复位函数、读函数、写函数。
2)入口首参数为“struct ops_onewire_dev”结构体指针,此部分就是硬件层相关,需要后期初始化的.
3)其余入口参数易于理解,读/写缓存及数据大小。


使用特权

评论回复
沙发
jcky001|  楼主 | 2023-10-27 14:44 | 只看该作者
2.3 onewire 抽象接口实现分别实现上述三者函数接口。2.3.1 复位函数复位函数,在单总线初始化外设器件时需要用到,用于判断总线与器件是否通信上,类似“握手”的动作。如图,为DS18B20的复位时序图,以下与单总线相关的时序图,都是以DS18B20为例,因为此芯片为单总线应用的经典。
根据时序图,实现复位函数。

2.3.2 读函数读函数即以该函数,通过单总线从外设上读取数据,至于代码的实现,完全是时序图的实现,无特殊难点。先实现单字节读函数,再通过调用单字节读函数实现多字节读函数。



使用特权

评论回复
板凳
jcky001|  楼主 | 2023-10-27 14:46 | 只看该作者
至此,onewire(单总线)抽象化完成,此部分代码与硬件层分离,亦可单独作为一个模块,移植到不同平台CPU时,也几乎无需改动。剩下部分工作则是实现“struct ops_onewire_dev”中的函数指针原型,即可使用一根单总线。

3.onewire 抽象应用以STM32F1为例,实现上述抽象接口。
3.1 “struct ops_onewire_dev” 实现此部分即是与硬件相关部分,不同CPU平台改动该部分即可,如从51单片机移植到STM32上。下面涉及到的IO宏,是对应IO的宏定义,如“ONEWIRE1_PORT”、“ONEWIRE1_PIN”,实际使用的是PC13 IO口。
3.1.1 IO输出


3.2 onewire 总线初始化3.2.1 onewire 抽象相关
第一步:定义一个“struct ops_onewire_dev”结构体类型变量(全局)——onewire1_dev。

第二步:实例化“onewire1_dev”中的函数指针。onewire1_dev.get_sdo = gpio_get_sdo;
onewire1_dev.set_sdo = gpio_set_sdo;
onewire1_dev.delayus = gpio_delayus;
第三步:使用时,通过传入“onewire1_dev”地址(指针)即可。

3.2.2 onewire 基础相关初始基础部分,与使用的CPU硬件相关,如时钟、IO方向等。




使用特权

评论回复
地板
jcky001|  楼主 | 2023-10-27 14:49 | 只看该作者
4.onewire 使用经过前面的步骤后,我们已经通过IO口翻转,模拟实现了一根单总线——“onewire1_dev”,以DS18B20为例,调用第一部分中三者接口,实现对DS18B20的操作。4.1 DS18B20操作对于DS18B20,不陌生,即是温度传感器,不多赘述,使用的功能主要是作为温度检测,另外还有其内部的唯一序列号会作为同一总线上挂多个DS18B20时的“地址”识别。亦可把DS18B20的唯一序列号作为模块、产品、通信总线等的唯一标识使用。因此,代码也是主要实现这两个功能。 至此,完成单总线的抽象分层使用。源码:https://github.com/Prry/drivers-for-mcu来源:https://acuity.blog.csdn.net/article/

使用特权

评论回复
5
Bblythe| | 2023-12-10 07:06 | 只看该作者

ART2固定使用PCLK时钟,只有开启和关闭的问题,不存在其它时钟源选择

使用特权

评论回复
6
童雨竹| | 2023-12-10 09:02 | 只看该作者

控制模块的时钟仍然由外设时钟PCLK提供

使用特权

评论回复
7
Pulitzer| | 2023-12-10 10:05 | 只看该作者

USART1可以有多个时钟源

使用特权

评论回复
8
公羊子丹| | 2023-12-10 11:08 | 只看该作者

STM32CUBEMX配置生成初始化代码

使用特权

评论回复
9
公羊子丹| | 2023-12-10 12:01 | 只看该作者

要把纹波电流平均分布

使用特权

评论回复
10
Wordsworth| | 2023-12-10 13:04 | 只看该作者

通过访问寄存器来控制I2C1工作时钟的开启。

使用特权

评论回复
11
Wordsworth| | 2023-12-10 13:04 | 只看该作者

通过访问寄存器来控制I2C1工作时钟的开启。

使用特权

评论回复
12
Clyde011| | 2023-12-10 14:07 | 只看该作者

I2C1的时钟可以自行选择HSI或者SYSCLK

使用特权

评论回复
13
万图| | 2023-12-10 16:03 | 只看该作者

I2C1工作时钟源选择;I2C1模块工作时钟的开启使能。

使用特权

评论回复
14
Uriah| | 2023-12-10 17:06 | 只看该作者

STM32芯片中有多个工作时钟源的外设很常见

使用特权

评论回复
15
帛灿灿| | 2023-12-10 19:02 | 只看该作者

CPU借助于APB总线访问相关寄存器达到对I2C1工作模块的控制

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1414

主题

3814

帖子

5

粉丝