I2C(IIC)
外设特性
SPV1x有1个IIC模块。该IIC模块支持以下功能特性:
支持Master/Slave模式。
支持7bit Slave地址。
通信速率最高支持800K。
支持总线40ns毛刺滤波。
支持长时间总线保持功能。
外设使用
1. 使用IIC前的配置
IIC使用前,需要配置工作时钟,并解除模块的复位状态。
在CMU_I2CnCLK中选择IIC的时钟源
配置CMU_CLKEN0.I2C0,使能IIC的时钟。
配置RMU_RSTEN0.I2C0,解除IIC的复位状态。
初始化IIC需要用到的GPIO引脚。
2. IIC主机功能配置
配置IIC_CFG.IIC_EN位,使能IIC模块。
配置IIC_CFG.MODE位,选择Master功能。
配置IIC_CFG.DIV_COR字段,设置IIC的SCK频率。DIV_COR的合理范围为1~255,同时,还需要确保分频后的频率不超过800K。
如果需要使用中断,则配置IIC_IE中的中断使能位。
发送起始信号和从机地址。向IIC_CTL.CMD写入START_CMD,同时向IIC_CTL.TX_DAT写入从机设备地址(7bit地址+写标志位)。IIC硬件会自动开始相应的总线操作,操作完成后,IIC_PD.START_DET和IIC_PD.BYTE_END会置位,软件还需要检查IIC_PD.NACK_DET是否置位,以确定从机是否正确收到设备地址,并回复ACK。
发送寄存器地址。向IIC_CTL.CMD写入RELEASE_BUS,同时向IIC_CTL.TX_DAT写入寄存器地址,IIC硬件会自动开始相应的总线操作,操作完成后,IIC_PD.BYTE_END会置位,软件需要检查IIC_PD.NACK_DET是否置位,以确定从机是否正确收到寄存器地址,并回复ACK。
如果是需要写数据,则在完成步骤(5)之后,向IIC_CTL.CMD写入RELEASE_BUS,同时向IIC_CTL.TX_DAT写入要发送的数据。IIC硬件会自动开始相应的总线操作,操作完成后, IIC_PD.BYTE_END会置位,软件还需要检查IIC_PD.NACK_DET是否置位,以确定从机是否正确收到数据,并回复ACK。重复此步骤,直至所有数据发送完成。最后,执行步骤(9),发送停止位,结束本次通信。
如果是需要读数据,则在完成步骤(5)之后,向IIC_CTL.CMD写入RESTART_CMD,同时向IIC_CTL.TX_DAT写入从机设备地址(7bit地址+读标志位)。IIC硬件会自动开始相应的总线操作,操作完成后,IIC_PD.START_DET和IIC_PD.BYTE_END会置位,软件还需要检查IIC_PD.NACK_DET是否置位,以确定从机是否正确收到设备地址,并回复ACK。
执行完步骤(7)后,向IIC_CTL.CMD写入RELEASE_BUS,同时写IIC_CTL.TX_ACK()。IIC硬件会自动开始相应的总线操作,操作完成后,IIC_PD.BYTE_END会置位。重复此步骤,直至所有数据发送完成。最后,执行步骤(9),发送停止位,结束本次通信。
发送停止位。向IIC_CTL.CMD写入STOP_CMD。IIC硬件会自动开始相应的总线操作,操作完成后,IIC_PD.STOP_DET会置位。
3. IIC从机功能配置
配置IIC_CFG.IIC_EN位,使能IIC模块。
配置IIC_CFG.MODE位,选择Slave功能。
配置IIC_CFG.DIV_COR字段。主机SCL时钟频率越高,IIC_CFG.DIV_COR配置值越小,建议范围8~120。
配置IIC_CFG.SLV_ADD字段,设置从机地址。
如果需要使用中断,则配置IIC_IE中响应的中断使能位。
响应主机寻址操作。当IIC从机收到主机的起始信号(或重复起始信号)和正确的从机地址后,IIC_PD.START_DET和IIC_PD.BYTE_END会置位。同时,IIC模块会将主机寻址时发送的读写标志位保存在IIC_STA.RW_FLAG中,软件需要根据此标志位的状态,做好接收数据或者发送数据的准备。
响应主机的写寄存器地址/写数据操作。如果步骤(6)中收到正确的从机地址后,IIC_STA.RW_FLAG的状态为0,那么接下来,主机将下发数据。主机每发送1字节数据,IIC_PD.BYTE_END会置位一次,软件在检测到IIC_PD.BYTE_END置位后,将数据从IIC_RX_DAT读走。
响应主机的读数据操作。如果步骤(6)中收到正确的从机地址后,IIC_STA.RW_FLAG的状态为1,那么接下来,主机将读取数据。第1个数据需要在寻址后就写入IIC_CTL.TX_DAT,后续的数据在IIC_PD.BYTE_END置位后写入IIC_CTL.TX_DAT。如果在IIC_PD.BYTE_END置位后,检测到IIC_PD.NACK_DET也置位,则表示主机已完成数据读取,此时软件不需要再向IIC_CTL.TX_DAT写入有效数据。
响应主机的停止信号。当IIC从机收到停止信号后,IIC_PD.STOP_DET会置位,此时表示本次通信结束。
注意事项
IIC有固定的协议要求,需要严格按规定的协议来操作IIC模块,否则会出现通信失败的情况。尤其是作为从机时,软件需要记录和判断从机当前所处的状态,同时还需要以较快的速度配合IIC模块,保证正确且快速地响应主机的各种操作。
IIC作为主机时,如果IIC总线出现硬件异常(如SCL或SDA信号线出现短路,无法驱动和产生所需时序),IIC_PD.START_DET和IIC_PD.STOP_DET可能不会置位。如果软件使用查询的方式等待这些Pending位,最好加入超时机制,以避免程序陷入死循环。出现此类错误后,需要复位IIC模块,以重置IIC硬件状态机。
IIC_PD寄存器中的Pending位,需要软件清除。在开始下一个步骤的操作前,软件需要主动清除对应的Pending位,避免上一个步骤的Pending位结果影响到下一个步骤的判断。
IIC作为从机时,如果主机发送的从机地址与设置的IIC_CFG.SLV_ADD不匹配,IIC模块不会起任何Pending。
IIC作为从机时,每次主机寻址操作、主机写数据操作和主机读数据操作后,从机都会进行总线保持操作(从机拉低SCL信号线),软件需要向IIC_CTL.CMD写入RELEASE_BUS,来释放SCL信号线,如果从机需要向主机发送有效数据,还需要同时向IIC_CTL.TX_DAT写入有效数据。
IIC作为从机时,软件需要根据IIC协议的规则,来记录和判断从机当前所处的状态,同时软件还需要以较快的速度配合IIC模块,保证正确且快速地响应主机的各种操作。
API说明
IIC API提供基础的IIC主机功能。
-
void iic_init(uint32_t baud)
IIC初始化。
- 参数
baud – IIC波特率(IIC SCL信号的频率)。
- 返回
无
-
void iic_deinit(void)
IIC去初始化。
- 返回
无
-
int32_t iic_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *buf, uint32_t len)
IIC读取数据。
- 参数
dev_addr – 7bit器件地址。
reg_addr – 器件寄存器地址。
buf – 指向容纳读取数据的缓冲区。
len – 读取的数据长度。
- 返回
0表示成功,其他值表示出错
- 返回类型
int32_t
-
int32_t iic_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *buf, uint32_t len)
IIC写数据。
- 参数
dev_addr – 7bit器件地址。
reg_addr – 器件寄存器地址。
buf – 指向要写入的数据。
len – 写入的数据长度。
- 返回
0表示成功,其他值表示出错
- 返回类型
int32_t
API使用示例
在 board.h 中设置 __USE_IIC_PIN_CFG 为1,表示需要启用IIC引脚配置。
#define __USE_IIC_PIN_CFG (1)
在 board.h 中设置并定义对应IIC需要用到的引脚以及引脚对应的MFP值。
#define IIC_SDA_PIN (GPIO_Pin_23) #define IIC_SDA_MFP (5) #define IIC_SCL_PIN (GPIO_Pin_24) #define IIC_SCL_MFP (5)备注
如果 __USE_IIC_PIN_CFG 为0,则需要用户手动配置IIC引脚。
IIC引脚上需要外接上拉电阻(通常为4.7K),以保证通讯稳定。
调用 iic_init() 初始化IIC模块。
该函数会初始化IIC用到的引脚(如果 __USE_IIC_PIN_CFG 为1),选择OSC_DEV时钟作为IIC的时钟。
iic_init(400000);
调用 iic_write() 发送数据。
阻塞式发送数据,直到所有数据发送完成或者出错。
iic_write(0x56, 0x10, buf, 10);备注
IIC写操作需要检查函数的返回值,确认操作成功。读操作同样如此。
调用 iic_read() 读取数据。
阻塞式读取数据,直到所有数据读取完成或者出错。
iic_read(0x56, 0x10, buf, 10);
如果不需要再使用IIC,调用 iic_deinit() 去初始化。
去初始化会关闭IIC的时钟,并让模块处于复位状态。相应的引脚复用也会被清除(如果 __USE_IIC_PIN_CFG 为1)。
寄存器定义