【RTT】I2C总线设备:分析

本文分析了RT-Thread中I2C总线设备的使用,包括硬件资源初始化、软件I2C注册、总线设备注册与初始化、数据传输方法,并以AHT10温湿度传感器为例展示了如何查找和操作I2C总线设备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概要

  一般情况下 MCU 的 I2C 器件都是作为主机和从机通讯,在 RT-Thread 中将 I2C 主机虚拟为 I2C 总线设备, I2C 从机通过 I2C 设备接口和 I2C 总线通讯。
   注:手头上的板子是正点原子的潘多拉,所以在这个潘多拉的bsp基础上进行分析
   水平有限,仅供参考

  首先,要确定是使用硬件I2C还是软件I2C,这个可以看配置菜单来确定,这里,可以在bsp对应的目录下调用env命令窗口,输入menuconfig即可。
在这里插入图片描述

  

一、I2C硬件资源初始化

  由于是使用软件I2C,对于stm32,硬件相关初始化定义在在/bsp/stm32/libraries/HAL_Drivers/drv_soft_i2c.c文件中。

int rt_hw_i2c_init(void)
{
   
    rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct stm32_i2c);
    rt_err_t result;

    for (int i = 0; i < obj_num; i++)
    {
   
        /* 操作包括set_sda set_scl get_sda get_scl udelay */
        i2c_obj[i].ops = stm32_bit_ops_default;
       
         /* 数据包括scl_pin sda_pin bus_name */
        i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
        i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
       
         /* 配置引脚功能 */
        stm32_i2c_gpio_init(&i2c_obj[i]);
        
        /* 注册到i2c总线上 */
        result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);
        RT_ASSERT(result == RT_EOK);
        stm32_i2c_bus_unlock(&soft_i2c_config[i]);
    }
    return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_i2c_init);

  在rt_hw_i2c_init函数中,我们发现,其所调用的注册函数是rt_i2c_bit_add_bus。那么,我们就去看下这个函数。

  

二、软件I2C的注册函数

  rt_i2c_bit_add_bus函数定义在i2c-bit-ops.c文件中,i2c-bit-ops.c文件主要实现了利用GPIO模拟IIC总线时序的相关接口函数。

### RTT HAL I2C 实现及相关问题 RT-Thread 是一个实时操作系统,其硬件抽象层(HAL)提供了对多种外设的支持,其中包括 I2C 接口。以下是关于 RTT HAL I2C 的实现细节以及可能遇到的问题。 #### 1. **I2C 基本功能** RT-Thread 提供了一套统一的 API 来操作 I2C 设备。这些接口允许开发者轻松配置和控制 I2C 总线上的设备通信。核心函数包括初始化、发送数据、接收数据等功能[^4]。 ```c // 初始化 I2C 设备 rt_err_t rt_i2c_bus_device_init(rt_i2c_bus_device_t bus, const char *name); // 发送数据到指定地址 rt_size_t rt_i2c_master_send(rt_i2c_bus_device_t bus, rt_uint16_t addr, struct rt_i2c_msg msgs[], rt_uint32_t num); ``` 上述代码展示了如何通过 `rt_i2c_bus_device_init` 函数初始化 I2C 总线,并使用 `rt_i2c_master_send` 进行数据传输[^4]。 #### 2. **多字节读写支持** 对于需要连续读取多个寄存器的情况,RT-Thread 支持链式消息结构体 (`struct rt_i2c_msg`),可以定义一系列的消息并一次性完成复杂的读写操作[^5]。 ```c struct rt_i2c_msg { rt_uint16_t addr; /* slave address */ rt_uint8_t flags; #define RT_I2C_RD 0x0001 /* this is a read message */ #define RT_I2C_WR 0 /* this is a write message */ rt_uint8_t len; /* msg length */ rt_uint8_t *buf; /* pointer to msg data */ }; ``` 此结构使得复杂的数据交互更加高效且易于管理[^5]。 #### 3. **常见问题及解决方案** ##### (1)**时序错误** 某些微控制器可能存在严格的时钟周期要求。如果目标器件无法及时响应,则可能导致超时或其他异常行为。可以通过调整 SCL 频率来解决此类问题[^6]。 ```c bus->config.freq = RT_I2C_FREQ_STANDARD_MAX; // 设置标准模式频率 ``` ##### (2)**NACK 错误** 当从设备未能正确接收到起始信号或者不认可当前地址时会返回 NACK。这通常是因为地址设置有误或是硬件连接存在问题[^7]。 建议检查以下几点: - 确认使用的七位或十位寻址方式是否匹配实际需求; - 测试线路是否存在短路现象。 ##### (3)**中断丢失** 部分平台依赖于中断机制驱动 I2C 数据流,在高负载环境下容易发生丢包情况。此时应考虑优化任务优先级分配策略或将关键部分改为轮询模式运行[^8]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值