中科蓝讯 IIC 操作

在我们的开发过程中,我们会发现好多外设都是通过I2C来通讯的。(当然啦,还有一些通过spi、uart等的协议进行通讯的)在使用I2C进行通讯的时候会发现有两种i2c的通讯方式,一种是模拟、一种是硬件。

这里就不说I2C的这两种方式的区别和I2C通讯的模式了,这些可以通过查博客进行了解。

在中科蓝讯的SDK代码中也提供了模拟和硬件的两种通讯方式。(在 bsp_i2c.c 文件中)可以自己去查看,这里就不说各个函数的功能了,就只说下我们需要注意的地方。

一、模拟I2C

这种方式就是通过调节IO电平来模拟I2C 通讯时候的波形来进行数据的传输。我们只需要将i2c的初始化放在外设初始化之前,正常的情况下使用读写函数是可以正常进行读写数据的。我们在使用的过程中需要注意外设的寄存器地址是8bit还是16bit的,需要与程序中的进行对应,否则会出现读写错误或者失败。

    

/***************************************************
    我这里的代码是对寄存器地址16bit的进行读写的函数
通过上面传入进来的 addr类型可以知道,该寄存器地址是16bit的。所以我们需要先发送高8bit再发送低8bit。因为内部bsp_i2c_tx_byte 函数是发送8bit的数据,所以16bit的需要分两次进行发送
***************************************************/
// i2c 的写函数
AT(.text.bsp.i2c)
void i2c_write_tx_byte(u8 I2C_ADDR,u16 addr, u8 *dat,u32 len)
{
    bsp_i2c_start();
    bsp_i2c_tx_byte(I2C_ADDR);
    bsp_i2c_rx_ack();
    bsp_i2c_tx_byte((u8)(addr >> 8));
    bsp_i2c_rx_ack();
    bsp_i2c_tx_byte((u8)(addr & 0xff));
    bsp_i2c_rx_ack();
	for(int i =0;i<len;i++)
	{
		bsp_i2c_tx_byte(dat[i]);
    	bsp_i2c_rx_ack();
	}
    bsp_i2c_stop();

}
// i2c 的读函数
AT(.text.bsp.i2c)
u8* i2c_read_rx_byte(u8 I2C_ADDR,u16 addr,u8 *dat,u32 len)
{
    bsp_i2c_start();
    bsp_i2c_tx_byte(I2C_ADDR);
    bsp_i2c_rx_ack();
    bsp_i2c_tx_byte((u8)(addr >> 8));
    bsp_i2c_rx_ack();
    bsp_i2c_tx_byte((u8)(addr & 0xff));
    bsp_i2c_rx_ack();
    bsp_i2c_start();
    bsp_i2c_tx_byte(I2C_ADDR | BIT(0));
    bsp_i2c_rx_ack();
	for(int i=0;i<len;i++)
	{
	    dat[i] = bsp_i2c_rx_byte();
		if(i ==(len-1))
	    	bsp_i2c_tx_ack();
		else
			bsp_i2c_tx_ack();
	}
    bsp_i2c_stop();
    return dat;
}

        如果你的器件地址是 8bit 那就不需要先发高8bit然后发低8bit了。就直接发送器件地址就可以了。还有一个要注意的,在读写的时候设备地址的bit0 是有区别的(0 写,1 读),所以在读取数据的时候需要在 I2C_ADDR 的 bit0 置1.

二、硬件I2C

        原理上和上面模拟的差不多,只是读写函数有内部提供的。

/*
    下面两个函数分别是寄存器16bit的读写函数
*/
void bsp_i2c_tx_buf(u16 dev_addr, u16 reg_addr, u8* data, u32 len)
{
	int i;
    u32 cfg;
    if (len == 0) {
        return;
    }

	for (i = 0; i < len; i++) {
        cfg = WDATA;
        if (i == 0) {               //ÊÕµÚ1byte
            
			cfg |= START_FLAG0 | DEV_ADDR0 | START_FLAG1 |REG_ADDR_1 ;
        }
        if (i == (len - 1)) {       //ÊÕ×îºó1byte
            cfg |= STOP_FLAG;
        }
        bsp_i2c_config(cfg, dev_addr, reg_addr, data[i]);
    }
}
void bsp_i2c_tx_to_rx_buf(u16 dev_addr, u16 reg_addr, u8 *buf, u16 len)
{
    u32 cfg = 0;
    u16 i;

    if (buf == NULL || len == 0)
    {
        return;
    }

    //step1: write reg addr
    cfg |= START_FLAG0 | DEV_ADDR0; // cfg = 起始信号 + 设备地址
#if 0  //!I2C_ADDRESSING_16BIT
    cfg |= REG_ADDR_0;
#else
    cfg |= REG_ADDR_1; // 16位寻址方式
#endif

    bsp_i2c_config(cfg, dev_addr, reg_addr, 0);

    //step2:read reg addr
    for (i = 0; i < (len + 1); i++)
    {
        cfg = RDATA; // 获取硬件读寄存器里的数据

        if (i == 0)                 //收第1byte
        {
            cfg |= START_FLAG0 | DEV_ADDR0; // 如果是第一byte数据,则额外加上:  起始信号+设备地址
            bsp_i2c_config(cfg, dev_addr | 0x01, reg_addr, 0);
        }
        else
        {
            if (i == (len))         //收最后1byte
            {
                cfg |= STOP_FLAG | NACK; // 如果是最后一byte数据 则额外加上: 停止信号+不需要对方应答信号
            }
            buf[i-1] = bsp_i2c_config(cfg, dev_addr, reg_addr, 0);
        }
    }
}


/*
    下面的函数是寄存器8bit的写函数
*/
void bsp_i2c_tx_buf1(u16 dev_addr, u16 reg_addr, u8* data, u32 len)
{
	int i;
    u32 cfg;
    if (len == 0) {
        return;
    }
    for (i = 0; i < len; i++) {
        cfg = WDATA;
        if (i == 0) {               //ÊÕµÚ1byte
            cfg |= START_FLAG0 | DEV_ADDR0 | REG_ADDR_0 | WDATA | STOP_FLAG;
        }
        if (i == (len - 1)) {       //ÊÕ×îºó1byte
            cfg |= STOP_FLAG | NACK;
        }
        data[i] = bsp_i2c_config(cfg, dev_addr, reg_addr, data[i]);
        //printf("==> i2c tx buf[%d] = 0x%x \n",i,  data[i]);
    }
}

        其实硬件的读写函数我们看到的没有什么大的区别,主要区别在于系统提供的static u32 bsp_i2c_config(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u32 dat) 函数中的 i2c_cfg 参数进行区别读写、寄存器地址8bit还是16bit

这里来说几个关键的值:

        WDATA:表示该函数是写数据到寄存器中

        RDATA:表示该函数是读寄存器里面的数据

        REG_ADDR_0:寄存器地址是8bit

        REG_ADDR_1:寄存器地址是16bit

/***************************************** END *****************************************/

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值