I2C 使用指南*
第一章 概述*
i2c 是可配置,可综合和可编程的控制总线,为系统中集成电路之间的通信链路提供支持。它是一个简单的双线总线,带有用于系统控制的软件定义协议,用于温度传感器和电压电平转换器,通用 I/O,A/D 和 D/A 转换器,COREC 和许多类型的微处理器。
IIC 也称 I2C,是一个多主从的串行总线,由飞利浦公司发明的通讯总线,属于半双工同步传输类总线,仅由两条线就能完成多机通讯,一条 SCL 时钟线,另外一条双向数据线 SDA,IIC 总线要求每个设备 SCL/SDA 线都是漏极开路模式,因此必须带上拉电阻才能正常工作。I2C 协议占用引脚少,硬件实现简单,可扩展性强,I2C 数据传输速率有标准模式 (100kbps)、快速模式 (400kbps) 和高速模式 (3.4Mbps)。所有接到 I2C 总线设备上的串行数据 SDA 都接到总线的 SDA 上,各设备的时钟线 SCL 接到总线的 SCL 上。I2C 总线上的每个设备都自己一个唯一的地址,来确保不同设备之间访问的准确性。任何时间点上只能有一个主控,且 SCL 由主控控制
第二章 APUS I2C 功能描述*
2.1 功能特性*
-
三路 I2C 总线控制器
-
串行数据线 (SDA) 和串行时钟 (SCL) 组成
- 支持标准模式 (100kbit/s)
- 支持快速模式 (400kbit/s)
- 支持高速模式 (3.4Mbit/s)
- 支持主机模式和从机模式
- 支持7-bit/10-bit寻址
- 批量传输模式
- 发送和接收缓冲区
- 中断或轮询模式操作
- 处理所有总线速度下的位和字节
- DMA 握手接口
- 可编程的 SDA 保持时间
- 作为 I2C 系统中的主机时,仅作为主机编程
- 作为 I2C 系统中的从站时,仅作为从站编程
第三章 i2C Master参考例子*
- 具体接口细节请参看头文件apus/platform/drv-apus/include/gx_i2c.h
3.1 I2C Master读写寄存器数据*
方式一 I2C Master读写*
static int i2c_master_example(int argc, char * const argv[])
{
padmux_set(I2C0_SCL_PIN, 10);
padmux_set(I2C0_SDA_PIN, 11);
/* 初始化i2c0 */
gx_i2c_init(0);
/* 设置i2c传输速度 */
gx_i2c_set_speed(0, 1000);
/* 初始化dma */
gx_dma_init();
unsigned char bus = 0, slv_addr = 0x57, address_width = 1;
unsigned int reg = 0x09;
unsigned char data = 0x03;
unsigned short len = 1;
int ret = -1;
/* 使用i2c0向设备地址为0x57的slave的0x09寄存器写入0x03 */
ret = gx_i2c_tx(bus, slv_addr, reg, address_width, &data, len);
if (ret != 0) {
printf("error\n");
return ret;
}
/* 使用i2c0读取设备地址为0x57的slave的0x03寄存器 */
ret = gx_i2c_rx(bus, slv_addr, reg, address_width, &data, len);
if (ret != 0) {
printf("error\n");
return ret;
}
printf("data = %d\t\n", data);
return 0;
}
COMMAND_EXPORT_ALIAS(i2c_master_example, i2c_master_example, "i2c_master_example");
方式二 i2C Master读写数据*
int i2c_master_example1(void)
{
padmux_set(I2C0_SCL_PIN, 10);
padmux_set(I2C0_SDA_PIN, 11);
/* 初始化i2c0 */
gx_i2c_init(0);
/* 设置i2c传输速度 */
gx_i2c_set_speed(0, 1000);
/* 初始化dma */
gx_dma_init();
unsigned char bus = 0, slv_addr = 0x57;
unsigned char data = 0x09;
unsigned short len = 1;
/* 使用i2c0向设备地址为0x57的slave写入0x09 */
ret = gx_i2c_write(bus, slv_addr, &data, len);
if (ret != 0) {
printf("error\n");
return ret;
}
/* 使用i2c0读取设备地址为0x09的slave */
ret = gx_i2c_read(bus, slv_addr, &data, len);
if (ret != 0) {
printf("error\n");
return ret;
}
return 0;
}
COMMAND_EXPORT_ALIAS(i2c_master_example1, i2c_master_example1, "i2c_master_example1");
方式三 i2C Master写数据*
int i2c_master_example2(void)
{
padmux_set(I2C0_SCL_PIN, 10);
padmux_set(I2C0_SDA_PIN, 11);
/* 初始化i2c0 */
gx_i2c_init(0);
/* 设置i2c传输速度 */
gx_i2c_set_speed(0, 1000);
/* 初始化dma */
gx_dma_init();
void *i2c_dev = NULL;
GX_I2C_MSG msgs;
unsigned char data = 0x09;
unsigned short len = 1;
unsigned char bus = 0, slv_addr = 0x57;
/* 打开i2c0 */
i2c_dev = gx_i2c_open(bus);
if (!i2c_dev) {
i2c_debug("open i2c dev failed.\n");
return -1;
}
/* 发送msg,向0x57的slave写0x09,作用与gx_i2c_write一致 */
msgs.len = len;
msgs.addr = slv_addr;
msgs.buf = &data;
msgs.flags = 0;
status = gx_i2c_transfer(i2c_dev, &msgs, 1);
/* 关闭i2c0 */
gx_i2c_close(i2c_dev);
return 0;
}
COMMAND_EXPORT_ALIAS(i2c_master_example2, i2c_master_example2, "i2c_master_example2");
方式四 i2C Master读数据*
int i2c_master_example3(void)
{
padmux_set(I2C0_SCL_PIN, 10);
padmux_set(I2C0_SDA_PIN, 11);
/* 初始化i2c0 */
gx_i2c_init(0);
/* 设置i2c传输速度 */
gx_i2c_set_speed(0, 1000);
/* 初始化dma */
gx_dma_init();
void *i2c_dev = NULL;
GX_I2C_MSG msgs;
unsigned char bus = 0, slv_addr = 0x57, address_width = 1;
unsigned char reg = 0x09, data = 0x40;
unsigned short len = 1;
/* 打开i2c0 */
i2c_dev = gx_i2c_open(bus);
if (!i2c_dev) {
i2c_debug("open i2c dev failed.\n");
return -1;
}
/* 发送msg,读取设备地址为0x57的slave的0x09寄存器,作用与gx_i2c_rx一致 */
msgs[0].addr = slv_addr;
msgs[0].buf = ®
msgs[0].len = address_width;
msgs[0].flags = 0;
msgs[1].addr = slv_addr;
msgs[1].buf = &data;
msgs[1].len = len;
msgs[1].flags = I2C_M_RD;
ret = gx_i2c_transfer(dev, msgs, 2);
/* 关闭i2c0 */
gx_i2c_close(i2c_dev);
return 0;
}
COMMAND_EXPORT_ALIAS(i2c_master_example3, i2c_master_example3, "i2c_master_example3");
3.2 i2C Master 中断读写*
其他中断读写API请参考头文件apus/platform/drv-apus/include/gx_i2c.h, 使用方式与3.1方式相似
static void async_callback(void *priv)
{
printf("%s!!\n", __func__);
}
static int i2c_master_async_example(int argc, char * const argv[])
{
unsigned char rx_buffer[256] __attribute__((aligned(DCACHE_LINE_SIZE)));
padmux_set(I2C0_SCL_PIN, 10);
padmux_set(I2C0_SDA_PIN, 11);
/* 初始化i2c0 */
gx_i2c_init(0);
/* 设置i2c传输速度 */
gx_i2c_set_speed(0, 1000);
/* 初始化dma */
gx_dma_init();
unsigned char bus = 0, slv_addr = 0x57, address_width = 1;
unsigned int reg = 0x09;
unsigned char data = 0x03;
unsigned short len = 1;
int ret = -1;
/* 使用i2c0向设备地址为0x57的slave的0x09寄存器写入0x03 */
ret = gx_i2c_async_tx(bus, slv_addr, reg, address_width, &data, len, async_callback, NULL);
if (ret != 0) {
printf("error\n");
return ret;
}
/* 使用i2c0读取设备地址为0x57的slave的0x03寄存器 */
ret = gx_i2c_async_rx(bus, slv_addr, reg, address_width, rx_buffer, 1, async_callback, NULL);
if (ret != 0) {
printf("gx_i2c_async_rx error\n");
return ret;
}
printf("data = %d\t\n", data);
return 0;
}
COMMAND_EXPORT_ALIAS(i2c_master_async_example, i2c_master_async_example, "i2c_master_async_example");
3.3 i2C MasterDMA读写*
使用接口同 i2C Master 中断读写。使能i2C DMA需要打开 apus/platform/drv-apus/src/i2c.c 控制
#define CONFIG_I2C_DMA
第四章 I2C Slave示例代码*
4.1 i2c slave 中断读写*
- 具体接口细节请参看头文件apus/platform/drv-apus/include/gx_i2c.h
void do_someting(void)
{
printf("stop\n");
}
static int gx_i2c_slave_async_callback(GX_I2C_SLAVE_EVENT event, unsigned char *val, void *private)
{
unsigned char data;
switch (event) {
/* 检测到stop信号 */
case I2C_SLAVE_STOP:
do_someting();
break;
/* 检测到读请求 */
case I2C_SLAVE_REQUESTED_DATA:
/* 返回给master 0x33 */
*val = 0x33;
break;
/* 检测到写请求 */
case I2C_SLAVE_RECEIVE_DATA:
/* 获取master发送的数据 */
data = *val;
break;
default:
break;
}
}
int i2c_slave_example(void)
{
unsigned char bus = 1, slv_addr = 0x57;
padmux_set(I2C1_SCL_PIN, 12);
padmux_set(I2C1_SDA_PIN, 13);
/* 初始化i2c0为设备地址0x57的slave */
gx_i2c_slave_open(bus, slv_addr, gx_i2c_slave_async_callback, NULL);
return 0;
}
COMMAND_EXPORT_ALIAS(i2c_slave_example, i2c_slave_example, "i2c_slave_example");
4.2 i2c slave DMA 响应读写*
- 使用接口同**i2c slave 中断**读写, 使能i2C DMA需要在apus/platform/drv-apus/src/i2c.c 定义相关控制
#define CONFIG_I2C_SLAVE_DMA_RX_TEST
#define CONFIG_I2C_SLAVE_DMA_TX_TEST
4.3 i2c slave DMA 特殊响应读写*
在 i2c master 未发起读的时候,i2c slave 先发起 dma 传输,等待 master 来读取,以此降低 DMA 初始化等过程的时延。初始化 i2c slave DMA 后调用 gx_i2c_slave_enable_fast_dma_tx 函数来使能该功能。
int gx_i2c_slave_enable_fast_dma_tx(unsigned char bus_id)
{
if (bus_id > 2)
return -1;
*(volatile unsigned int *)0xb500001C |= 1 << (bus_id * 4);
return 0;
}
- 未使用该功能
- 使用该功能