中科蓝讯 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> 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
如果你的器件地址是 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) { //ÊÕµÚ1bytecfg |= START_FLAG0 | DEV_ADDR0 | START_FLAG1 |REG_ADDR_1 ;}if (i == (len - 1)) { //ÊÕ×îºó1bytecfg |= 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 addrcfg |= START_FLAG0 | DEV_ADDR0; // cfg = 起始信号 + 设备地址
#if 0 //!I2C_ADDRESSING_16BITcfg |= REG_ADDR_0;
#elsecfg |= REG_ADDR_1; // 16位寻址方式
#endifbsp_i2c_config(cfg, dev_addr, reg_addr, 0);//step2:read reg addrfor (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) { //ÊÕµÚ1bytecfg |= START_FLAG0 | DEV_ADDR0 | REG_ADDR_0 | WDATA | STOP_FLAG;}if (i == (len - 1)) { //ÊÕ×îºó1bytecfg |= 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 *****************************************/
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
