# fvi2c **Repository Path**: Fins-s/fvi2c ## Basic Information - **Project Name**: fvi2c - **Description**: 这是一个虚拟 i2c (virtual i2c) 框架,支持主机模式,支持总线仲裁 - **Primary Language**: C - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 12 - **Forks**: 4 - **Created**: 2020-10-29 - **Last Updated**: 2026-01-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # fvi2c ## 介绍 这是一个虚拟 i2c (virtual i2c) 框架,支持主机模式,支持总线仲裁,Apache-2.0开源协议 ## 特性 1. 支持i2c主机模式 2. 支持总线仲裁 3. 支持10bit从机地址 4. 最少只需要三个接口函数就可以实现移植 ## 名词解释 1. fvi2c:指代本虚拟 I2C 框架 2. SCL:I2C 时钟线 3. SDA:I2C 数据线 **注意:** 文档中以'<''>'括起来的参数表示该参数由用户输入或实现 ## 文件构成 1. ```fvi2c.h``` 中包含用户所需要使用的所有头文件 2. ```common``` 文件夹中包含通用文件 1. ```fvi2c_config.h``` 中包含对 fvi2c 进行配置的宏开关 2. ```fvi2c_debug.h``` 中包含 fvi2c 中断言语句的实现,如果使用断言,用户需要自己实现断言宏 3. ```fvi2c_def.h``` 中包含 fvi2c 中需要用到的所有类型的定义 3. master 文件夹中包含 fvi2c 主机协议的实现 1. ```fvi2c_signal.h ```中包含 I2C 底层信号的实现,包含起始信号、重复起始信号、停止信号、逻辑0/1. 2. ```fvi2c_master.h``` 中包含 fvi2c 主机模式函数的声明,和相关宏定义的实现 3. ```fvi2c_master.c``` 中包含 fvi2c 主机模式函数的实现 4. ```slave ```文件夹未使用 5. ```sample``` 文件夹包含 fvi2c 的使用示例 ## 编写规范 1. 文件名全部使用小写字母,不同表达意义的单词或字母使用下划线分割 2. 变量名使用驼峰法,首字母小写,单词或表达一个意义的字母组合首字母大写 3. 函数名使用帕斯卡命名法,单词或表达一个意义的字母组合首字母大写(示例:USB 表示为 Usb ) 4. 类型名使用 '小写模块名' + '_' + '类形名' + '类型后缀' 的命名方式(示例:fvi2c_msg ) 5. 结构体使用 '_s' 后缀重命名(示例:fvi2c_msg_s ) 6. 枚举使用 '_e' 后缀重命名 7. 联合体使用 '_u' 后缀重命名 ## 移植说明 1. 克隆本仓库到自己的项目 >```git clone <代码仓库地址>"``` 2. 包含 fvi2c.h 文件 >```#include "fvi2c.h"``` 3. 实现三个底层接口 1. >```fvi2c_pSta_e (*GetPin)(fvi2c_pin_e pin);``` **描述**:此接口函数用来获取 GPIO 口的状态 **输入参数**: ```pin``` 可能的输入值为 ```FVI2C_SCL/FVI2C_SDA``` 分别代表 I2C 总线的 SCL 引脚和 SDA 引脚。 **返回值**:此函数应返回以 ```FVI2C_PIN_LOW/FVI2C_PIN_HIGH``` 表示的引脚状态 2. >```void (*SetPin)(fvi2c_pin_e pin, fvi2c_pSta_e status);``` **描述**:此接口函数用来获取 GPIO 口的状态 **输入参数**: ```pin``` 可能的输入值为 ```FVI2C_SCL/FVI2C_SDA``` 分别代表 I2C 总线的 SCL 引脚和 SDA 引脚。 **输入参数**: ```status``` 可能的输入值为 ```FVI2C_PIN_LOW/FVI2C_PIN_HIGH``` 代表要设置的引脚电平 **返回值**:该函数没有返回值 3. >```void (*UnitDelay)(void);``` **描述**:此接口函数用来延时一个单位时间,fvi2c 中的时间都是单位时间的整数倍 **参数**:该函数没有参数 **返回值**:该函数没有返回值 4. 创建 I2C 实例 >```fvi2c_s ;``` 5. 创建底层接口结构体 >``` fvi2c_lLIf_s <接口结构体名称> = {``` ```.GetPin = <获取引脚状态函数>,``` ```.SetPin = <设置引脚状态函数>,``` ``` .UnitDelay = <单位时间延时函数> }``` 可以使用宏定义 ```FVI2C_NEW_IF(, , , )``` 快速创建接口结构体,并链接接口函数 示例: ```FVI2C_NEW_IF(<接口结构体名称>, <获取引脚状态函数>, <设置引脚状态函数>, <单位时间延时函数>);``` 6. 创建配置结构体 >```fvi2c_conf_s = {``` ```.holdPerTime = ,``` ```.holdPosTime = ,``` ```.chgPerTime = ,``` ```.chgPosTime = }``` **参数**: ```holdPerTime``` 表示数据保持阶段前导时间为 `````` * 单位时间,I2C 重复起始信号和停止信号的 SDA 电平会在经过数据保持阶段前导时间后进行跳变,fvi2c 会在经过数据保持阶段前导时间后进行引脚读取,以进行总线仲裁。 **参数**: ```holdPosTime``` 表示数据保持阶段后置时间为 `````` * 单位时间,fvi2c 在经过数据保持阶段后置时间后拉低 SCL 。 **参数**: ```chgPerTime``` 表示数据更改阶段前导时间为 `````` * 单位时间,fvi2c 会在经过数据更改阶段前导时间后进行数据跳变。 **参数**: ```chgPosTime``` 表示数据更改阶段后置时间为 `````` * 单位时间,fvi2c 会在经过数据更改阶段后置时间后尝试拉高 SCL。 可以使用宏定义 ```FVI2C_NEW_CONF(, , , , )``` 快速创建配置结构体,并设置配置参数 7. 调用 ```Fvi2cAttachIf()``` 链接底层接口 >```Fvi2cAttachIf(, <接口结构体>);``` 8. 调用 ```Fvi2cConfig()``` 配置 I2C 参数 >```Fvi2cConfig(, <配置结构体>);``` **注意:** 移植示例可以查看 ```sample``` 文件夹 ## 使用说明 通过移植说明已经可以完成 fvi2c 的移植,本章节将介绍 fvi2c的使用。 1. 创建消息,或消息数组,可以使用宏定义 >``` fvi2c_msg_s ``` 消息结构体的实现: ``` typedef struct fvi2c_msg { fuint16 addr; /**< I2C 器件的地址,8位地址 */ fvi2c_flag_e flags; /**< 消息的标志,参考 'fvi2c_flag_e' 使用 '|' 使能多个标志 */ fuint32 len; /**< 当该消息是发送消息时代表消息的长度。当消息是读取消息读取数据长度。单位为字节 */ fuint8* msg; /**< 发送数据或读取数据的缓存区地址*/ }fvi2c_msg_s; ``` 2. 调用 ```Fvi2cMasTransfer()``` 发送消息 >```fvi2c_ret_e Fvi2cMasTransfer(, <消息数量>, <消息数组首地址或消息地址>)``` 3. 函数返回值说明 ``` /************************************************* * @brief 函数返回值 ************************************************/ typedef enum fvi2c_ret { FVI2C_ROK = 0, /**< 成功 */ FVI2C_RERR, /**< 错误 */ FVI2C_RNACK, /**< 设备非应答 */ FVI2C_RBUS_BUSY, /**< I2C 总线忙 */ FVI2C_RARB_FAIL, /**< 总线仲裁失败 */ FVI2C_RTIMEOUT, /**< 拉高SCL线超时 */ }fvi2c_ret_e; ``` 4. 消息标志说明 ``` /************************************************* * @brief 消息的标志,使用 '|' 使能多个标志 ************************************************/ typedef enum fvi2c_flag { FVI2C_8B_ADDR = 0U, /**< 8位地址 (默认) */ FVI2C_10B_ADDR = 1U, /**< 10位地址 */ FVI2C_RWADDR = 0U, /**< 输入地址为读写地址 (默认)*/ FVI2C_OLADDR = (1U << 1), /**< 输入地址不包含读写位,读写方向由读写标志确定 */ FVI2C_WRITE = 0U, /**< 写标志 (默认)*/ FVI2C_READ = (1U << 2), /**< 读标志 */ FVI2C_READ_ACK = 0U, /**< 读数据时产生应答信号 (默认)*/ FVI2C_READ_NACK = (1U << 3), /**< 读数据时不产生应答信号*/ FVI2C_GERR_NACK = 0U, /**< 写数据接收到 NACK 时产生错误 (默认)*/ FVI2C_IGNORE_NACK = (1U << 4), /**< 写数据时忽略 NACK */ }fvi2c_flag_e; ``` 5. 宏编译开关说明 ``` #define FVI2C_WPIN_TIMEOUT 500U /**< 等待SCL拉高时读取判断次数 */ #define FVI2C_USE_FULL_ASSERT 1U /**< 1: 使用断言(需要实现FVI2C_ASSERT(expr) 宏) 0: 不使用断言*/ ``` **注意:** 使用示例可以查看 ```sample``` 文件夹