打印
[其他ST产品]

STM32 模拟IIC源代码 多个I2C减少冗余代码

[复制链接]
285|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
七毛钱|  楼主 | 2022-10-14 22:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
当设计中使用I2C的数量多于1个时,其底层I2C的代码逻辑都是一样的,只有IO口变了,为此还要复制粘贴、修改IO,不仅费时,而且还浪费片内资源,因此可以使用指针来重复执行IIC底层代码,实现一个代码,多个IO使用。
注意:使用什么IO口,一定要打开其IO时钟,同时配置为输出开漏模式!!!
使用例程在最下面

Stm32f30x_SMLT_I2C.h
  • #ifndef __Stm32f30x_SMLT_I2C_H
  • #define __Stm32f30x_SMLT_I2C_H
  • //========================= Include ===============================================================
  • #include "stm32f30x.h"
  • //========================= Variable ==============================================================
  • typedef struct
  • {
  •         GPIO_TypeDef* SDA_GPIO;        //SDA的GPIO组地址
  •         GPIO_TypeDef* SCL_GPIO;        //SCL的GPIO组地址
  •         uint32_t SDA_SBIT;                //SDA 在 BSRR寄存器 中的置位
  •         uint32_t SDA_RBIT;                //SDA 在 BSRR寄存器 中的复位
  •         uint32_t SCL_SBIT;                //SCL 在 BSRR寄存器 中的置位
  •         uint32_t SCL_RBIT;                //SCL 在 BSRR寄存器 中的复位
  •         uint32_t SDA_MODER;                //SDA 在 MODER寄存器 中的配置位
  •         uint32_t SDA_MODER_0;        //SDA 在 MODER寄存器 中的配置位低位
  •         uint32_t SDA_MODER_1;        //SDA 在 MODER寄存器 中的配置位高位
  •         uint8_t SCL_Delay;                //SCL的延时参数 调整波特率 越大波特率越大
  • }I2C_Struct;
  • extern I2C_Struct S_I2C_IO[2];//------------------------------------- 修改处
  • //(想要3个的话,数组添加,下面的define也要添加,初始化函数S_I2C_Init中也要添加)
  • //========================= I2C1_Define ================================================================
  • //--------------------------SDA-------------------------------------- 修改处
  • #define S_I2C1_SDA_GPIO                GPIOE
  • #define S_I2C1_SDA_BIT                0
  • //--------------------------SCL-------------------------------------- 修改处
  • #define S_I2C1_SCL_GPIO                GPIOE
  • #define S_I2C1_SCL_BIT                1
  • #define S_I2C1_SCL_DELAY        0x80
  • //还需配置结构体初始化函数 S_I2C_Init 别忘了打开时钟及开漏配置
  • //========================= I2C2_Define ================================================================
  • //--------------------------SDA-------------------------------------- 修改处
  • #define S_I2C2_SDA_GPIO                GPIOE
  • #define S_I2C2_SDA_BIT                11
  • //--------------------------SCL-------------------------------------- 修改处
  • #define S_I2C2_SCL_GPIO                GPIOB
  • #define S_I2C2_SCL_BIT                13
  • #define S_I2C2_SCL_DELAY        0x10
  • //还需配置结构体初始化函数 S_I2C_Init 别忘了打开时钟及开漏配置
  • // //========================= I2Cx_Define ================================================================
  • // //--------------------------SDA-------------------------------------- 修改处
  • // #define S_I2Cx_SDA_GPIO                GPIOx
  • // #define S_I2Cx_SDA_BIT                x
  • // //--------------------------SCL-------------------------------------- 修改处
  • // #define S_I2Cx_SCL_GPIO                GPIOx
  • // #define S_I2Cx_SCL_BIT                x
  • // #define S_I2Cx_SCL_DELAY                x
  • // //添加在此添加
  • //========================= Function ==============================================================
  • void S_I2C_Init(void);//--------------------------------------------- 修改处
  • void S_I2C_Start(I2C_Struct I2C_temp);
  • void S_I2C_Stop(I2C_Struct I2C_temp);
  • uint8_t S_I2C_SendByte(I2C_Struct I2C_temp, uint8_t byte);
  • uint8_t S_I2C_ReceiveByte(I2C_Struct I2C_temp, uint8_t nack);
  • uint8_t S_I2C_WriteRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t data);
  • uint8_t S_I2C_ReadRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ);
  • uint8_t S_I2C_PointerRead(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ);
  • //========================= Define ================================================================
  • //通过宏定义将IO结构体直接放入基础函数中
  • //-------------------------- I2C1 -----------------------------------
  • #define S_I2C1_Start()                                                                                        S_I2C_Start(S_I2C_IO[0])
  • #define S_I2C1_Stop()                                                                                        S_I2C_Stop(S_I2C_IO[0])
  • #define S_I2C1_SendByte(byte)                                                                        S_I2C_SendByte(S_I2C_IO[0], byte)
  • #define S_I2C1_ReceiveByte(nack)                                                                S_I2C_ReceiveByte(S_I2C_IO[0], nack)
  • #define S_I2C1_WriteRegister(addr, regAddr, data)                                S_I2C_WriteRegister(S_I2C_IO[0], addr, regAddr, data)
  • #define S_I2C1_ReadRegister(addr, regAddr, amount, data, typ)        S_I2C_ReadRegister(S_I2C_IO[0], addr, regAddr, amount, data, typ)
  • #define S_I2C1_PointerRead(addr, regAddr, amount, data, typ)        S_I2C_PointerRead(S_I2C_IO[0], addr, regAddr, amount, data, typ)
  • //-------------------------- I2C2 -----------------------------------
  • #define S_I2C2_Start()                                                                                        S_I2C_Start(S_I2C_IO[1])
  • #define S_I2C2_Stop()                                                                                        S_I2C_Stop(S_I2C_IO[1])
  • #define S_I2C2_SendByte(byte)                                                                        S_I2C_SendByte(S_I2C_IO[1], byte)
  • #define S_I2C2_ReceiveByte(nack)                                                                S_I2C_ReceiveByte(S_I2C_IO[1], nack)
  • #define S_I2C2_WriteRegister(addr, regAddr, data)                                S_I2C_WriteRegister(S_I2C_IO[1], addr, regAddr, data)
  • #define S_I2C2_ReadRegister(addr, regAddr, amount, data, typ)        S_I2C_ReadRegister(S_I2C_IO[1], addr, regAddr, amount, data, typ)
  • #define S_I2C2_PointerRead(addr, regAddr, amount, data, typ)        S_I2C_PointerRead(S_I2C_IO[1], addr, regAddr, amount, data, typ)
  • //-------------------------- Another --------------------------------
  • #define ACK                0
  • #define NACK        1
  • #define FAILED        0
  • #define SUCCEED        1
  • #define ARRAY        0
  • #define STRUCT        1
  • //=================================================================================================
  • #endif

