IIC
📎 原始文档:https://www.kdocs.cn/l/cbL2zOx5Gs7Z IIC
IO口及其他配置定义
此处以695_demo板级配置文件举例:
IIC基础使用函数
此处以695的软件IIC举例,同时也建议客户使用软件IIC来进行IIC各项操作。
函数文件:iic_soft.c iic_soft.h
IIC一般使用方式
#define WRITEORDER 0x58 //写命令
#define READORDER 0x59 //读命令
参考使用方式
//指定寄存器地址写一个字节
u8 I2C_write_byte(u8 writeAddr,u8 byte)
{
u8 ret = 0;
iic_start(iic); //I2C启动
ret += iic_tx_byte(iic, WRITEORDER); //写命令
ret += iic_tx_byte(iic,writeAddr); //写地址
ret += iic_tx_byte(iic,byte); //写一个字节
iic_stop(iic); //产生一个停止条件
if(ret < 3){
return 1;
}
else{
return 0;
}
}
//指定寄存器地址读一个字节
u8 I2C_read_byte(u8 readaddr)
{
u8 ret = 0;
u8 data = 0;
iic_start(iic); //I2C启动
ret += iic_tx_byte(iic, WRITEORDER); //写命令
ret += iic_tx_byte(iic,readaddr); //read地址
iic_stop(iic); //I2C停止
iic_start(iic); //I2C启动(写转为读命令,需要再次启动I2C)
ret += iic_tx_byte(iic, READORDER); //读命令
data = iic_rx_byte(iic, 0); //读操作
iic_stop(iic); //产生一个停止条件
if(ret < 3){
return 1;
}
else{
return data;
}
}
/**********************************************************
//在指定地址写入数据
//writeset_addr :写入数据的器件地址
//writeAddr :寄存器地址
//buf :要写入的数据
//len :写入的长度
**********************************************************/
u8 IIC_write_reg(char writeset_addr,char writeAddr,const void *buf, int len)
{
u8 ret = 0;
u8 i = 0;
u8 ack = 0;
iic_start(iic); //I2C启动
ret += iic_tx_byte(iic, writeset_addr); //写器件地址
ret += iic_tx_byte(iic,writeAddr); //写寄存器地址
for (i = 0; i < len; i++) {
ret += iic_tx_byte(iic, ((char *)buf)[i]);
}
iic_stop(iic); //产生一个停止条件
if(ret < len+2){
return 1;
}
else{
return 0;
}
}
/**********************************************************
//读指定地址的数据
//readaddr :读取数据的目的地址
//buf :读出的数据
//len :读出数据的长度z
**********************************************************/
u8 I2C_read_reg(u8 readaddr,void *buf, int len)
{
u8 ret = 0;
iic_start(iic); //I2C启动
ret += iic_tx_byte(iic, WRITEORDER); //写命令
ret += iic_tx_byte(iic,readaddr); //read地址
iic_stop(iic); //I2C停止
iic_start(iic); //I2C启动(写转为读命令,需要再次启动I2C)
ret += iic_tx_byte(iic, READORDER); //读命令
iic_read_buf(iic, &buf, len); //读操作
iic_stop(iic); //产生一个停止条件
if(ret < 3){
return 1;
}
else{
return 0;
}
}
IIC做从机参考资料
备注:其他系列调式逻辑也是一样的,挺多是寄存器配置不一样。寄存器配置可以看对应IC的用户手册IIC章节,如JL701N(详细内容自己看芯片用户手册,若没有芯片用户手册请找对应代理商拿):


