MicroPython中I2C模块的设计与实现(1) - machine_i2c框架的机制

本文介绍MicroPython中I2C模块machine_i2c的设计与实现,重点分析了machine_i2c的框架机制及其实现细节,包括init()和transfer_single()等关键函数的作用和移植方法。

MicroPython中I2C模块的设计与实现(1) - machine_i2c框架的机制

苏勇,2022年3月

Introduction

MicroPython在extmod目录下提供了machine_i2c的实现框架,并附带了一个GPIO模拟I2C的实现实例SoftI2C。在本文中,将具体分析machine_i2c的实现框架,以期得到移植machine_i2c的实践方法。在阅读代码的过程中,将专注于machine_i2c的框架,但仍借助于SoftI2C实现的接口描述machine_i2c在具体平台上移植的工作。在后续的文章中,将SoftI2C作为machine_i2c的一个具体实例,与硬件I2C等同,分析SoftI2C的实现,并补完machine_i2c.c文件中需要适配具体硬件平台的部分移植代码。

Algorithm

快速浏览了extmod/machine_i2c.c文件,700多行的代码的源码文件确实比较大。跳过mp_hal_i2c_xxx()和mp_machine_soft_i2c_transfer()函数的部分代码,开始看mp_machine_i2c_xxx()machine_i2c_xxx()系列函数,这部分内容将构成machine_i2c类模块的实现框架。

根据之前分析和设计MicroPython类模块的经验,这里先从实例化类模块的部分代码入手。以machine_i2c.c文件中的SoftI2C为例:

STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
   
   
    {
   
    MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2c_init_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) },

    // primitive I2C operations
    {
   
    MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_i2c_start_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_i2c_stop_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_i2c_readinto_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) },

    // standard bus operations
    {
   
    MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) },

    // memory operations
    {
   
    MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) },
    {
   
    MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) },
};
MP_DEFINE_CONST_DICT(mp_machine_i2c_locals_dict, machine_i2c_locals_dict_table);

STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = {
   
   
    .init = mp_machine_soft_i2c_init,
    .start = (int (*)(mp_obj_base_t *))mp_hal_i2c_start,
    .stop = (int (*)(mp_obj_base_t *))mp_hal_i2c_stop,
    .read = mp_machine_soft_i2c_read,
    .write = mp_machine_soft_i2c_write,
    .transfer = mp_machine_soft_i2c_transfer,
};

const mp_obj_type_t mp_machine_soft_i2c_type = {
   
   
    {
   
    &mp_type_type },
    .name = MP_QSTR_SoftI2C,
    .print = mp_machine_soft_i2c_print,
    .make_new =
### ### 硬件连接配置 ESP32-S3 微控制器支持 I2C 总线协议,可作为主机(Master)从机设备进行通信。要使用 ESP32-S3 BME680 传感器进行 I2C 通信,首先需要正确连接硬件引脚。BME680 是一款集成温度、湿度、压力和气体检测功能的传感器,其通过 I2C 接口传输数据[^1]。 将 BME680 的 SDA 引脚连接到 ESP32-S3 的任意一个 GPIO 引脚,并确保该引脚被配置为 I2C 数据线;同理,将 BME680 的 SCL 引脚连接至另一个 GPIO 引脚,并设置为 I2C 时钟线。此外,BME680 需要上拉电阻以保证信号完整性,通常这些外部组件已经集成在模块设计中。 ### ### 软件初始化流程 在软件层面,开发者可以使用 ESP-IDF 或 MicroPython 来配置 I2C 主机模式。若采用 ESP-IDF 框架,则需调用 `i2c_param_config` 函数来设定 I2C 控制器参数,包括模式选择为主机、指定 SDA 和 SCL 对应的 GPIO 引脚以及设置上拉使能状态等。完成参数配置后,还需调用 `i2c_driver_install` 来安装 I2C 驱动程序,从而启用 I2C 通信功能。 对于 MicroPython 用户而言,可以通过导入 machine 模块中的 I2C 类来进行快速开发。构造 I2C 实例时传入适当的参数,例如频率、SDA 和 SCL 所使用的 Pin 对象等信息即可实现初始化过程。 ### ### 示例代码:ESP-IDF 下的 I2C 初始化 ```c #include "driver/i2c.h" #define I2C_MASTER_SCL_IO 22 /*!< gpio number for I2C master clock */ #define I2C_MASTER_SDA_IO 21 /*!< gpio number for I2C master data */ #define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */ #define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */ void i2c_master_init() { i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ, }; i2c_param_config(I2C_MASTER_NUM, &conf); i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0); } ``` ### ### 示例代码:MicroPython 中的 I2C 初始化 ```python from machine import I2C, Pin # 创建一个I2C实例并设置为主机模式 i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000) # 扫描总线上所有可用的从机地址 addresses = i2c.scan() print("Found I2C devices at addresses:", [hex(addr) for addr in addresses]) ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值