管理多条模拟IIC总线方法

本文档详细介绍了在嵌入式系统中使用软件设计多条模拟IIC总线的方法,涉及GPIO配置、IIC通信函数如读写地址、数据和页面操作,适用于三轴传感器、温度传感器和AT24CEEPROM等设备的通信。

问题:当使用多条模拟IIC总线:软件如何设计

问题链接
https://segmentfault.com/a/1190000022107594

链接1

在这里插入图片描述

代码示例:

#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


评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值