IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> RT-Thread Nano如何适配I2C设备API,并在RT-Thread Nano使用软件包 -> 正文阅读

[嵌入式]RT-Thread Nano如何适配I2C设备API,并在RT-Thread Nano使用软件包

本文介绍了如何在 RT-Thread Studio 上使用 RT-Thread Nano,并基于 BearPI-IOT STM32L431RCT6 的基础工程进行讲解如何使用 I2C 设备接口及相关软件包使用。

BearPI-IOT board

为什么需要设备接口

  1. RT-Thread 分为标准版本和 Nano 版本,其特点如下:

  • RT-Thread 标准版:拥有设备驱动框架,软件包等组件,软件包都是基于设备驱动接口来实现。

  • RT-Thread Nano:仅仅只是一个 RTOS 内核。没有任何组件。

  • Nano 是无法直接使用 RT-Thread 丰富软件包功能。

  • Nano 是一个面向低资源的 MCU 等芯片,不可能增加如同标准版的设备驱动框架。

  • Nano 需要一套统一设备驱动 API,屏蔽不同芯片的 HAL 层的区别。方便移植工程到不同的平台。

  • Nano 需要一套设备驱动 API,可以方便使用丰富软件包组件。

  • 准备工作

    1. 使用 RT-Thread Studio 建立一个 STM32L431RCT6 的 RT-Thread Nano 基础工程。

    2. 基础工程创建可参考:在 RT-Thread Studio 上使用 RT-Thread Nano

    I2C 设备接口

    1. 在 RT-Thread 标准版中,I2C设备驱动提供了一套设备管理接口来访问 I2C,用户程序可以直接使用该 API 操作 I2C 的功能,设备管理接口如下:

    「函数」「描述」
    rt_device_find()根据 I2C 总线设备名称查找设备获取设备句柄
    rt_i2c_transfer()传输数据

    1. 由于 RT-Thread Nano 不使用设备驱动框架,所以没有对应的 rt_device_find() 这个 API 获取设备对象。但 RT-Thread 标准版实际为用户层提供了另外一套 API 给用户层使用。设备管理接口如下:

    「函数」「描述」
    rt_i2c_bus_device_find()根据 I2C 总线设备名称查找设备获取设备句柄
    rt_i2c_transfer()传输数据
    rt_i2c_master_send()发送数据
    rt_i2c_master_recv()接收数据

    1. 对于 RT-Thread Nano,只需要适配如上这套 API,便可简单修改后使用 RT-Thread 丰富软件包功能。

    适配 I2C 设备接口

    1. 复制 RT-Thread 完整版工程中的 i2c.h 文件(路径:rt-thread\components\drivers\include\drivers\i2c.h)到我们准备好的 STM32L431RCT6 的 RT-Thread Nano 基础工程中。

    2. 由于 RT-Thread Nano 没有设备驱动框架,所以我们要把 i2c.h 中有关完整版的内容去掉。整理完之后的 i2c.h 文件如下:

    /*
    ?*?Copyright?(c)?2006-2021,?RT-Thread?Development?Team
    ?*
    ?*?SPDX-License-Identifier:?Apache-2.0
    ?*
    ?*?Change?Logs:
    ?*?Date???????????Author????????Notes
    ?*?2021-04-20?????RiceChen??????first?version
    ?*/
    
    #ifndef?__I2C_H__
    #define?__I2C_H__
    
    #include?<rtthread.h>
    
    #ifdef?__cplusplus
    extern?"C"?{
    #endif
    
    #define?RT_I2C_WR????????????????0x0000
    #define?RT_I2C_RD???????????????(1u?<<?0)
    #define?RT_I2C_ADDR_10BIT???????(1u?<<?2)??/*?this?is?a?ten?bit?chip?address?*/
    #define?RT_I2C_NO_START?????????(1u?<<?4)
    #define?RT_I2C_IGNORE_NACK??????(1u?<<?5)
    #define?RT_I2C_NO_READ_ACK??????(1u?<<?6)??/*?when?I2C?reading,?we?do?not?ACK?*/
    #define?RT_I2C_NO_STOP??????????(1u?<<?7)
    
    struct?rt_i2c_config
    {
    ????char?*name;
    ????rt_uint8_t?scl;
    ????rt_uint8_t?sda;
    };
    
    struct?rt_i2c_msg
    {
    ????rt_uint16_t?addr;
    ????rt_uint16_t?flags;
    ????rt_uint16_t?len;
    ????rt_uint8_t??*buf;
    };
    
    /*for?i2c?bus?driver*/
    struct?rt_i2c_bus_device
    {
    ????struct?rt_i2c_config?*config;
    ????rt_uint16_t??flags;
    ????rt_uint16_t??addr;
    ????struct?rt_mutex?lock;
    ????rt_uint32_t??timeout;
    ????rt_uint32_t??retries;
    ????void?*priv;
    };
    
    struct?rt_i2c_bus_device?*rt_i2c_bus_device_find(const?char?*bus_name);
    rt_size_t?rt_i2c_transfer(struct?rt_i2c_bus_device?*bus,
    ??????????????????????????struct?rt_i2c_msg?????????msgs[],
    ??????????????????????????rt_uint32_t???????????????num);
    rt_err_t?rt_i2c_control(struct?rt_i2c_bus_device?*bus,
    ????????????????????????rt_uint32_t???????????????cmd,
    ????????????????????????rt_uint32_t???????????????arg);
    rt_size_t?rt_i2c_master_send(struct?rt_i2c_bus_device?*bus,
    ?????????????????????????????rt_uint16_t???????????????addr,
    ?????????????????????????????rt_uint16_t???????????????flags,
    ?????????????????????????????const?rt_uint8_t?????????*buf,
    ?????????????????????????????rt_uint32_t???????????????count);
    rt_size_t?rt_i2c_master_recv(struct?rt_i2c_bus_device?*bus,
    ?????????????????????????????rt_uint16_t???????????????addr,
    ?????????????????????????????rt_uint16_t???????????????flags,
    ?????????????????????????????rt_uint8_t???????????????*buf,
    ?????????????????????????????rt_uint32_t???????????????count);
    
    rt_inline?rt_err_t?rt_i2c_bus_lock(struct?rt_i2c_bus_device?*bus,?rt_tick_t?timeout)
    {
    ????return?rt_mutex_take(&bus->lock,?timeout);
    }
    
    rt_inline?rt_err_t?rt_i2c_bus_unlock(struct?rt_i2c_bus_device?*bus)
    {
    ????return?rt_mutex_release(&bus->lock);
    }
    
    int?rt_i2c_core_init(void);
    
    #ifdef?__cplusplus
    }
    #endif
    
    #endif
    
    
    1. 我们需要适配如上6个 I2C 设备 API ,参考实例:

    「函数」「描述」
    rt_i2c_core_init()I2C 总线初始化
    rt_i2c_bus_device_find()根据 I2C 总线设备名称查找设备获取设备句柄
    rt_i2c_transfer()数据传输
    rt_i2c_control()I2C 总线配置
    rt_i2c_master_send()发送数据
    rt_i2c_master_recv()接收数据

    • drv_i2c.c

    /*
    ?*?Copyright?(c)?2006-2021,?RT-Thread?Development?Team
    ?*
    ?*?SPDX-License-Identifier:?Apache-2.0
    ?*
    ?*?Change?Logs:
    ?*?Date???????????Author????????????Notes
    ?*?2021-08-21?????RiceChen?????the?first?version
    ?*/
    
    #include?<board.h>
    #include?"drv_i2c.h"
    
    #ifdef?RT_USING_I2C
    
    enum
    {
    #ifdef?RT_USING_I2C1
    ????I2C1_INDEX,
    #endif
    #ifdef?RT_USING_I2C2
    ????I2C2_INDEX,
    #endif
    };
    
    static?struct?rt_i2c_config?i2c_config[]?=
    {
    #ifdef?RT_USING_I2C1
    ?????RT_I2C1_CONFIG,
    #endif
    #ifdef?RT_USING_I2C2
    ?????RT_I2C1_CONFIG
    #endif
    };
    
    static?struct?rt_i2c_bus_device?i2c_bus[sizeof(i2c_config)?/?sizeof(i2c_config[0])]?=?{0};
    
    static?void?rt_i2c_configure(struct?rt_i2c_bus_device?*bus)
    {
    ????rt_uint8_t?scl_pin?=?bus->config->scl;
    ????rt_uint8_t?sda_pin?=?bus->config->sda;
    
    ????rt_pin_mode(scl_pin,?PIN_MODE_OUTPUT_OD);
    ????rt_pin_mode(sda_pin,?PIN_MODE_OUTPUT_OD);
    
    ????rt_pin_write(scl_pin,?PIN_HIGH);
    ????rt_pin_write(sda_pin,?PIN_HIGH);
    }
    
    static?void?rt_i2c_set_sda(struct?rt_i2c_bus_device?*bus,?rt_uint32_t?state)
    {
    ????rt_uint8_t?sda_pin?=?bus->config->sda;
    
    ????if?(state)
    ????{
    ????????rt_pin_write(sda_pin,?PIN_HIGH);
    ????}
    ????else
    ????{
    ????????rt_pin_write(sda_pin,?PIN_LOW);
    ????}
    }
    
    static?void?rt_i2c_set_scl(struct?rt_i2c_bus_device?*bus,?rt_uint32_t?state)
    {
    ????rt_uint8_t?scl_pin?=?bus->config->scl;
    
    ????if?(state)
    ????{
    ????????rt_pin_write(scl_pin,?PIN_HIGH);
    ????}
    ????else
    ????{
    ????????rt_pin_write(scl_pin,?PIN_LOW);
    ????}
    }
    
    static?rt_uint32_t?rt_i2c_get_sda(struct?rt_i2c_bus_device?*bus)
    {
    ????rt_uint8_t?sda_pin?=?bus->config->sda;
    
    ????return?rt_pin_read(sda_pin);
    }
    
    static?rt_uint32_t?rt_i2c_get_scl(struct?rt_i2c_bus_device?*bus)
    {
    ????rt_uint8_t?scl_pin?=?bus->config->scl;
    
    ????return?rt_pin_read(scl_pin);
    }
    
    static?void?rt_i2c_udelay(rt_uint32_t?us)
    {
    ????rt_hw_us_delay(us);
    }
    
    #define?SET_SDA(bus,?val)???rt_i2c_set_sda(bus,?val)
    #define?SET_SCL(bus,?val)???rt_i2c_set_scl(bus,?val)
    #define?GET_SDA(bus)????????rt_i2c_get_sda(bus)
    #define?GET_SCL(bus)????????rt_i2c_get_scl(bus)
    
    #define?SDA_L(bus)??????????SET_SDA(bus,?0)
    #define?SDA_H(bus)??????????SET_SDA(bus,?1)
    #define?SCL_L(bus)??????????SET_SCL(bus,?0)
    
    static?rt_err_t?SCL_H(struct?rt_i2c_bus_device?*bus)
    {
    ????rt_tick_t?start;
    
    ????SET_SCL(bus,?1);
    
    ????if(rt_i2c_get_scl(bus))
    ????{
    ????????goto?done;
    ????}
    
    ????start?=?rt_tick_get();
    ????while?(!GET_SCL(bus))
    ????{
    ????????if?((rt_tick_get()?-?start)?>?100)
    ????????????return?-RT_ETIMEOUT;
    ????????rt_thread_delay(100);
    ????}
    done:
    ????rt_i2c_udelay(1);
    
    ????return?RT_EOK;
    }
    
    static?void?rt_i2c_start(struct?rt_i2c_bus_device?*bus)
    {
    ????SDA_L(bus);
    ????rt_i2c_udelay(1);
    ????SCL_L(bus);
    }
    
    static?void?rt_i2c_restart(struct?rt_i2c_bus_device?*bus)
    {
    ????SDA_H(bus);
    ????SCL_H(bus);
    ????rt_i2c_udelay(1);
    
    ????SDA_L(bus);
    ????rt_i2c_udelay(1);
    ????SCL_L(bus);
    }
    
    static?void?rt_i2c_stop(struct?rt_i2c_bus_device?*bus)
    {
    ????SDA_L(bus);
    ????rt_i2c_udelay(1);
    ????SCL_H(bus);
    ????rt_i2c_udelay(1);
    ????SDA_H(bus);
    ????rt_i2c_udelay(1);
    }
    
    rt_inline?rt_bool_t?rt_i2c_waitack(struct?rt_i2c_bus_device?*bus)
    {
    ????rt_bool_t?ack;
    
    ????SDA_H(bus);
    ????rt_i2c_udelay(1);
    
    ????if?(SCL_H(bus)?<?0)
    ????{
    ????????return?-RT_ETIMEOUT;
    ????}
    ????ack?=?!GET_SDA(bus);
    ????SCL_L(bus);
    
    ????return?ack;
    }
    
    static?rt_int32_t?rt_i2c_writeb(struct?rt_i2c_bus_device?*bus,?rt_uint8_t?data)
    {
    ????rt_int32_t?i;
    ????rt_uint8_t?bit;
    
    ????for?(i?=?7;?i?>=?0;?i--)
    ????{
    ????????SCL_L(bus);
    ????????bit?=?(data?>>?i)?&?1;
    ????????SET_SDA(bus,?bit);
    ????????rt_i2c_udelay(1);
    ????????if?(SCL_H(bus)?<?0)
    ????????{
    ????????????return?-RT_ETIMEOUT;
    ????????}
    ????}
    ????SCL_L(bus);
    ????rt_i2c_udelay(1);
    
    ????return?rt_i2c_waitack(bus);
    }
    
    static?rt_int32_t?rt_i2c_readb(struct?rt_i2c_bus_device?*bus)
    {
    ????rt_uint8_t?i;
    ????rt_uint8_t?data?=?0;
    
    ????SDA_H(bus);
    ????rt_i2c_udelay(1);
    ????for?(i?=?0;?i?<?8;?i++)
    ????{
    ????????data?<<=?1;
    ????????if?(SCL_H(bus)?<?0)
    ????????{
    ????????????return?-RT_ETIMEOUT;
    ????????}
    ????????if?(GET_SDA(bus))
    ????????????data?|=?1;
    ????????SCL_L(bus);
    ????????rt_i2c_udelay(1);
    ????}
    
    ????return?data;
    }
    
    static?rt_size_t?rt_i2c_send_bytes(struct?rt_i2c_bus_device?*bus,
    ???????????????????????????????????struct?rt_i2c_msg?*msg)
    {
    ????rt_int32_t?ret;
    ????rt_size_t?bytes?=?0;
    ????const?rt_uint8_t?*ptr?=?msg->buf;
    ????rt_int32_t?count?=?msg->len;
    ????rt_uint16_t?ignore_nack?=?msg->flags?&?RT_I2C_IGNORE_NACK;
    
    ????while?(count?>?0)
    ????{
    ????????ret?=?rt_i2c_writeb(bus,?*ptr);
    
    ????????if?((ret?>?0)?||?(ignore_nack?&&?(ret?==?0)))
    ????????{
    ????????????count?--;
    ????????????ptr?++;
    ????????????bytes?++;
    ????????}
    ????????else?if?(ret?==?0)
    ????????{
    ????????????return?0;
    ????????}
    ????????else
    ????????{
    ????????????return?ret;
    ????????}
    ????}
    
    ????return?bytes;
    }
    
    static?rt_err_t?rt_i2c_send_ack_or_nack(struct?rt_i2c_bus_device?*bus,?int?ack)
    {
    ????if?(ack)
    ????????SET_SDA(bus,?0);
    ????rt_i2c_udelay(1);
    ????if?(SCL_H(bus)?<?0)
    ????{
    ????????return?-RT_ETIMEOUT;
    ????}
    ????SCL_L(bus);
    
    ????return?RT_EOK;
    }
    
    static?rt_size_t?rt_i2c_recv_bytes(struct?rt_i2c_bus_device?*bus,
    ???????????????????????????????????struct?rt_i2c_msg?*msg)
    {
    ????rt_int32_t?val;
    ????rt_int32_t?bytes?=?0;???/*?actual?bytes?*/
    ????rt_uint8_t?*ptr?=?msg->buf;
    ????rt_int32_t?count?=?msg->len;
    ????const?rt_uint32_t?flags?=?msg->flags;
    
    ????while?(count?>?0)
    ????{
    ????????val?=?rt_i2c_readb(bus);
    ????????if?(val?>=?0)
    ????????{
    ????????????*ptr?=?val;
    ????????????bytes?++;
    ????????}
    ????????else
    ????????{
    ????????????break;
    ????????}
    
    ????????ptr?++;
    ????????count?--;
    ????????if?(!(flags?&?RT_I2C_NO_READ_ACK))
    ????????{
    ????????????val?=?rt_i2c_send_ack_or_nack(bus,?count);
    ????????????if?(val?<?0)
    ????????????????return?val;
    ????????}
    ????}
    
    ????return?bytes;
    }
    
    static?rt_int32_t?rt_i2c_send_address(struct?rt_i2c_bus_device?*bus,
    ??????????????????????????????????????rt_uint8_t?addr,?rt_int32_t?retries)
    {
    ????rt_int32_t?i;
    ????rt_err_t?ret?=?0;
    
    ????for?(i?=?0;?i?<=?retries;?i++)
    ????{
    ????????ret?=?rt_i2c_writeb(bus,?addr);
    ????????if?(ret?==?1?||?i?==?retries)
    ????????????break;
    ????????rt_i2c_stop(bus);
    ????????rt_i2c_udelay(1);
    ????????rt_i2c_start(bus);
    ????}
    
    ????return?ret;
    }
    
    static?rt_err_t?rt_i2c_bit_send_address(struct?rt_i2c_bus_device?*bus,
    ????????????????????????????????????????struct?rt_i2c_msg?*msg)
    {
    ????rt_uint16_t?flags?=?msg->flags;
    ????rt_uint16_t?ignore_nack?=?msg->flags?&?RT_I2C_IGNORE_NACK;
    
    ????rt_uint8_t?addr1,?addr2;
    ????rt_int32_t?retries;
    ????rt_err_t?ret;
    
    ????retries?=?ignore_nack???0?:?bus->retries;
    
    ????if?(flags?&?RT_I2C_ADDR_10BIT)
    ????{
    ????????addr1?=?0xf0?|?((msg->addr?>>?7)?&?0x06);
    ????????addr2?=?msg->addr?&?0xff;
    
    ????????ret?=?rt_i2c_send_address(bus,?addr1,?retries);
    ????????if?((ret?!=?1)?&&?!ignore_nack)
    ????????{
    ????????????return?-RT_EIO;
    ????????}
    
    ????????ret?=?rt_i2c_writeb(bus,?addr2);
    ????????if?((ret?!=?1)?&&?!ignore_nack)
    ????????{
    ????????????return?-RT_EIO;
    ????????}
    ????????if?(flags?&?RT_I2C_RD)
    ????????{
    ????????????rt_i2c_restart(bus);
    ????????????addr1?|=?0x01;
    ????????????ret?=?rt_i2c_send_address(bus,?addr1,?retries);
    ????????????if?((ret?!=?1)?&&?!ignore_nack)
    ????????????{
    ????????????????return?-RT_EIO;
    ????????????}
    ????????}
    ????}
    ????else
    ????{
    ????????addr1?=?msg->addr?<<?1;
    ????????if?(flags?&?RT_I2C_RD)
    ????????????addr1?|=?1;
    ????????ret?=?rt_i2c_send_address(bus,?addr1,?retries);
    ????????if?((ret?!=?1)?&&?!ignore_nack)
    ????????????return?-RT_EIO;
    ????}
    
    ????return?RT_EOK;
    }
    
    rt_err_t?rt_i2c_control(struct?rt_i2c_bus_device?*bus,
    ????????????????????????rt_uint32_t???????????????cmd,
    ????????????????????????rt_uint32_t???????????????arg)
    {
    ????return?RT_EOK;
    }
    
    rt_size_t?rt_i2c_transfer(struct?rt_i2c_bus_device?*bus,
    ??????????????????????????struct?rt_i2c_msg?????????msgs[],
    ??????????????????????????rt_uint32_t???????????????num)
    {
    ????struct?rt_i2c_msg?*msg;
    ????rt_int32_t?i,?ret;
    ????rt_uint16_t?ignore_nack;
    
    ????rt_i2c_start(bus);
    ????for?(i?=?0;?i?<?num;?i++)
    ????{
    ????????msg?=?&msgs[i];
    ????????ignore_nack?=?msg->flags?&?RT_I2C_IGNORE_NACK;
    ????????if?(!(msg->flags?&?RT_I2C_NO_START))
    ????????{
    ????????????if?(i)
    ????????????{
    ????????????????rt_i2c_restart(bus);
    ????????????}
    ????????????ret?=?rt_i2c_bit_send_address(bus,?msg);
    ????????????if?((ret?!=?RT_EOK)?&&?!ignore_nack)
    ????????????{
    ????????????????goto?out;
    ????????????}
    ????????}
    ????????if?(msg->flags?&?RT_I2C_RD)
    ????????{
    ????????????ret?=?rt_i2c_recv_bytes(bus,?msg);
    ????????????if?(ret?>=?1)
    ????????????????;
    ????????????if?(ret?<?msg->len)
    ????????????{
    ????????????????if?(ret?>=?0)
    ????????????????????ret?=?-RT_EIO;
    ????????????????goto?out;
    ????????????}
    ????????}
    ????????else
    ????????{
    ????????????ret?=?rt_i2c_send_bytes(bus,?msg);
    ????????????if?(ret?>=?1)
    ????????????????;
    ????????????if?(ret?<?msg->len)
    ????????????{
    ????????????????if?(ret?>=?0)
    ????????????????????ret?=?-RT_ERROR;
    ????????????????goto?out;
    ????????????}
    ????????}
    ????}
    ????ret?=?i;
    
    out:
    ????rt_i2c_stop(bus);
    
    ????return?ret;
    }
    
    rt_size_t?rt_i2c_master_send(struct?rt_i2c_bus_device?*bus,
    ?????????????????????????????rt_uint16_t???????????????addr,
    ?????????????????????????????rt_uint16_t???????????????flags,
    ?????????????????????????????const?rt_uint8_t?????????*buf,
    ?????????????????????????????rt_uint32_t???????????????count)
    {
    ????rt_err_t?ret;
    ????struct?rt_i2c_msg?msg;
    
    ????msg.addr??=?addr;
    ????msg.flags?=?flags;
    ????msg.len???=?count;
    ????msg.buf???=?(rt_uint8_t?*)buf;
    
    ????ret?=?rt_i2c_transfer(bus,?&msg,?1);
    
    ????return?(ret?>?0)???count?:?ret;
    }
    
    rt_size_t?rt_i2c_master_recv(struct?rt_i2c_bus_device?*bus,
    ?????????????????????????????rt_uint16_t???????????????addr,
    ?????????????????????????????rt_uint16_t???????????????flags,
    ?????????????????????????????rt_uint8_t???????????????*buf,
    ?????????????????????????????rt_uint32_t???????????????count)
    {
    ????rt_err_t?ret;
    ????struct?rt_i2c_msg?msg;
    ????RT_ASSERT(bus?!=?RT_NULL);
    
    ????msg.addr???=?addr;
    ????msg.flags??=?flags?|?RT_I2C_RD;
    ????msg.len????=?count;
    ????msg.buf????=?buf;
    
    ????ret?=?rt_i2c_transfer(bus,?&msg,?1);
    
    ????return?(ret?>?0)???count?:?ret;
    }
    
    struct?rt_i2c_bus_device?*rt_i2c_bus_device_find(const?char?*bus_name)
    {
    ????rt_size_t?bus_num?=?sizeof(i2c_bus)?/?sizeof(i2c_bus[0]);
    
    ????for(int?i?=?0;?i?<?bus_num;?i++)
    ????{
    ????????if(rt_strncmp(i2c_bus[i].config->name,?bus_name,?RT_NAME_MAX)?==?0)
    ????????{
    ????????????return?&i2c_bus[i];
    ????????}
    ????}
    ????return?RT_NULL;
    }
    
    int?rt_i2c_core_init(void)
    {
    ????rt_size_t?bus_num?=?sizeof(i2c_bus)?/?sizeof(i2c_bus[0]);
    
    ????for(int?i?=?0;?i?<?bus_num;?i++)
    ????{
    ????????i2c_bus[i].config?=?&i2c_config[i];
    ????????rt_i2c_configure(&i2c_bus[i]);
    ????}
    
    ????return?RT_EOK;
    }
    INIT_COMPONENT_EXPORT(rt_i2c_core_init);
    
    #endif?/*?RT_USING_I2C?*/
    
    
    • drv_i2c.h

    /*
    ?*?Copyright?(c)?2006-2021,?RT-Thread?Development?Team
    ?*
    ?*?SPDX-License-Identifier:?Apache-2.0
    ?*
    ?*?Change?Logs:
    ?*?Date???????????Author????????????Notes
    ?*?2021-04-20?????RiceChen??????first?version
    ?*/
    
    #ifndef?__DRV_I2C_H__
    #define?__DRV_I2C_H__
    
    #include?<drv_common.h>
    #include?<board.h>
    #include?"pin.h"
    #include?"i2c.h"
    
    #ifdef?__cplusplus
    extern?"C"?{
    #endif
    
    #ifdef?RT_USING_I2C1
    #define?RT_I2C1_SCL_PIN????????????GET_PIN(B,?6)
    #define?RT_I2C1_SDA_PIN????????????GET_PIN(B,?7)
    
    #define?RT_I2C1_CONFIG?????????????????????????????????????????\
    ????{??????????????????????????????????????????????????????????\
    ????????.name?=?"i2c1",????????????????????????????????????????\
    ????????.scl?=?RT_I2C1_SCL_PIN,????????????????????????????????\
    ????????.sda?=?RT_I2C1_SDA_PIN,????????????????????????????????\
    ????}
    #endif
    
    #ifdef?RT_USING_I2C2
    #define?RT_I2C2_SCL_PIN????????????GET_PIN(B,?8)
    #define?RT_I2C2_SDA_PIN????????????GET_PIN(B,?9)
    
    #define?RT_I2C2_CONFIG?????????????????????????????????????????\
    ????{??????????????????????????????????????????????????????????\
    ????????.name?=?"i2c2",????????????????????????????????????????\
    ????????.scl?=?RT_I2C2_SCL_PIN,????????????????????????????????\
    ????????.sda?=?RT_I2C2_SDA_PIN,????????????????????????????????\
    ????}
    #endif
    
    #ifdef?__cplusplus
    }
    #endif
    
    #endif?/*?__DRV_GPIO_H__?*/
    

    编写 I2C 设备使用示例

    #include?<rtthread.h>
    #include?<rtdevice.h>
    
    #define?AHT10_I2C_BUS_NAME??????????"i2c1"??/*?传感器连接的I2C总线设备名称?*/
    #define?AHT10_ADDR??????????????????0x38????/*?从机地址?*/
    #define?AHT10_CALIBRATION_CMD???????0xE1????/*?校准命令?*/
    #define?AHT10_NORMAL_CMD????????????0xA8????/*?一般命令?*/
    #define?AHT10_GET_DATA??????????????0xAC????/*?获取数据命令?*/
    
    static?struct?rt_i2c_bus_device?*i2c_bus?=?RT_NULL;?????/*?I2C总线设备句柄?*/
    static?rt_bool_t?initialized?=?RT_FALSE;????????????????/*?传感器初始化状态?*/
    
    /*?写传感器寄存器?*/
    static?rt_err_t?write_reg(struct?rt_i2c_bus_device?*bus,?rt_uint8_t?reg,?rt_uint8_t?*data)
    {
    ????rt_uint8_t?buf[3];
    ????struct?rt_i2c_msg?msgs;
    ????rt_uint32_t?buf_size?=?1;
    
    ????buf[0]?=?reg;?//cmd
    ????if?(data?!=?RT_NULL)
    ????{
    ????????buf[1]?=?data[0];
    ????????buf[2]?=?data[1];
    ????????buf_size?=?3;
    ????}
    
    ????msgs.addr?=?AHT10_ADDR;
    ????msgs.flags?=?RT_I2C_WR;
    ????msgs.buf?=?buf;
    ????msgs.len?=?buf_size;
    
    ????/*?调用I2C设备接口传输数据?*/
    ????if?(rt_i2c_transfer(bus,?&msgs,?1)?==?1)
    ????{
    ????????return?RT_EOK;
    ????}
    ????else
    ????{
    ????????return?-RT_ERROR;
    ????}
    }
    
    /*?读传感器寄存器数据?*/
    static?rt_err_t?read_regs(struct?rt_i2c_bus_device?*bus,?rt_uint8_t?len,?rt_uint8_t?*buf)
    {
    ????struct?rt_i2c_msg?msgs;
    
    ????msgs.addr?=?AHT10_ADDR;
    ????msgs.flags?=?RT_I2C_RD;
    ????msgs.buf?=?buf;
    ????msgs.len?=?len;
    
    ????/*?调用I2C设备接口传输数据?*/
    ????if?(rt_i2c_transfer(bus,?&msgs,?1)?==?1)
    ????{
    ????????return?RT_EOK;
    ????}
    ????else
    ????{
    ????????return?-RT_ERROR;
    ????}
    }
    
    static?void?read_temp_humi(float?*cur_temp,?float?*cur_humi)
    {
    ????rt_uint8_t?temp[6];
    
    ????write_reg(i2c_bus,?AHT10_GET_DATA,?RT_NULL);??????/*?发送命令?*/
    ????rt_thread_mdelay(400);
    ????read_regs(i2c_bus,?6,?temp);????????????????/*?获取传感器数据?*/
    
    ????/*?湿度数据转换?*/
    ????*cur_humi?=?(temp[1]?<<?12?|?temp[2]?<<?4?|?(temp[3]?&?0xf0)?>>?4)?*?100.0?/?(1?<<?20);
    ????/*?温度数据转换?*/
    ????*cur_temp?=?((temp[3]?&?0xf)?<<?16?|?temp[4]?<<?8?|?temp[5])?*?200.0?/?(1?<<?20)?-?50;
    }
    
    static?void?aht10_init(const?char?*name)
    {
    ????rt_uint8_t?temp[2]?=?{0,?0};
    
    ????/*?查找I2C总线设备,获取I2C总线设备句柄?*/
    ????i2c_bus?=?rt_i2c_bus_device_find(name);
    
    ????if?(i2c_bus?==?RT_NULL)
    ????{
    ????????rt_kprintf("can't?find?%s?device!\n",?name);
    ????}
    ????else
    ????{
    ????????write_reg(i2c_bus,?AHT10_NORMAL_CMD,?temp);
    ????????rt_thread_mdelay(400);
    
    ????????temp[0]?=?0x08;
    ????????temp[1]?=?0x00;
    ????????write_reg(i2c_bus,?AHT10_CALIBRATION_CMD,?temp);
    ????????rt_thread_mdelay(400);
    ????????initialized?=?RT_TRUE;
    ????}
    }
    
    static?void?i2c_aht10_sample(int?argc,?char?*argv[])
    {
    ????float?humidity,?temperature;
    ????char?name[RT_NAME_MAX];
    
    ????humidity?=?0.0;
    ????temperature?=?0.0;
    
    ????if?(argc?==?2)
    ????{
    ????????rt_strncpy(name,?argv[1],?RT_NAME_MAX);
    ????}
    ????else
    ????{
    ????????rt_strncpy(name,?AHT10_I2C_BUS_NAME,?RT_NAME_MAX);
    ????}
    
    ????if?(!initialized)
    ????{
    ????????/*?传感器初始化?*/
    ????????aht10_init(name);
    ????}
    ????if?(initialized)
    ????{
    ????????/*?读取温湿度数据?*/
    ????????read_temp_humi(&temperature,?&humidity);
    
    ????????rt_kprintf("read?aht10?sensor?humidity???:?%d.%d?%%\n",?(int)humidity,?(int)(humidity?*?10)?%?10);
    ????????if(?temperature?>=?0?)
    ????????{
    ????????????rt_kprintf("read?aht10?sensor?temperature:?%d.%d°C\n",?(int)temperature,?(int)(temperature?*?10)?%?10);
    ????????}
    ????????else
    ????????{
    ????????????rt_kprintf("read?aht10?sensor?temperature:?%d.%d°C\n",?(int)temperature,?(int)(-temperature?*?10)?%?10);
    ????????}
    ????}
    ????else
    ????{
    ????????rt_kprintf("initialize?sensor?failed!\n");
    ????}
    }
    /*?导出到?msh?命令列表中?*/
    MSH_CMD_EXPORT(i2c_aht10_sample,?i2c?aht10?sample);
    
    实例代码运行现象:
    
    ```?C
    msh?>i2c_aht10_sample?i2c1
    read?aht10?sensor?humidity???:?90.0?%
    read?aht10?sensor?temperature:?25.33°C
    msh?>
    

    I2C 设备相关软件包使用

    1. 我们使用as7341软件包来验证 I2C 设备 API。

    2. 首先克隆 as7341 软件包到 STM32L431RCT6 的 RT-Thread Nano 工程。as7341 软件包链接:https://github.com/RiceChen/as7341.git

    3. 由于没有了 RT-Thread 标准版本的设备驱动框架,所以对软件包进行简单的修改:

    • 在 as7341.h 中包含 drv_i2c.h 头文件。

    • 修改 as7341.c 中的测试用例。代码如下:

    static?void?as7341(int?argc,?char?*argv[])
    {
    ????static?as7341_device_t?dev?=?RT_NULL;
    ????
    ????if?(argc?>?1)
    ????{
    ????????if?(!strcmp(argv[1],?"probe"))
    ????????{
    ????????????if?(argc?>=?3)
    ????????????{
    ????????????????/*?initialize?the?sensor?when?first?probe?*/
    ????????????????if?(!dev?||?strcmp(dev->i2c->config->name,?argv[2]))?//?修改点1
    ????????????????{
    ????????????????????/*?deinit?the?old?device?*/
    ????????????????????if(dev)
    ????????????????????{
    ??????rt_kprintf("Deinit?as7341\n");
    ????????????????????????as7341_deinit(dev);
    ????????????????????}
    
    ????????????????????dev?=?as7341_init(argv[2],?eSpm);
    ????????????????????if(!dev)
    ????????????????????{
    ????????????????????????rt_kprintf("as7341?probe?failed,?check?input?args\n");
    ????????????????????}else
    ?????{
    ??????rt_kprintf("as7341?probed,?addr:0x%x\n",?AS7341_ADDR)?;
    ?????}
    ????????????????}
    ????????????}
    ????????????else
    ????????????{
    ????????????????as7341_usage();
    ????????????}
    ????????}
    ????????else?if?(!strcmp(argv[1],?"read"))
    ????????{
    ????????????if?(dev)
    ????????????{
    ????????????????if(!strcmp(argv[2],?"spectral"))
    ????????????????{
    ????????????????????MODE_ONE_DATA_t?data1;
    ????????????????????MODE_TOW_DATA_t?data2;
    
    ????????????????????as7341_start_measure(dev,?eF1F4ClearNIR);
    ????????????????????data1?=?as7341_read_spectral_data_one(dev);
    ????????????????????rt_kprintf("F1(405-425nm):?%d\n",?data1.ADF1);
    ????????????????????rt_kprintf("F2(435-455nm):?%d\n",?data1.ADF2);
    ????????????????????rt_kprintf("F3(470-490nm):?%d\n",?data1.ADF3);
    ????????????????????rt_kprintf("F4(505-525nm):?%d\n",?data1.ADF4);
    
    ????????????????????as7341_start_measure(dev,?eF5F8ClearNIR);
    ????????????????????data2?=?as7341_read_spectral_data_tow(dev);
    ????????????????????rt_kprintf("F5(545-565nm):?%d\n",?data2.ADF5);
    ????????????????????rt_kprintf("F6(580-600nm):?%d\n",?data2.ADF6);
    ????????????????????rt_kprintf("F7(620-640nm):?%d\n",?data2.ADF7);
    ????????????????????rt_kprintf("F8(670-690nm):?%d\n",?data2.ADF8);
    
    ????????????????????rt_kprintf("Clear:?%d\n",?data2.ADCLEAR);
    ????????????????????rt_kprintf("NIR:?%d\n",?data2.ADNIR);
    ????????????????}
    ????????????????else?if(!strcmp(argv[2],?"flicker"))
    ????????????????{
    ????????????????????rt_uint8_t?freq?=?0;
    ????????????????????freq?=?as7341_read_flicker_data(dev);
    ????????????????????if(freq?==?1)
    ????????????????????{
    ????????????????????????rt_kprintf("Unknown?frequency\n");
    ????????????????????}
    ????????????????????else?if(freq?==?0)
    ????????????????????{
    ????????????????????????rt_kprintf("No?flicker\n");
    ????????????????????}
    ????????????????????else
    ????????????????????{
    ????????????????????????rt_kprintf("freq:?%dHz\n",?freq);
    ????????????????????}
    ????????????????}
    ????????????????else
    ????????????????{
    ????????????????????as7341_usage();
    ????????????????}
    ????????????????
    ????????????}
    ????????????else
    ????????????{
    ????????????????rt_kprintf("Please?using?'as7341?probe?<i2c?dev?name>'?first\n");
    ????????????}
    ????????}
    ????????else
    ????????{
    ????????????as7341_usage();
    ????????}
    ????}
    ????else
    ????{
    ????????as7341_usage();???
    ????}
    }
    
    1. 使用 as7341 软件包实例,编译烧录便可以在终端输入测试命令:

    msh?>as7341?probe?i2c1
    as7341?id:?0x24
    as7341?probed,?addr:0x39
    msh?>
    msh?>as7341?read?spectral
    F1(405-425nm):?1
    F2(435-455nm):?3
    F3(470-490nm):?4
    F4(505-525nm):?5
    F5(545-565nm):?7
    F6(580-600nm):?6
    F7(620-640nm):?7
    F8(670-690nm):?4
    Clear:?22
    NIR:?2
    msh?>
    

    总结

    • 通过适配I2C设备接口,我们可以无缝对接到软件包的使用。

    • 对于低资源的芯片使用 Nano 并且能够使用 RT-THREAD 丰富的软件,无疑是一个非常完美的做法。也没有庞大的驱动框架。

    • 通过这样的方式,学习完 RT-THREAD Nano 在转移到 RT-THREAD 标准版的学习,更加简单方便。

    关注微信公众号『Rice嵌入式开发技术分享』,后台回复“微信”添加作者微信,备注”入群“,便可邀请进入技术交流群。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-02 11:32:57  更:2021-09-02 11:34:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:39:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码