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”。