问题:当使用多条模拟IIC总线:软件如何设计
问题链接
https://segmentfault.com/a/1190000022107594

代码示例:
#include "bsp_iic_extend.h"
/*
* IIC读写方式扩展版本
* 方便扩展IO
* 更新版本V0001
* author: lei--
*/
/*
* 支持的设备
*/
/*
*三轴+温度+EEPROM
*/
iic_control_t iic_ctl_triaxial = {0};
iic_control_t iic_ctl_temper = {0};
iic_control_t iic_ctl_at24c = {0};
/*
* 初始IIC_IO
*/
void bsp_iic_object_init_extend(void)
{
iic_ctl_triaxial.SCL_GPIOx = GPIOB;
iic_ctl_triaxial.SCL_Pin = GPIO_PIN_6;
iic_ctl_triaxial.SDA_GPIOx = GPIOB;
iic_ctl_triaxial.SDA_Pin = GPIO_PIN_7;
iic_ctl_triaxial.Speed = 1;
iic_ctl_temper.SCL_GPIOx = GPIOC;
iic_ctl_temper.SCL_Pin = GPIO_PIN_0;
iic_ctl_temper.SDA_GPIOx = GPIOC;
iic_ctl_temper.SDA_Pin = GPIO_PIN_1;
iic_ctl_temper.Speed = 1;
iic_ctl_at24c.SCL_GPIOx = GPIOB;
iic_ctl_at24c.SCL_Pin = GPIO_PIN_13;
iic_ctl_at24c.SDA_GPIOx = GPIOB;
iic_ctl_at24c.SDA_Pin = GPIO_PIN_14;
iic_ctl_at24c.Speed =1;
}
/*
* io拉高
*/
void bsp_iic_extend_gpio_high(GPIO_TypeDef *GPIOx,uint16_t Pin)
{
HAL_GPIO_WritePin(GPIOx, Pin, GPIO_PIN_SET);
}
/*
* io拉低
*/
void bsp_iic_extend_gpio_low(GPIO_TypeDef *GPIOx,uint16_t Pin)
{
HAL_GPIO_WritePin(GPIOx, Pin, GPIO_PIN_RESET);
}
/*
* io读
*/
uint8_t bsp_iic_extend_gpio_read(GPIO_TypeDef *GPIOx,uint16_t Pin)
{
return HAL_GPIO_ReadPin(GPIOx, Pin);
}
/*
* 设置IO模式
*/
void bsp_iic_extend_mode(iic_control_t *io_ctl, uint8_t mode, uint8_t high_low)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(mode == IIC_MODE_OUTPUT)
mode = GPIO_MODE_OUTPUT_PP;
else
mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pin = io_ctl->SDA_Pin;
GPIO_InitStruct.Mode = mode;
GPIO_InitStruct.Pull = IIC_IO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(io_ctl->SDA_GPIOx, &GPIO_InitStruct);
}
/*
* 初始化
*/
void user_iic_init_extend(iic_control_t *io_ctl)
{
EXTEND_SCL_HIGH(io_ctl);
user_delay(1);
EXTEND_SDA_HIGH(io_ctl);
user_delay(1);
}
/*
* 开始
*/
void user_iic_start_extend(iic_control_t *io_ctl)
{
EXTEND_SDA_HIGH(io_ctl);
user_delay(1);
EXTEND_SCL_HIGH(io_ctl);
user_delay(1);
EXTEND_SDA_LOW(io_ctl);
user_delay(1);
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
}
/*
* 停止
*/
void user_iic_stop_extend(iic_control_t *io_ctl)
{
EXTEND_SDA_LOW(io_ctl);
user_delay(1);
EXTEND_SCL_HIGH(io_ctl);
user_delay(1);
EXTEND_SDA_HIGH(io_ctl);
user_delay(1);
}
/*
* 应答
*/
void user_iic_ack_extend(iic_control_t *io_ctl,uint8_t ack)
{
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
if(ack == IIC_ACK)
{
EXTEND_SDA_LOW(io_ctl);
}
else
{
EXTEND_SDA_HIGH(io_ctl);
}
user_delay(1);
EXTEND_SCL_HIGH(io_ctl);
user_delay(1);
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
}
/*
* 等待应答
*/
uint8_t user_iic_wait_ack_extend(iic_control_t *io_ctl)
{
uint8_t ack =0;
uint8_t i =0;
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
bsp_iic_extend_mode(io_ctl, IIC_MODE_INPUT, IIC_IO_NOPULL);
EXTEND_SCL_HIGH(io_ctl);
user_delay(1);
for(i=0; i<IIC_WAIT_ACK_CNT; i++)
{
if( EXTEND_SDA_READ(io_ctl) == GPIO_PIN_SET)
{
ack = IIC_NO_ACK;
}
else
{
ack = IIC_ACK;
break;
}
user_delay(1);
}
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
bsp_iic_extend_mode(io_ctl, IIC_MODE_OUTPUT, IIC_IO_NOPULL);
return ack;
}
/*
*读写地址
*/
void user_iic_write_address_extend(iic_control_t *io_ctl, uint8_t dev_addr, uint8_t w_r_flag)
{
uint8_t i = 0;
uint8_t data = 0;
data = (dev_addr<<1) | w_r_flag;
for(uint8_t t=0; t<8; t++)
{
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
if(data & 0x80)
{
EXTEND_SDA_HIGH(io_ctl);
}
else
{
EXTEND_SDA_LOW(io_ctl);
}
user_delay(1);
EXTEND_SCL_HIGH(io_ctl);
user_delay(1);
data<<=1;
}
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
user_iic_wait_ack_extend(io_ctl);
}
/*
*写数据
*/
void user_iic_write_data_extend(iic_control_t *io_ctl, uint8_t data_t)
{
uint8_t i = 0;
uint8_t data = data_t;
for(uint8_t t=0; t<8; t++)
{
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
if(data & 0x80)
{
EXTEND_SDA_HIGH(io_ctl);
}
else
{
EXTEND_SDA_LOW(io_ctl);
}
user_delay(1);
EXTEND_SCL_HIGH(io_ctl);
user_delay(1);
data<<=1;
}
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
user_iic_wait_ack_extend(io_ctl);
}
/*
*读数据
*/
uint8_t user_iic_read_data_extend(iic_control_t *io_ctl, uint8_t ack)
{
uint8_t data =0;
bsp_iic_extend_mode(io_ctl, IIC_MODE_INPUT, IIC_IO_NOPULL);
for(uint8_t t=0; t<8; t++)
{
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
EXTEND_SCL_HIGH(io_ctl);
user_delay(1);
if( EXTEND_SDA_READ(io_ctl) )
{
data = data<<1 | 0x01;
}
else
{
data = data<<1 | 0x00;
}
}
EXTEND_SCL_LOW(io_ctl);
user_delay(1);
bsp_iic_extend_mode(io_ctl, IIC_MODE_OUTPUT, IIC_IO_NOPULL);
user_iic_ack_extend(io_ctl, ack);
return data;
}
/*
* 写一字节数据
*/
void user_write_byte_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint8_t mem_addr, uint8_t mem_data)
{
//开始
user_iic_start_extend(io_ctl);
//写地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_WRITE);
//内部寄存器地址
user_iic_write_data_extend(io_ctl, mem_addr);
//内部寄存器数据
user_iic_write_data_extend(io_ctl, mem_data);
//停止
user_iic_stop_extend(io_ctl);
}
/*
* 写一字节数据_16位内存地址
*/
void user_write_byte_16bit_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t mem_data)
{
//开始
user_iic_start_extend(io_ctl);
//写地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_WRITE);
//内部寄存器地址
user_iic_write_data_extend(io_ctl, mem_addr>>8);
user_iic_write_data_extend(io_ctl, mem_addr&0xFF);
//内部寄存器数据
user_iic_write_data_extend(io_ctl, mem_data);
//停止
user_iic_stop_extend(io_ctl);
}
/*
* 读一字节数据
*/
void user_read_byte_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint8_t mem_addr, uint8_t *mem_data)
{
uint8_t rec_data =0;
//开始
user_iic_start_extend(io_ctl);
//写地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_WRITE);
//内部寄存器地址
user_iic_write_data_extend(io_ctl, mem_addr);
//开始
user_iic_start_extend(io_ctl);
//读地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_READ);
//读数据
rec_data = user_iic_read_data_extend(io_ctl, IIC_NO_ACK);
//停止
user_iic_stop_extend(io_ctl);
*mem_data = rec_data;
}
/*
* 读一字节数据_16位地址
*/
void user_read_byte_16bit_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t *mem_data)
{
uint8_t rec_data =0;
//开始
user_iic_start_extend(io_ctl);
//写地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_WRITE);
//内部寄存器地址
user_iic_write_data_extend(io_ctl, mem_addr>>8);
user_iic_write_data_extend(io_ctl, mem_addr&0xFF);
//开始
user_iic_start_extend(io_ctl);
//读地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_READ);
//读数据
rec_data = user_iic_read_data_extend(io_ctl, IIC_NO_ACK);
//停止
user_iic_stop_extend(io_ctl);
*mem_data = rec_data;
}
/*
* 读多字节数据-部分设备
*/
void user_iic_read_byte_more_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint8_t mem_addr, uint8_t *mem_data, uint8_t length)
{
uint8_t rec_buff[8] ={0};
if(length > 8)
return;
//开始
user_iic_start_extend(io_ctl);
//写地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_WRITE);
//内部寄存器地址
user_iic_write_data_extend(io_ctl, mem_addr);
//开始
user_iic_start_extend(io_ctl);
//读地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_READ);
//读数据
rec_buff[0] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[1] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[2] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[3] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[4] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[5] = user_iic_read_data_extend(io_ctl, IIC_NO_ACK);
//停止
user_iic_stop_extend(io_ctl);
memcpy(mem_data, rec_buff, length);
}
/*
* 读多字节数据-16为内存地址
*/
void user_iic_read_byte_more_16bit_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t *mem_data, uint8_t length)
{
uint8_t rec_buff[8] ={0};
if(length > 8)
return;
//开始
user_iic_start_extend(io_ctl);
//写地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_WRITE);
//内部寄存器地址1
user_iic_write_data_extend(io_ctl, mem_addr>>8);
//内部寄存器地址2
user_iic_write_data_extend(io_ctl, mem_addr&0xFF);
//部分设备读取等待
rt_thread_mdelay(20);
//开始
user_iic_start_extend(io_ctl);
//读地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_READ);
//读数据
rec_buff[0] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[1] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[2] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[3] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[4] = user_iic_read_data_extend(io_ctl, IIC_ACK);
rec_buff[5] = user_iic_read_data_extend(io_ctl, IIC_NO_ACK);
//停止
user_iic_stop_extend(io_ctl);
memcpy(mem_data, rec_buff, length);
}
/*
* 写多字节数据_16位内存地址
* IIC_EEPROM_at24c512
* 页写
*/
void user_write_byte_16bit_page_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t *mem_data, uint8_t len)
{
//开始
user_iic_start_extend(io_ctl);
//写地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_WRITE);
//内部寄存器地址
user_iic_write_data_extend(io_ctl, mem_addr>>8);
user_iic_write_data_extend(io_ctl, mem_addr&0xFF);
if(len >= AT24C512_PAGE_SIZE)
len = AT24C512_PAGE_SIZE;
if(mem_addr + len > AT24C512_ROM_SIZE)
len = AT24C512_ROM_SIZE - mem_addr;
if((mem_addr%AT24C512_PAGE_SIZE) + len > AT24C512_PAGE_SIZE)
len = len - ((mem_addr+len)%AT24C512_PAGE_SIZE) ;
for(uint8_t t=0; t<len; t++)
{
//内部寄存器数据
user_iic_write_data_extend(io_ctl, *(mem_data+t));
}
//停止
user_iic_stop_extend(io_ctl);
}
/*
* 读多字节数据_16位内存地址
* IIC_EEPROM_at24c512
* 页读
*/
void user_read_byte_16bit_page_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t *mem_data, uint8_t len)
{
//开始
user_iic_start_extend(io_ctl);
//写地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_WRITE);
//内部寄存器地址
user_iic_write_data_extend(io_ctl, mem_addr>>8);
user_iic_write_data_extend(io_ctl, mem_addr&0xFF);
//开始
user_iic_start_extend(io_ctl);
//读地址
user_iic_write_address_extend(io_ctl, dev_addr, IIC_READ);
if(len >= AT24C512_PAGE_SIZE)
len = AT24C512_PAGE_SIZE;
if(mem_addr + len > AT24C512_ROM_SIZE)
len = AT24C512_ROM_SIZE - mem_addr;
if((mem_addr%AT24C512_PAGE_SIZE) + len > AT24C512_PAGE_SIZE)
len = len - ((mem_addr+len)%AT24C512_PAGE_SIZE) ;
for(uint8_t t=0; t<len; t++)
{
//内部寄存器数据
*(mem_data+t) = user_iic_read_data_extend(io_ctl, IIC_ACK);
}
//停止
user_iic_stop_extend(io_ctl);
}
#ifndef __BSP_IIC_EXTEND_H
#define __BSP_IIC_EXTEND_H
#include "app_user.h"
/*
* IO定义
*/
#define EXTEND_SCL_HIGH(gpio) bsp_iic_extend_gpio_high((gpio)->SCL_GPIOx, (gpio)->SCL_Pin)
#define EXTEND_SCL_LOW(gpio) bsp_iic_extend_gpio_low((gpio)->SCL_GPIOx, (gpio)->SCL_Pin)
#define EXTEND_SDA_HIGH(gpio) bsp_iic_extend_gpio_high((gpio)->SDA_GPIOx, (gpio)->SDA_Pin)
#define EXTEND_SDA_LOW(gpio) bsp_iic_extend_gpio_low((gpio)->SDA_GPIOx, (gpio)->SDA_Pin)
#define EXTEND_SDA_READ(gpio) bsp_iic_extend_gpio_read((gpio)->SDA_GPIOx, (gpio)->SDA_Pin)
//未定义
#ifndef AT24C512_PAGE_SIZE
#define AT24C512_PAGE_SIZE (128)
#endif
#ifndef AT24C512_ROM_SIZE
#define AT24C512_ROM_SIZE (64*1024)
#endif
/*
* IO定义
*/
typedef struct
{
GPIO_TypeDef *SCL_GPIOx;
uint16_t SCL_Pin;
GPIO_TypeDef *SDA_GPIOx;
uint16_t SDA_Pin;
uint8_t Speed;
}iic_control_t;
extern void bsp_iic_object_init_extend(void);
extern void user_iic_init_extend(iic_control_t *io_ctl);
extern void user_write_byte_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint8_t mem_addr, uint8_t mem_data);
extern void user_write_byte_16bit_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t mem_data);
extern void user_read_byte_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint8_t mem_addr, uint8_t *mem_data);
extern void user_read_byte_16bit_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t *mem_data);
extern void user_iic_read_byte_more_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint8_t mem_addr, uint8_t *mem_data, uint8_t length);
extern void user_iic_read_byte_more_16bit_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t *mem_data, uint8_t length);
extern void user_write_byte_16bit_page_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t *mem_data, uint8_t len);
extern void user_read_byte_16bit_page_extend(iic_control_t *io_ctl, uint8_t dev_addr,uint16_t mem_addr, uint8_t *mem_data, uint8_t len);
#endif
本文档详细介绍了在嵌入式系统中使用软件设计多条模拟IIC总线的方法,涉及GPIO配置、IIC通信函数如读写地址、数据和页面操作,适用于三轴传感器、温度传感器和AT24CEEPROM等设备的通信。
8026