复制代码


Stm32f30x_SMLT_I2C.c

  • #include "Stm32f30x_SMLT_I2C.h"
  • I2C_Struct S_I2C_IO[2];//IO口结构体,通过.h文件定义使用的引脚
  • /**
  • * @description: I2C结构体IO初始化
  • * @param {I2C_Struct*} I2C_temp        I2C的IO结构体
  • * @param {GPIO_TypeDef*}        SDA_GPIO                I2C SDA GPIO(GPIOA~GPIOx)
  • * @param {uint8_t}                        SDA_BIT                        I2C SDA引脚号(1~16)
  • * @param {GPIO_TypeDef*}        SCL_GPIO                I2C SCL GPIO(GPIOA~GPIOx)
  • * @param {uint8_t}                        SCL_BIT                        I2C SCL引脚号(1~16)
  • * @param {uint8_t}                        SCL_Delay                I2C SCL时钟延时(0x00~0xff)越大波特率越低
  • * @return {*}
  • */
  • void S_I2C_Struct_Init(I2C_Struct* I2C_temp, GPIO_TypeDef* SDA_GPIO, uint8_t SDA_BIT, GPIO_TypeDef* SCL_GPIO, uint8_t SCL_BIT, uint8_t SCL_Delay)
  • {
  •         I2C_temp->SDA_GPIO = SDA_GPIO;
  •         I2C_temp->SCL_GPIO = SCL_GPIO;
  •         I2C_temp->SDA_SBIT = (0x00000001 << SDA_BIT);
  •         I2C_temp->SDA_RBIT = (0x00010000 << SDA_BIT);
  •         I2C_temp->SCL_SBIT = (0x00000001 << SCL_BIT);
  •         I2C_temp->SCL_RBIT = (0x00010000 << SCL_BIT);
  •         I2C_temp->SDA_MODER = 0x00000003 << (SDA_BIT << 1);
  •         I2C_temp->SDA_MODER_0 = 0x00000001 << (SDA_BIT << 1);
  •         I2C_temp->SDA_MODER_1 = 0x00000002 << (SDA_BIT << 1);
  •         I2C_temp->SCL_Delay = SCL_Delay;
  • }
  • /**
  • * @description: I2C结构体总初始化,将计算的各个变量存入结构体中
  • * @param {*}
  • * @return {*}
  • */
  • void S_I2C_Init(void)
  • {
  •         S_I2C_Struct_Init(&S_I2C_IO[0], S_I2C1_SDA_GPIO, S_I2C1_SDA_BIT, S_I2C1_SCL_GPIO, S_I2C1_SCL_BIT, S_I2C1_SCL_DELAY);
  •         S_I2C_Struct_Init(&S_I2C_IO[1], S_I2C2_SDA_GPIO, S_I2C2_SDA_BIT, S_I2C2_SCL_GPIO, S_I2C2_SCL_BIT, S_I2C2_SCL_DELAY);
  •         // S_I2C_Struct_Init(&S_I2C_IO[x], S_I2Cx_SDA_GPIO, S_I2Cx_SDA_BIT, S_I2Cx_SCL_GPIO, S_I2Cx_SCL_BIT, S_I2Cx_SCL_DELAY);//添加在此添加
  • }
  • /**
  • * @description: I2C时钟延时,调整波特率
  • * @param {*}
  • * @return {*}
  • */
  • void S_I2C_Delay(uint8_t temp)
  • {
  •     for ( ; temp; temp--)
  •         {
  •                 /* code */
  •         }
  • }
  • /**
  • * @description: 产生起始信号
  • * @param {I2C_Struct} I2C_temp I2C_IO结构体
  • * @return {*}
  • */
  • void S_I2C_Start(I2C_Struct I2C_temp)
  • {
  •         I2C_temp.SDA_GPIO->MODER |= I2C_temp.SDA_MODER_0;
  •         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_SBIT;
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  •         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  • }
  • /**
  • * @description: 产生停止信号
  • * @param {I2C_Struct} I2C_temp
  • * @return {*}
  • */
  • void S_I2C_Stop(I2C_Struct I2C_temp)
  • {
  •         I2C_temp.SDA_GPIO->MODER |= I2C_temp.SDA_MODER_0;
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  •         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  •         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_SBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  • }
  • /**
  • * @description: 发送一个字节数据
  • * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  • * @param {uint8_t} byte        数据
  • * @return {uint8_t}                NACK
  • *                                                         ACK
  • */
  • uint8_t S_I2C_SendByte(I2C_Struct I2C_temp, uint8_t byte)
  • {
  •         uint8_t temp = 0x00;
  •         for(uint8_t i = 0x80; i; i >>= 1)
  •         {
  •                 I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  •                 if(byte & i)
  •                 {
  •                         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_SBIT;
  •                 }
  •                 else
  •                 {
  •                         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  •                 }
  •         S_I2C_Delay(I2C_temp.SCL_Delay);
  •                 I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  •         S_I2C_Delay(I2C_temp.SCL_Delay);
  •         }
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  •         I2C_temp.SDA_GPIO->MODER &= ~I2C_temp.SDA_MODER;
  •         S_I2C_Delay(I2C_temp.SCL_Delay);
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  •         if(I2C_temp.SDA_GPIO -> IDR & I2C_temp.SDA_SBIT)
  •         {
  •                 temp = NACK;
  •         }
  •         else
  •         {
  •                 temp = ACK;
  •         }
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  •         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  •         I2C_temp.SDA_GPIO->MODER |= I2C_temp.SDA_MODER_0;
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  •         return temp;
  • }
  • /**
  • * @description: 接收一个字节数据
  • * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  • * @param {uint8_t} nack        接收后结束要发送的应答信号
  • *                                                         NACK
  • *                                                         ACK
  • * @return {uint8_t}        接收到的字节
  • */
  • uint8_t S_I2C_ReceiveByte(I2C_Struct I2C_temp, uint8_t nack)
  • {
  •         uint8_t byte = 0x00;
  •         I2C_temp.SDA_GPIO->MODER &= ~I2C_temp.SDA_MODER;
  •         for (uint8_t i = 8; i; i--)
  •         {
  •                 I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  •         S_I2C_Delay(I2C_temp.SCL_Delay);
  •                 byte <<= 1;
  •                 I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  •                 if(I2C_temp.SDA_GPIO -> IDR & I2C_temp.SDA_SBIT)
  •                 {
  •                         byte |= 0x01;
  •                 }
  •         S_I2C_Delay(I2C_temp.SCL_Delay);
  •         }
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  •         I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  •         I2C_temp.SDA_GPIO->MODER |= I2C_temp.SDA_MODER_0;
  •         if(nack)
  •                 I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_SBIT;
  •         else
  •                 I2C_temp.SDA_GPIO->BSRR |= I2C_temp.SDA_RBIT;
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_RBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  •         I2C_temp.SCL_GPIO->BSRR |= I2C_temp.SCL_SBIT;
  •     S_I2C_Delay(I2C_temp.SCL_Delay);
  •         return byte;
  • }
  • /**
  • * @description: 写一个字节的寄存器
  • * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  • * @param {uint8_t} addr        器件地址(0x00~0x7f)
  • * @param {uint8_t} regAddr        寄存器地址(0x00~0xff)
  • * @param {uint8_t} data        数据
  • * @return {uint8_t}        FAILED        失败
  • *                                                 SUCCEED        成功
  • */
  • uint8_t S_I2C_WriteRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t data)
  • {
  •         addr <<= 1;
  •         S_I2C_Start(I2C_temp);
  •         if(S_I2C_SendByte(I2C_temp, addr) == NACK)
  •         {
  •                 S_I2C_Stop(I2C_temp);
  •                 return FAILED;
  •         }
  •         if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
  •         {
  •                 S_I2C_Stop(I2C_temp);
  •                 return FAILED;
  •         }
  •         if(S_I2C_SendByte(I2C_temp, data) == NACK)
  •         {
  •                 S_I2C_Stop(I2C_temp);
  •                 return FAILED;
  •         }
  •         S_I2C_Stop(I2C_temp);
  •         return SUCCEED;
  • }
  • /**
  • * @description:                 读取器件,读取格式:器件读-寄存器地址-读取数据
  • * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  • * @param {uint8_t} addr        器件地址(0x00~0x7f)
  • * @param {uint8_t} regAddr        寄存器地址(0x00~0xff)
  • * @param {uint8_t} amount        读取数据数量(0x00~0xff)
  • * @param {uint8_t*} data        返回数据指针
  • * @param {uint8_t} typ                数据指针类型(由于结构体和数组存储方式不一样,因此需要区分)
  • *                                                 ARRAY        数组
  • *                                                 STRUCT        结构体
  • * @return {*}                        FAILD   读取失败 数据无效
  • *                                                 SUCCEED 读取成功 数据有效
  • */
  • uint8_t S_I2C_ReadRegister(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ)
  • {
  •         S_I2C_Start(I2C_temp);
  •         addr = (addr << 1) | 0x01;
  •         if(S_I2C_SendByte(I2C_temp, addr) == NACK)
  •         {
  •                 S_I2C_Stop(I2C_temp);
  •                 return FAILED;
  •         }
  •         if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
  •         {
  •                 S_I2C_Stop(I2C_temp);
  •                 return FAILED;
  •         }
  •         for(amount -= 1;amount;amount --)
  •         {
  •                 *data = S_I2C_ReceiveByte(I2C_temp, ACK);
  •                 if(typ == ARRAY)
  •                         data ++;
  •                 else
  •                         data --;
  •         }
  •         *data = S_I2C_ReceiveByte(I2C_temp, NACK);
  •         S_I2C_Stop(I2C_temp);
  •         return SUCCEED;
  • }
  • /**
  • * @description:                 读取器件,读取格式:器件写-寄存器地址-器件读-读取数据
  • * @param {I2C_Struct} I2C_temp        I2C_IO结构体
  • * @param {uint8_t} addr        器件地址(0x00~0x7f)
  • * @param {uint8_t} regAddr        寄存器地址(0x00~0xff)
  • * @param {uint8_t} amount        读取数据数量(0x00~0xff)
  • * @param {uint8_t*} data        返回数据指针
  • * @param {uint8_t} typ                数据指针类型(由于结构体和数组存储方式不一样,因此需要区分)
  • *                                                 ARRAY        数组
  • *                                                 STRUCT        结构体
  • * @return {uint8_t}        FAILD   读取失败 数据无效
  • *                                                 SUCCEED 读取成功 数据有效
  • */
  • uint8_t S_I2C_PointerRead(I2C_Struct I2C_temp, uint8_t addr, uint8_t regAddr, uint8_t amount, uint8_t* data, uint8_t typ)
  • {
  •         addr <<= 1;
  •         S_I2C_Start(I2C_temp);
  •         if(S_I2C_SendByte(I2C_temp, addr) == NACK)
  •         {
  •                 S_I2C_Stop(I2C_temp);
  •                 return FAILED;
  •         }
  •         if(S_I2C_SendByte(I2C_temp, regAddr) == NACK)
  •         {
  •                 S_I2C_Stop(I2C_temp);
  •                 return FAILED;
  •         }
  •         S_I2C_Stop(I2C_temp);
  •         addr |= 0x01;
  •         S_I2C_Start(I2C_temp);
  •         if(S_I2C_SendByte(I2C_temp, addr) == NACK)        //NACK
  •         {
  •                 S_I2C_Stop(I2C_temp);
  •                 return FAILED;
  •         }
  •         for(amount -= 1;amount;amount --)
  •         {
  •                 *data = S_I2C_ReceiveByte(I2C_temp, ACK);
  •                 if(typ == ARRAY)
  •                         data ++;
  •                 else
  •                         data --;
  •         }
  •         *data = S_I2C_ReceiveByte(I2C_temp, NACK);
  •         S_I2C_Stop(I2C_temp);
  •         return SUCCEED;
  • }

复制代码


使用方法
  • void main(void)
  • {
  •         CLOCK_Init();
  •         GPIO_Init();
  •         S_I2C_Init();//初始化结构体,在宏定义中修改引脚等定义
  •         //接下来就可以调用I2C函数了
  • }

复制代码


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

342

主题

2359

帖子

4

粉丝