当设计中使用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函数了
- }
复制代码
|
|