STM32F4IO口模拟多个IIC方案
一、问题来源
最近在做一个比赛要用到6个激光测距传感器(VL53L0),原计划用Modbus协议的,但是由于不知名原因(可能是线太长了,PCB板子没有加终端电阻),总是只能驱动一个激光,加上第二个激光就会读不出来数据,所以打算用IIC协议,但是正点原子IIC协议的底层函数是用宏实现的,只能支持一个IIC,激光模块上也没有片选口,只能采用6个不同的IIC控制6个激光的方案或者使用TI的TCA9548AIIC拓展芯片的方法来解决,我采用的是6个不同的IIC控制6个激光的方案。
二、IIC相对于Modbus的协议的优势
Modbus协议区分两组不同的命令的方式是靠延时,激光模块的厂家给的例程两组命令间隔100ms这样我600ms才能轮询一边所有激光,速度有些慢,而IIC协议来通信只需要间隔20ms的激光传感器最快测距等待时间读取传感器的值就可以了,如果配置传感器为连续测量模式我几乎就是20ms就可以获得6个传感器的数据。速度相对于Modbus协议快了很多。但是Modbus的CRC校验可以保证数据的准确性,IIC不能。
三、解决方法
下面是我想到的几种方法
1、使用函数指针,使用不同的IIC前更改指针指向的函数,但是这种方法要建立很多函数或者宏,比较麻烦。
2、使用##更改宏,根据不同的传入参数达到使用不同函数的效果,但是我没有成功。
3、使用结构体数组,更改原有的宏和底层函数,调用不同的结构体来实现IIC之间的转换。
四 具体实现方法
1、首先建立一个结构体,内容分别是SCL和SDA的GPIO和引脚。
typedef struct
{
GPIO_TypeDef *SCL_GPIO;
uint32_t SCL_Pin;
GPIO_TypeDef *SDA_GPIO;
uint32_t SDA_Pin;
}LDC_IIC;
2、然后初始化结构体数组,这里要把keil的模式调成C99模式,这时串口的printf函数那里会报错,在前面加一个void就可以了。
LDC_IIC LDC_VL53L0X[6]={
[0]={
.SCL_GPIO=GPIOE,.SCL_Pin=GPIO_Pin_13,.SDA_GPIO=GPIOE,.SDA_Pin=GPIO_Pin_15},
[1]={
.SCL_GPIO=GPIOG,.SCL_Pin=GPIO_Pin_2,.SDA_GPIO=GPIOG,.SDA_Pin=GPIO_Pin_4},
[2]={
.SCL_GPIO=GPIOB,.SCL_Pin=GPIO_Pin_0,.SDA_GPIO=GPIOB,.SDA_Pin=GPIO_Pin_2},
[3]={
.SCL_GPIO=GPIOC,.SCL_Pin=GPIO_Pin_0,.SDA_GPIO=GPIOC,.SDA_Pin=GPIO_Pin_2},
[4]={
.SCL_GPIO=GPIOG,.SCL_Pin=GPIO_Pin_9,.SDA_GPIO=GPIOG,.SDA_Pin=GPIO_Pin_11},
[5