Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
I2C_IIC
STM32H7
设备驱动
stm32 硬件i2c设计基于stm32h750
发布于 2024-02-17 21:16:28 浏览:970
订阅该版
[tocm] # 设计考虑——RTThread I2C设备 参考RTThread版本 当前最新版本master分支v5.0.2 i2c驱动框架包含三个文件分别是 ![屏幕截图 2024-02-17 182655.png](https://oss-club.rt-thread.org/uploads/20240217/afbd38eb01e06b1dbd48bffd14df71cf.png) 用pin设备模拟i2c时序并且对接i2c设备框架的 ` i2c_bit-ops.c` ```c //不是本次讨论重点 ``` 负责提供i2c框架通用接口函数和注册总线设备到rtt设备框架的i2c核心/框架 ` i2c_core.c` ![屏幕截图 2024-02-17 183154.png](https://oss-club.rt-thread.org/uploads/20240217/00dfe039014e2221b75acba4a846a327.png) 负责提供的i2c设备驱动 ` i2c_dev.c` ![屏幕截图 2024-02-17 183512.png](https://oss-club.rt-thread.org/uploads/20240217/14de304f24b48a9dde66657b7d406930.png) 其中dev依赖于bus的传输函数,相当于套了一个壳,装饰一下,同时RTT没有明确的总线->设备概念,可能是为了简化或者其他原因,设备和总线使用同一个结构体,个人偏向是一个是对接device 向上层提供read write 一个面向驱动提供 `rt_i2c_transfer`之类的代码 ## RTThread I2C驱动编写关注点 ### control ``` static rt_err_t i2c_bus_device_control(rt_device_t dev, int cmd, void *args) { rt_err_t ret; struct rt_i2c_priv_data *priv_data; struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)dev->user_data; RT_ASSERT(bus != RT_NULL); switch (cmd) { /* set 10-bit addr mode */ case RT_I2C_DEV_CTRL_10BIT: bus->flags |= RT_I2C_ADDR_10BIT; break; case RT_I2C_DEV_CTRL_TIMEOUT: bus->timeout = *(rt_uint32_t *)args; break; case RT_I2C_DEV_CTRL_RW: priv_data = (struct rt_i2c_priv_data *)args; ret = rt_i2c_transfer(bus, priv_data->msgs, priv_data->number); if (ret < 0) { return -RT_EIO; } break; default: return rt_i2c_control(bus, cmd, args); } return RT_EOK; } ``` 注意到提供10bit 地址控制模式,读写和控制参数向下级传递尝试获取支持(说明驱动程序可以自己编写控制函数提供独特的控制) ### xfer `ret = bus->ops->master_xfer(bus, msgs, num);` 这句code表明驱动需要实现同时与 `ret = bus->ops->i2c_bus_control(bus, cmd, args);` 分析表明我们要编写的驱动大概率就是ops里面定义的函数 ### `struct rt_i2c_bus_device_ops` ``` struct rt_i2c_bus_device_ops { rt_ssize_t (*master_xfer)(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); rt_ssize_t (*slave_xfer)(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); rt_err_t (*i2c_bus_control)(struct rt_i2c_bus_device *bus, int cmd, void *args); }; ``` 我们看到ops要我们实现三个函数,但是slave_xfsr在框架里面并没有实现,推测对于i2c slave的开发进度缓慢 现在我们已经清楚要如何编写一个rtt i2c 设备驱动,我们再来看看stm32 ## STM32 HAL库下的I2C 这里使用 STM32Cube_FW_H7_V1.11.1 包进行参考 board使用正点原子北极星stm32h750xhb6核心板验证(artpi同款芯片) bsp工程继承自artpi 参考文档 STM32H7xx参考手册(V3中文版 和 STM32H750勘误手册 由于对于f1等芯片新版本的i2c有一个比较大的变化就是timing寄存器 对于timing的描述是这样的 ![屏幕截图 2024-02-17 191523.png](https://oss-club.rt-thread.org/uploads/20240217/3c4eb9e170567dc24dd88c0541e90f78.png.webp) ![屏幕截图 2024-02-17 191643.png](https://oss-club.rt-thread.org/uploads/20240217/a6b41bfa9c807146557c9677571cbe8c.png.webp) ![屏幕截图 2024-02-17 191711.png](https://oss-club.rt-thread.org/uploads/20240217/690e02a199bdcf9398740d1e3695793d.png.webp) 可以看到目前感觉自动计算timing值还比较麻烦,那不如直接使用cubemx计算,官方也是如此推荐的 初始化就注意这个 ### HAL库函数 ``` HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); ``` 我们关注seq函数,值得注意的是对于阻塞模式并没有提供这些函数,虽然可以通过mem系列函数模拟或者直接寄存器实现但是考虑复杂性和通用性故放弃阻塞驱动编写,直接使用中断模式,后续也能十分方便的扩展到dma模式 ``` #define I2C_FIRST_FRAME ((uint32_t)I2C_SOFTEND_MODE) #define I2C_FIRST_AND_NEXT_FRAME ((uint32_t)(I2C_RELOAD_MODE | I2C_SOFTEND_MODE)) #define I2C_NEXT_FRAME ((uint32_t)(I2C_RELOAD_MODE | I2C_SOFTEND_MODE)) #define I2C_FIRST_AND_LAST_FRAME ((uint32_t)I2C_AUTOEND_MODE) #define I2C_LAST_FRAME ((uint32_t)I2C_AUTOEND_MODE) #define I2C_LAST_FRAME_NO_STOP ((uint32_t)I2C_SOFTEND_MODE) ``` ``` #define I2C_RELOAD_MODE I2C_CR2_RELOAD #define I2C_AUTOEND_MODE I2C_CR2_AUTOEND #define I2C_SOFTEND_MODE (0x00000000U) ``` 可以看到xferOption提供的宏和对应扩展,softend 表示不产生stop信号 reload 不产生addr传输 ## 代码编写 先验证hal库驱动板载at24c02 ``` static uint8_t data[256] ={ 32}; HAL_I2C_Master_Seq_Transmit_IT(hi2c2, 0xa0, &(data[0]), 1, I2C_FIRST_FRAME); if(rt_completion_wait(completion, 100)!=RT_EOK){ LOG_E("time out1"); } //osDelay(1); // HAL_I2C_Master_Seq_Transmit_IT(hi2c2,0xa1,0xff,1,I2C_LAST_FRAME_NO_STOP); HAL_I2C_Master_Seq_Receive_IT(hi2c2, 0xa0, &(data[0]), 128, I2C_FIRST_AND_NEXT_FRAME); if (rt_completion_wait(completion, 100) != RT_EOK) { LOG_E("time out2"); } HAL_I2C_Master_Seq_Receive_IT(hi2c2, 0xa0, &(data[128]), 128, I2C_LAST_FRAME); if (rt_completion_wait(completion, 100) != RT_EOK) { LOG_E("time out4"); } ``` 将数据打印出来显然是对的,没有截图 然后编写rtt驱动 参考模拟驱动的编写和硬件spi编写方式 代码过长,直接提供链接 [GitHub](https://github.com/Dyyt587/rtthread_hardware_i2c_driver "GitHub") 完成基本驱动后进行测试 ``` rt_ssize_t ret; struct rt_i2c_msg msg[3]; uint8_t addr=0; msg[0].addr = 0xa0; msg[0].flags = RT_I2C_WR; msg[0].len = 1; msg[0].buf = &addr; msg[1].addr = 0xa0; msg[1].flags = RT_I2C_RD; msg[1].len = 128; msg[1].buf = &data[0]; msg[2].addr = 0xa0; msg[2].flags = RT_I2C_NO_START|RT_I2C_RD; msg[2].len = 128; msg[2].buf = &data[128]; ret = rt_i2c_transfer(&i2c_drv->i2c_bus, msg, sizeof(msg)/sizeof(struct rt_i2c_msg)); LOG_HEX("data",16,data,sizeof(data)); ``` 打印数据进行查看 ![屏幕截图 2024-02-17 194549.png](https://oss-club.rt-thread.org/uploads/20240217/1b8f251fa6dae1db1512f40cec0b3b1c.png) 数据符合,实现初代版本,简单添加dma相关配置,但未验证 存在细小bug,优化中
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
dyyt
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
NXP的I2C应该比ST的好用吧
2
Use of I2C device driver
3
关于I2C 驱动问题请教
4
我如何知道这个iic的io配置和我电路设计的是一致的?
5
I2C模拟读操作失败,不知道问什么进不去读函数
6
RTT的I2C有官方文档资料没有
7
求 STM32F103 IIC 自定义IO初始化 代码
8
报一个LPC4008代码中I2C的bug
9
RTOS IIC总线使用
10
关于在RTT中使用STM32 I2C的疑问
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
国产MCU移植系列教程汇总,欢迎查看!
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
文件系统
DMA
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
ota在线升级
WIZnet_W5500
UART
flash
packages_软件包
cubemx
PWM
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
中断
flashDB
socket
Debug
GD32
编译报错
msh
keil_MDK
at_device
rt_mq_消息队列_msg_queue
ulog
C++_cpp
SFUD
本月问答贡献
出出啊
1512
个答案
341
次被采纳
小小李sunny
1437
个答案
289
次被采纳
张世争
774
个答案
167
次被采纳
crystal266
546
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部