I2C - eeprom_interrupt
本 demo 主要介绍 I2C 使用中断的方式读写 eeprom。
硬件连接
本 demo 使用到的 gpio 参考 board_i2c0_gpio_init
,将 eeprom 模块与开发板连接,具体引脚连接方式如下表(以BL616为例):
开发板 I2C 引脚 |
eeprom 模块 |
---|---|
SCL(GPIO14) |
SCL |
SDA(GPIO15) |
SDA |
GND |
GND |
VCC |
VCC |
软件实现
更详细的代码请参考 examples/peripherals/i2c/i2c_eeprom_interrupt
1board_init();
board_init
中会开启 I2C IP 时钟,并选择 I2C 时钟源和分频。
1board_i2c0_gpio_init();
配置相关引脚为 I2C 功能
1i2c0 = bflb_device_get_by_name("i2c0");
2
3bflb_i2c_init(i2c0, 400000);
获取 i2c0 句柄,并初始化 i2c0 频率为 400K
1/* Set i2c interrupt */
2bflb_i2c_int_mask(i2c0, I2C_INTEN_END | I2C_INTEN_TX_FIFO | I2C_INTEN_RX_FIFO | I2C_INTEN_NACK | I2C_INTEN_ARB | I2C_INTEN_FER, false);
3bflb_irq_attach(i2c0->irq_num, i2c_isr, NULL);
4bflb_irq_enable(i2c0->irq_num);
调用
bflb_i2c_int_mask(i2c0, I2C_INTEN_END | I2C_INTEN_TX_FIFO | I2C_INTEN_RX_FIFO | I2C_INTEN_NACK | I2C_INTEN_ARB | I2C_INTEN_FER, false)
打开 I2C 中断注册 I2C 中断
1uint8_t write_data[256];
2uint8_t read_data[256];
3
4/* Write and read buffer init */
5for (size_t i = 0; i < 256; i++) {
6 write_data[i] = i;
7 read_data[i] = 0;
8}
初始化发送和接收 buffer
1/* Write page 0 */
2subaddr[1] = EEPROM_SELECT_PAGE0;
3
4msgs[0].addr = 0x50;
5msgs[0].flags = I2C_M_NOSTOP;
6msgs[0].buffer = subaddr;
7msgs[0].length = 2;
8
9msgs[1].addr = 0x50;
10msgs[1].flags = 0;
11msgs[1].buffer = write_data;
12msgs[1].length = EEPROM_TRANSFER_LENGTH;
13
14bflb_i2c_transfer(i2c0, msgs, 2);
15if (txFifoFlag) {
16 printf("TX FIFO Ready interrupt generated\r\n");
17 txFifoFlag = 0;
18}
19if (rxFifoFlag) {
20 printf("RX FIFO Ready interrupt generated\r\n");
21 rxFifoFlag = 0;
22}
23printf("write over\r\n\r\n");
24bflb_mtimer_delay_ms(100);
bflb_i2c_transfer(i2c0, msgs, 2)
开启 i2c 传输
1/* Unmask interrupt */
2bflb_i2c_int_mask(i2c0, I2C_INTEN_END | I2C_INTEN_TX_FIFO | I2C_INTEN_RX_FIFO | I2C_INTEN_NACK | I2C_INTEN_ARB | I2C_INTEN_FER, false);
3
4/* Write page 1 */
5subaddr[1] = EEPROM_SELECT_PAGE1;
6
7msgs[1].addr = 0x50;
8msgs[1].flags = 0;
9msgs[1].buffer = write_data + EEPROM_TRANSFER_LENGTH;
10msgs[1].length = EEPROM_TRANSFER_LENGTH;
11
12bflb_i2c_transfer(i2c0, msgs, 2);
13if (txFifoFlag) {
14 printf("TX FIFO Ready interrupt generated\r\n");
15 txFifoFlag = 0;
16}
17if (rxFifoFlag) {
18 printf("RX FIFO Ready interrupt generated\r\n");
19 rxFifoFlag = 0;
20}
21printf("write over\r\n\r\n");
22bflb_mtimer_delay_ms(100);
开启 I2C 中断,进行第二次数据传输
1/* Unmask interrupt */
2bflb_i2c_int_mask(i2c0, I2C_INTEN_END | I2C_INTEN_TX_FIFO | I2C_INTEN_RX_FIFO | I2C_INTEN_NACK | I2C_INTEN_ARB | I2C_INTEN_FER, false);
3
4/* Read page 0 */
5subaddr[1] = EEPROM_SELECT_PAGE0;
6
7msgs[1].addr = 0x50;
8msgs[1].flags = I2C_M_READ;
9msgs[1].buffer = read_data;
10msgs[1].length = EEPROM_TRANSFER_LENGTH;
11bflb_i2c_transfer(i2c0, msgs, 2);
12if (txFifoFlag) {
13 printf("TX FIFO Ready interrupt generated\r\n");
14 txFifoFlag = 0;
15}
16if (rxFifoFlag) {
17 printf("RX FIFO Ready interrupt generated\r\n");
18 rxFifoFlag = 0;
19}
20printf("read over\r\n\r\n");
读取 eeprom 的数据
1/* Unmask interrupt */
2bflb_i2c_int_mask(i2c0, I2C_INTEN_END | I2C_INTEN_TX_FIFO | I2C_INTEN_RX_FIFO | I2C_INTEN_NACK | I2C_INTEN_ARB | I2C_INTEN_FER, false);
3
4/* Read page 1 */
5subaddr[1] = EEPROM_SELECT_PAGE1;
6
7msgs[1].addr = 0x50;
8msgs[1].flags = I2C_M_READ;
9msgs[1].buffer = read_data + EEPROM_TRANSFER_LENGTH;
10msgs[1].length = EEPROM_TRANSFER_LENGTH;
11bflb_i2c_transfer(i2c0, msgs, 2);
12if (txFifoFlag) {
13 printf("TX FIFO Ready interrupt generated\r\n");
14 txFifoFlag = 0;
15}
16if (rxFifoFlag) {
17 printf("RX FIFO Ready interrupt generated\r\n");
18 rxFifoFlag = 0;
19}
第二次读取数据
1/* Check read data */
2for (uint8_t i = 0; i < 2 * EEPROM_TRANSFER_LENGTH; i++) {
3 if (write_data[i] != read_data[i]) {
4 printf("check fail, %d write: %02x, read: %02x\r\n", i, write_data[i], read_data[i]);
5 }
6}
检查发送和读取的数据是否一致
编译和烧录
参考 环境搭建
实验现象
按下 RST 按键,数据传输完成后,打印“write over”,“read over”和“check over”。