IIC控制器¶
IIC可以在MCU和MCU或者MCU和外设之间进行通信。可以同时连接多个slave设备实现多机并联通信。可以启用DMA功能减小CPU的负担。
【基本特性】¶
IIC控制器的主要特性如下表所示:
- 一共有两个IIC控制器,每一个都可以单独配置
- 可以配置为slave模式,或者master模式。
- 支持100kHz、400kHz、1MHz三种SCL频率。
- 支持DMA读写操作。
- 支持7bit或10bit器件地址。
- 支持0bit、8bit、16bit内存地址读取。
- 自带16Byte发送接收FIFO,可减小CPU负担。
【程序操作】¶
程序操作流程如下图所示:
第一步:实例化IIC。¶
app_iic_inst_t iic0 = IIC_INSTANCE(0);
app_iic_inst_t iic1 = IIC_INSTANCE(1);
如果使用IIC外设,必须首先声明IIC实例,然后才可以对实例进行操作。
其中“IIC_INSTANCE”宏定义可以进行IIC实例的声明,其中的参数为IIC控制器序号,数值为0-2。
如需同时使用多个PWM通道,则需要同时声明多个实例。上述代码声明了2个IIC实例,可以同时输出2路IIC信号。
第二步:配置传输参数。¶
数据结构¶
传输参数结构体定义如下所示:
/**@brief IIC communication structure holding configuration settings for the peripheral.
*/
typedef struct
{
app_iic_address_bit_num_t dev_addr_bit_num; /** device address length. */
app_iic_mem_addr_num_t mem_addr_bit_num; /** memory address length. */
app_iic_work_mode_t work_mode; /** work mode is slave or master. */
app_iic_speed_mode_t speed_mode; /** SCL clock speed switch. */
uint16_t slave_address; /** Slave Address only in SLAVE MODE */
uint8_t sda_pin; /** SDA pin number, range from 2 to 23. */
uint8_t scl_pin; /** SCL pin number, range from 2 to 23. */
uint8_t enable_pull_up; /** if SDA and SCL enable internal pull-up resistor. */
uint8_t use_dma; /** use DMA = 1 , donnot use DMA = 0 */
}app_iic_comm_params_t;
参数含义¶
其中的成员的参数含义以及取值,如下表所示:
参数 | 取值 | 含义 |
---|---|---|
dev_addr_bit_num | IIC_7BIT_ADDRESS | 器件设备地址具有7bit |
IIC_10BIT_ADDRESS | 器件设备地址具有10bit | |
mem_addr_bit_num | IIC_NO_MEMORY_ADDRESS | 没有器件内存地址。即IIC普通对传。 |
IIC_8BIT_MEMORY_ADDRESS | 8bit器件内存地址。即某些传感器的数据在指定地址存放,其地址为8bit | |
IIC_16BIT_MEMORY_ADDRESS | 16bit器件内存地址。即某些传感器的数据在指定地址存放,其地址为16bit | |
work_mode | IIC_SLAVE | 工作模式:系统工作在slave从模式 |
IIC_MASTER | 工作模式:系统工作在master主模式 | |
speed_mode | IIC_STANDARD_MODE | 标准速度:SCL速度100kHz |
IIC_FAST_MODE | 快速模式:SCL速度400kHz | |
IIC_HIGH_SPEED_MODE | 高速模式:SCL速度1000kHz,在此模式下,系统会自动先发送一个总线识别码。不可取消。 | |
slave_address | 0x0000 – 0x3FF | 设备的地址。仅仅作为slave模式下有效。地址不包含最低位的RW位。在master模式下,可以不关心此成员。 |
sda_pin | 2-23 | IIC的SDA脚选择 |
scl_pin | 2-23 | IIC的SCL脚选择 |
enable_pull_up | 0或1 | 0:不启用内部自带的上拉功能,必须外加上拉电阻。 |
1:启用内部自带的上拉功能,可以不用外加上拉电阻。 | ||
use_dma | 0或1 | 含义:是否启用DMA传输。在读取或写入操作时候,系统会根据此参数,来决定是否使用DMA。 |
其中从模式(slave)暂不支持DMA传输。0:不启用DMA传输。1:启用DMA传输。 |
第三步:初始化。¶
设置完参数之后,需要进行初始化操作,让参数生效,并且开启IIC。
函数原型:
void app_iic_init (periph_inst_handle_t hdl);
函数使用:
app_iic_init(&iic0.inst);
初始化的过程,会开启IIC模块,并开启对应的中断系统,以及时钟模块。
第四步:读写操作。¶
读写接口¶
读写操作分为读操作和写操作。
读写操作函数原型如下:
void app_iic_read (periph_inst_handle_t hdl,
uint8_t *bufptr,
uint32_t size,
uint16_t device_address,
uint16_t mem_address ,
void (*callback) (void*,uint8_t),
void* dummy);
void app_iic_write(periph_inst_handle_t hdl,
uint8_t *bufptr,
uint32_t size,
uint16_t device_address,
uint16_t mem_address ,
void (*callback) (void*,uint8_t),
void* dummy);
其中读写的函数比较类似,参数的内容和含义是完全相同的。
读操作和写操作在底层又分为:DMA操作和不带DMA操作。
但是对于用户的接口仍然只有上述的两个函数,用户只需要配置第二步中的use_dma参数,在底层即可自动切换是否启用DMA,而无需用户的额外操作。
参数含义¶
函数的参数含义如下表所示:
参数 | 含义 |
---|---|
hdl | IIC模块实例的句柄,表明了使用哪一个IIC进行操作。 |
bufptr | 需要发送/接收的数据的指针。 |
size | 需要发送/接收的数据的长度。 |
device_address | 目标设备的器件地址。该地址为8bit,包含最低位的RW标志。
例如:参数为0xA0,那么在写操作系统会发送0xA0,读操作系统会发送0xA1
|
mem_address | 要读取的目标设备的的内存地址。该数据会紧接着器件地址之后发送。
如果不需要发送mem_address,那么需要在第二步的mem_addr_bit_num设置为IIC_NO_MEMORY_ADDRESS,
然后本参数可以不做处理。
|
callback | 发送完成的回调函数 |
dummy | 发送完成的回调函数的参数 |
第五步:关闭IIC。¶
在使用完毕IIC的时候,或者更改IIC参数的需要重新运行的时候,需要进行关闭IIC的操作。
函数原型:
void app_iic_uninit (periph_inst_handle_t hdl);
函数使用:
app_iic_uninit(&iic0.inst);
关闭的过程,会关闭IIC模块,并关闭对应的中断系统,以及时钟模块。
【注意事项与说明】¶
关于device_address和mem_address的理解,以AT24C02芯片为例:
(1)device_address说明¶
AT24C02芯片采用A2、A1、A0三个引脚的电平来控制device address。如下图所示:
当A2、A1、A0三个脚均接地,那么该器件的写地址为0xA0,读地址为0xA1。上述函数中的device_address应该填写0xA0。而非0x50。
(2)memory address说明¶
在发送完device_address,会再发送memory address的内容,之后再发送bufptr的内容。
当第二步的mem_addr_bit_num参数不同,发送的内容也不同。
如下表所示
mem_addr_bit_num参数内容 | 发送数据内容
|
---|---|
IIC_NO_MEMORY_ADDRESS | 发送完毕device_address之后,立即发送bufptr的内容
|
IIC_8BIT_MEMORY_ADDRESS | 发送完毕device_address之后,
再发送1字节的memory address,然后再发送bufptr的内容
|
IIC_16BIT_MEMORY_ADDRESS | 发送完毕device_address之后,
再发送2字节的memory address,然后再发送bufptr的内容
|
(3)memory address类型介绍¶
下面以AT24C02和AT24C1024B为实例介绍。
1、8bit的memory address¶
AT24C02芯片对指定地址写入一个字节的操作,如下图所示;
其中图中的WORD ADDRESS就是函数参数中的mem_address。
在发送完成device address之后,紧接着发送一个字节word address,来确定写入EEPROM中的哪一个地址中的数据。后面紧跟着的内容就是需要写入的数据内容。
2、16bit的memory address¶
AT24C1024芯片对指定地址写入一个字节的操作,如下图所示;
其中图中的WORD ADDRESS就是函数参数中的mem_address。由于AT24C1024的内存比较大,需要更大的寻址空间,所以需要2字节的内存地址。
在发送完成device address之后,紧接着发送两个字节的word address,来确定写入EEPROM中的哪一个地址中的数据。后面紧跟着的内容就是需要写入的数据内容。
3、no memory address¶
如果对IIC进行操作的对象,不是存储芯片或者传感器,就没有上述的memory address。可以选择mem_addr_bit_num参数为IIC_NO_MEMORY_ADDRESS。这样在发送的时候,就不会发送memory address这部分的内容。
(4)收发数据注意事项¶
- bufptr所指向的内存,务必要预留足够大的空间,用来存放发送、接受的数据内容。
- 如果使用DMA发送或接受,如果参数size的长度超过32,需要在“app_iic.h”中的宏定义中,增大APP_IIC_DMA_TXRX_BUFFER参值至少为size的大小。
#define APP_IIC_DMA_TXRX_BUFFER 32
【样例程序】¶
参考“app_iic_test.c”
主模式测试¶
程序与流程¶
void app_iic_master_test(void)
uint8_t app_iic_eeprom_test(app_iic_inst_t *handle ,
uint8_t use_dma ,
uint8_t speed_mode)
app_iic_eeprom_test函数为EEPROM测试读写函数。该函数内部流程如下图所示:
参数含义¶
其参数含义如下表所示:
参数 | 含义
|
---|---|
app_iic_inst_t *handle | 选择使用哪一个IIC实例进行操作。
|
uint8_t use_dma | 选择是否启用DMA操作
0:不启用DMA
1:启用DMA
|
uint8_t speed_mode | 选择速度模式。
1:低速模式(100kHz),同IIC_STANDARD_MODE
2:全速模式(400kHz),同IIC_FAST_MODE
3:高速模式(1MHz),同IIC_HIGH_SPEED_MODE
|
其中app_iic_master_test函数会循环调用app_iic_eeprom_test函数。每一次调用的时候,会分别启用不同的速度模式,以及不同的DMA模式。并且会分别选择使用IIC0还是IIC1进行测试。
从模式测试¶
程序与流程¶
void app_iic_slave_test(void)
uint32_t app_iic_slave_module_test(app_iic_inst_t *hdl_master ,
app_iic_inst_t *hdl_slave ,
uint8_t speed_mode)
其中app_iic_slave_module_test函数为IIC0和IIC1,一个作为主模式,一个作为从模式,两者相互对传的测试读写函数。该函数内部流程如下图所示:
参数含义¶
其参数含义如下表所示:
参数 | 含义
|
---|---|
app_iic_inst_t *hdl_master | 主设备的实例的句柄
|
app_iic_inst_t *hdl_master | 从设备的实例的句柄
|
uint8_t speed_mode | 选择速度模式。
1:低速模式(100kHz),同IIC_STANDARD_MODE
2:全速模式(400kHz),同IIC_FAST_MODE
3:高速模式(1MHz),同IIC_HIGH_SPEED_MODE
|
其中app_iic_slave_test函数会循环调用app_iic_slave_module_test函数。每一次调用的时候,会分别启用不同的速度模式。并且会分别选择使用IIC0作为slave还是IIC1作为slave进行测试。