外挂FM IIC通信参考
AC696X:
sd CLK 和 dat0 复用 IIC CLK和DATA ,SD卡只支持CLK检测
外挂FM复用SD卡引脚_696V170.zip
ac696n_soundbox_sdk_v0.2.3(5807 FM IIC 脚和 卡口复用 )
链接:https://pan.baidu.com/s/1GY2yNSr-ZcbKF6uuCScbdg
提取码:8888
AC695X:
AC695N_soundbox_sdk_release_0.0.7-外挂收音RDA5807复用SD卡
链接:https://pan.baidu.com/s/1rdX549Jzj9-heOauSDiOiw
提取码:8888
AC695N_soundbox_sdk_release_3.0.1(外挂5807收音正常版本)
链接:https://pan.baidu.com/s/1J6TLCDgyWxRETnwViFrosw
提取码:8888
AC608X:
ac608n_soundbox_sdk_v1.1.1-iic复用SD卡
链接:https://pan.baidu.com/s/1AGxayv5yPzWeDixSbQDedg
提取码:8888
AC700X:
AC7006F4SDK121外挂收音芯片5807参考DEMO
~~链接:https://pan.baidu.com/s/1P1djXnYdeZFfmbM_NRO-YQ ~~
~~提取码:8888 ~~
见FM相关应用.otl
AC700N耳机IIC驱动demo
【金山文档】 AC700N耳机IIC驱动demo
https://kdocs.cn/l/cjOxT1cC9STV
读写IIC外设寄存器demo(需要根据外设文档要求调整)
void delay_us(u32 us)
{
delay(us * 3);
}
#define iAP2_REG_ADDR_W 0b00100000
#define iAP2_REG_ADDR_R 0b00100001
static u8 is_iic_busy = 0;
int iAP2_ic_write(u8 reg_addr, u8 *data, u16 data_len)
{
u8 step1_retry_cnt = 0;
u8 step2_retry_cnt = 0;
u16 total_len = 0;
__retry:
is_iic_busy = 1;
iic_start();
iic_sendbyte_io(iAP2_REG_ADDR_W);
u8 nack = r_ack();
step1_retry_cnt++;
if(nack && step1_retry_cnt < 10){
delay_us(500);
goto __retry;
}
else if(nack){
iAP2_printf("func:%s line:%d failed", __func__, __LINE__);
goto __iic_end;
}
iic_sendbyte_io(reg_addr);
nack = r_ack();
step2_retry_cnt++;
if(nack && step2_retry_cnt < 10){
delay_us(500);
step1_retry_cnt = 0;
goto __retry;
}
else if(nack){
iAP2_printf("func:%s line:%d failed", __func__, __LINE__);
goto __iic_end;
}
u8 ret = 0;
for (; data_len > 0; data_len--) {
total_len++;
iic_sendbyte_io(*data++); //写数据
ret += r_ack();
delay_us(50);
}
iic_stop();
is_iic_busy = 0;
iAP2_printf("%s succ, ret %d-data:%d", __func__, ret, total_len);
return total_len;
__iic_end:
iic_stop();
is_iic_busy = 0;
iAP2_printf("%s fail, ret %d", __func__, ret);
return 0;
}
int iAP2_ic_read(u8 reg_addr, u8 *data, u16 read_len)
{
u8 step1_retry_cnt = 0;
u8 step2_retry_cnt = 0;
u16 total_len = 0;
__retry_0:
is_iic_busy = 1;
iic_start();
iic_sendbyte_io(iAP2_REG_ADDR_W);
u8 nack = r_ack();
step1_retry_cnt++;
if(nack && step1_retry_cnt < 10){
delay_us(500);
goto __retry_0;
}
else if(nack){
iAP2_printf("func:%s line:%d failed", __func__, __LINE__);
goto __iic_end;
}
iic_sendbyte_io(reg_addr);
nack = r_ack();
step2_retry_cnt++;
if(nack && step2_retry_cnt < 10){
delay_us(500);
step1_retry_cnt = 0;
goto __retry_0;
}
else if(nack){
iAP2_printf("func:%s line:%d failed", __func__, __LINE__);
goto __iic_end;
}
iic_stop();
step2_retry_cnt = 0;
__retry_1:
iic_start();
iic_sendbyte_io(iAP2_REG_ADDR_R);
nack = r_ack();
step2_retry_cnt++;
if(nack && step2_retry_cnt < 10){
delay_us(500);
goto __retry_1;
}
else if(nack){
iAP2_printf("func:%s line:%d failed", __func__, __LINE__);
goto __iic_end;
}
for (; read_len > 0; read_len--) {
*data++ = iic_revbyte_io(); //读数据
total_len++;
if(read_len > 1){
s_ack(0);
}
else{
s_ack(1);
}
delay_us(33);
}
iic_stop();
is_iic_busy = 0;
iAP2_printf("%s succ", __func__);
return total_len;
__iic_end:
iic_stop();
is_iic_busy = 0;
iAP2_printf("%s fail stop", __func__);
return 0;
}
FAQ
1、708硬件IIC注意点
1、引脚需要和硬件iic引脚对齐,不能够修改引脚
2、提高中断优先级避免出现打断,主要是提高稳定性
3、优化偶尔收不到结束位