查看: 331|回复: 2

[原创] 【S32K146 RT-thread】之 GPIO 模拟I2C

[复制链接]
  • TA的每日心情
    奋斗
    3 小时前
  • 签到天数: 595 天

    [LV.9]以坛为家II

    51

    主题

    2225

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    7071
    最后登录
    2024-4-28
    发表于 2024-1-7 21:13:48 | 显示全部楼层 |阅读模式
    本帖最后由 andeyqi 于 2024-1-8 09:13 编辑

    之前通过S32K146 硬件I2C适配了RT-thread 的I2C的驱动框架(https://www.nxpic.org.cn/module/forum/thread-802563-1-1.html),但是S32K146 平台在只有一路硬件I2C控制器,如果要使用大于一路I2C,剩下的只能通过GPIO 来模拟,模拟I2C主要依赖PIN驱动,我们已经适配了PIN驱动(https://www.nxpic.org.cn/module/forum/thread-802577-1-1.html),基于PIN 驱动的基础上适配GPIO模拟I2C驱动只需要实现如下几个GPIO相关的函数即可.
    1. #define SET_SDA(ops, val)   ops->set_sda(ops->data, val)
    2. #define SET_SCL(ops, val)   ops->set_scl(ops->data, val)
    3. #define GET_SDA(ops)        ops->get_sda(ops->data)
    4. #define GET_SCL(ops)        ops->get_scl(ops->data)
    复制代码


    有了PIN 驱动的基础上述函数的实现就很容易了。
    • set_sda 函数实现:

    1. /**
    2.   * @brief  This function sets the sda pin.
    3.   * @param  data, state
    4.   * @retval None
    5.   */
    6. static void s32k1xx_set_sda(void *data, rt_int32_t state)
    7. {
    8.     struct s32k1xx_soft_i2c_config* cfg = (struct s32k1xx_soft_i2c_config*)data;
    9.    
    10.     rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
    11.    
    12.     if (state)
    13.     {
    14.         rt_pin_write(cfg->sda, PIN_HIGH);
    15.     }
    16.     else
    17.     {
    18.         rt_pin_write(cfg->sda, PIN_LOW);
    19.     }
    20. }
    复制代码
    • set_scl 函数实现
    1. /**
    2.   * @brief  This function sets the scl pin.
    3.   * @param  data, state
    4.   * @retval None
    5.   */
    6. static void s32k1xx_set_scl(void *data, rt_int32_t state)
    7. {
    8.     struct s32k1xx_soft_i2c_config* cfg = (struct s32k1xx_soft_i2c_config*)data;
    9.    
    10.     rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
    11.    
    12.     if (state)
    13.     {
    14.         rt_pin_write(cfg->scl, PIN_HIGH);
    15.     }
    16.     else
    17.     {
    18.         rt_pin_write(cfg->scl, PIN_LOW);
    19.     }
    20. }
    复制代码

    • get_sda 函数适配
    1. /**
    2.   * @brief  This function gets the sda pin state.
    3.   * @param  data
    4.   * @retval None
    5.   */
    6. static rt_int32_t s32k1xx_get_sda(void *data)
    7. {
    8.     struct s32k1xx_soft_i2c_config* cfg = (struct s32k1xx_soft_i2c_config*)data;
    9.    
    10.     rt_pin_mode(cfg->sda, PIN_MODE_INPUT);
    11.    
    12.     return rt_pin_read(cfg->sda);
    13. }
    复制代码


    • get_scl  函数适配
    1. /**
    2.   * @brief  This function gets the scl pin state.
    3.   * @param  data
    4.   * @retval None
    5.   */
    6. static rt_int32_t s32k1xx_get_scl(void *data)
    7. {
    8.     struct s32k1xx_soft_i2c_config* cfg = (struct s32k1xx_soft_i2c_config*)data;

    9.     rt_pin_mode(cfg->scl,PIN_MODE_INPUT);

    10.     return rt_pin_read(cfg->scl);
    11. }
    复制代码
    从S32K146 的特性头文件可知PORT口 不支持开漏模式,读取scl/sda 接口需要将GPIO切换为输入模式,读取数据前需要切换为输出模式。
    PORT_FEATURE.png

    • 注册接口函数至系统
    1. static const struct rt_i2c_bit_ops s32k1xx_bit_ops_default =
    2. {
    3.     .data     = RT_NULL,
    4.     .set_sda  = s32k1xx_set_sda,
    5.     .set_scl  = s32k1xx_set_scl,
    6.     .get_sda  = s32k1xx_get_sda,
    7.     .get_scl  = s32k1xx_get_scl,
    8.     .udelay   = s32k1xx_udelay,
    9.     .delay_us = 1,
    10.     .timeout  = 100
    11. };

    12. /**
    13.   * @brief  I2C initialization function
    14.   * @param  None
    15.   * @retval RT_EOK indicates successful initialization.
    16.   */
    17. int rt_hw_soft_i2c_init(void)
    18. {
    19.     rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct s32k1xx_i2c);
    20.     rt_err_t result;

    21.     for (int i = 0; i < obj_num; i++)
    22.     {
    23.         i2c_obj[i].ops = s32k1xx_bit_ops_default;
    24.         i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
    25.         i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
    26.         s32k1xx_i2c_gpio_init(&i2c_obj[i]);

    27.         result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);

    28.         RT_ASSERT(result == RT_EOK);

    29.         s32k1xx_i2c_bus_unlock(&soft_i2c_config[i]);

    30.         LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
    31.         soft_i2c_config[i].bus_name,
    32.         soft_i2c_config[i].scl,
    33.         soft_i2c_config[i].sda);
    34.     }

    35.     return RT_EOK;
    36. }
    37. INIT_APP_EXPORT(rt_hw_soft_i2c_init);
    复制代码
    • 在RT-thread 系统中开启soft i2c 驱动框架
    12723_soft_i2c.jpg

    通过menuconfig 配置软件I2C pin 脚
    31351.jpg


    • 使用i2c-tool 工具验证

    基于之前适配的i2c-tool工具(https://www.nxpic.org.cn/module/forum/thread-802558-1-1.html)扫描节点验证发现可以正常通过gpio 模拟的i2c1总线节点读取到节点0x50,说明gpio 模拟的I2C已经正常工作了。

    23648_i2c1.jpg




    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3301

    主题

    6548

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32040
    最后登录
    2024-4-28
    发表于 2024-1-8 11:24:14 | 显示全部楼层
    感谢分享,100篇指日可待
    签到签到
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    3 小时前
  • 签到天数: 595 天

    [LV.9]以坛为家II

    51

    主题

    2225

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    7071
    最后登录
    2024-4-28
     楼主| 发表于 2024-1-8 13:21:49 | 显示全部楼层
    NXP管管 发表于 2024-1-8 11:24
    感谢分享,100篇指日可待

    争取完成     
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-28 13:16 , Processed in 0.115602 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表