打印
[牛人杂谈]

I2C的配置

[复制链接]
1385|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
I2c, AC, ck, ip
I2C相信大家都不陌生,很多人都用GPIO模拟过I2C。但是模拟的太占CPU资源,并且一般只能模拟Master,模拟slave还是挺困难的。
下面介绍一下I2C IP。
这个是I2CON寄存器,I2C的控制寄存器

从左往右依次为:中断使能位,状态变化指示位,发送START信号,发送STOP信号,回ACK,使能I2C IP
 I2C_STS:I2C的状态发生变化该位就会置1
 START:请求I2C IP 发送START信号。一旦发送成功,该I2C就作为I2C Master
 STOP:请求I2C IP 发送STOP信号
 ACK:如果收到数据的时候该位为1,I2C IP将回ACK给对方,否则回NACK
其实从I2C的波形就可以看出,I2C协议完全是状态驱动的,从START信号开始,发送/接收地址字节之后收到ACK/NACK状态,发送/接收数据之后收到ACK/NACK状态,发送STOP

这个就是状态寄存器,状态一旦发生改变,就会发生I2C中断,然后读该寄存器就知道发生了何事。

沙发
huangcunxiake|  楼主 | 2018-11-21 23:36 | 只看该作者
下图就是I2C作为Master和Slave时各个状态的含义表格:


0xF8是总线空闲的状态值,也是STATUS寄存器的缺省值。
下面详细介绍一下上表的各个状态。
Master状态介绍:
1) 发送START信号成功,发生I2C中断,STATUS寄存器的值=0x08
2) 作为I2C Master没有发送STOP又发送START信号成功,发生I2C中断,STATUS寄存器的值=0x10
3) 发送地址+W成功并收到ACK,发生I2C中断,STATUS寄存器的值=0x18
4) 发送地址+W成功并收到NACK,发生I2C中断,STATUS寄存器的值=0x20

5) 发送数据成功并收到ACK,发生I2C中断,STATUS寄存器的值=0x28
6) 发送数据成功并收到NACK,发生I2C中断,STATUS寄存器的值=0x30
7) Master发生仲裁失败,发生I2C中断,STATUS寄存器的值=0x38
8) 发送地址+R成功并收到ACK,发生I2C中断,STATUS寄存器的值=0x40
9) 发送地址+R成功并收到NACK,发生I2C中断,STATUS寄存器的值=0x48
10) 收到数据并返回ACK,发生I2C中断,STATUS寄存器的值=0x50
11) 收到数据并返回NACK,发生I2C中断,STATUS寄存器的值=0x58
12) 总线错误,发生I2C中断,STATUS寄存器的值=0x00

Slave状态介绍:
1) 收到RE-START信号或者STOP信号,发生I2C中断,STATUS寄存器的值=0xA0
2) 收到SLA+R信号并返回ACK,发生I2C中断,STATUS寄存器的值=0xA8
3) 作为Master仲裁失败HW会自动转为Slave,之后收到SLA+R信号,发生I2C中断,STATUS寄存器的值=0xB0
4) 发送数据并收到ACK,发生I2C中断,STATUS寄存器的值=0xB8
5) 发送数据并收到NACK,发生I2C中断,STATUS寄存器的值=0xC0
6) 从接发送最后一个数据,但是居然收到的是ACK,发生I2C中断,STATUS寄存器的值=0xC8
7) 从接收到SLA+W并返回ACK,发生I2C中断,STATUS寄存器的值=0x60
8) 作为Master仲裁失败HW会自动转为Slave,之后收到SLA+W信号,发生I2C中断,STATUS寄存器的值=0x68
9) 收到数据并返回ACK,发生I2C中断,STATUS寄存器的值=0x80
10) 收到数据并返回NACK,发生I2C中断,STATUS寄存器的值=0x88
11) 广播模式收到SLA+W并返回ACK,发生I2C中断,STATUS寄存器的值=0x70
12) 广播模式仲裁失败,发生I2C中断,STATUS寄存器的值=0x78
13) 广播模式收到数据并返回ACK,发生I2C中断,STATUS寄存器的值=0x90


使用特权

评论回复
板凳
huangcunxiake|  楼主 | 2018-11-21 23:42 | 只看该作者
知道所有的状态之后,配置好I2C,然后在中断里面查看STATUS寄存器,处理状态就可以了。超时中断是用户设定时间内没有发生状态改变,就会发生超时中断,这个可以防止软件被hold住。
下面是一个读/写EEPROM的例子。照样是先选择用到的IP的时钟源,使能各个IP的时钟,然后配置多功能引脚,然后是I2C IP功能初始化。另外是I2C 的中断处理函数。中断处理函数中根据STATUS寄存器的值,进行状态处理。只要调用函数I2C_SET_CONTROL_REG(I2C0, I2C_SI);清除状态改变标志,I2C IP就会自动开始下一个状态。
void I2C0_IRQHandler(void)












return 0;
}

使用特权

评论回复
地板
huangcunxiake|  楼主 | 2018-11-21 23:43 | 只看该作者
总结上面I2C_MasterRx的流程为:
1) I2C_SET_CONTROL_REG(I2C0, I2C_STA); 发送START信号,之后该I2C IP就作为Master
2) 发生I2C中断,STATUS=0x08,表示START信号发送成功,然后软件写I2CDAT寄存器,发送I2C地址+W给EEPROM
3) 发生I2C中断,STATUS=0x18,表示SLA+W发送成功并收到ACK,然后发送高位地址给EEPROM
4) 发生I2C中断,STATUS=0x28,表示高位地址发送成功并收到ACK,然后发送低位地址给EEPROM
5) 发生I2C中断,STATUS=0x28,表示低位地址发送成功并收到ACK,然后再次发送START信号——Repeat START
6) 发生I2C中断,STATUS=0x10,表示Repeat START发送成功,然后发送I2C地址+R给EEPROM
7) 发生I2C中断,STATUS=0x40,表示SLA+R发送成功,并收到ACK,然后不设ACK bit,将回NACK给EEPROM
8) 发生I2C中断,STATUS=0x58,收到EEPROM返回的数据并回NACK给EEPROM
把这个流程对应I2C_MasterRx函数仔细看一下,相信不难懂。
发送的流程也类似,在此就不再赘述。

使用特权

评论回复
5
huangcunxiake|  楼主 | 2018-11-21 23:43 | 只看该作者
其实搞通信接口操作,最难的就是配置了,学会配置初始化,其他用的时候就很简单了。

使用特权

评论回复
6
huangcunxiake|  楼主 | 2018-11-21 23:43 | 只看该作者
其实搞通信接口操作,最难的就是配置了,学会配置初始化,其他用的时候就很简单了。

使用特权

评论回复
7
heisexingqisi| | 2018-11-22 00:12 | 只看该作者
一段数据只有一个开始和结尾吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

189

主题

3407

帖子

9

粉丝