[APM32E0] APM32E030的IIC驱动(硬件)

[复制链接]
166|1
口天土立口 发表于 2025-9-6 14:39 | 显示全部楼层 |阅读模式
本帖最后由 口天土立口 于 2025-9-6 14:56 编辑

7721868bbd6208941c.png

843368bbd63360d02.png
APM32E030支持I2C功能。

本次代码基于开发板:APM32E030R Micro-EVB
IO:SCL->PB6,SDA->PB7

I2C初始化代码如下:
  1. /* 初始化IIC引脚 */
  2. static void bsp_iic_gpio_init(void)
  3. {
  4.     GPIO_Config_T gpioConfig;
  5.    
  6.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);
  7.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);   
  8.     GPIO_ConfigStructInit(&gpioConfig);
  9.    
  10.     /*
  11.      * SCL -> PB6
  12.      * SDA -> PB7
  13.      */
  14.     GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_6, GPIO_AF_PIN1);
  15.     GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_7, GPIO_AF_PIN1);
  16.    
  17.     gpioConfig.pin     = GPIO_PIN_6;
  18.     gpioConfig.mode    = GPIO_MODE_AF;
  19.     gpioConfig.outtype = GPIO_OUT_TYPE_OD;
  20.     gpioConfig.speed   = GPIO_SPEED_50MHz;
  21.     gpioConfig.pupd    = GPIO_PUPD_NO;
  22.     GPIO_Config(GPIOB, &gpioConfig);
  23.     gpioConfig.pin     = GPIO_PIN_7;
  24.     GPIO_Config(GPIOB, &gpioConfig);
  25. }
  1. /* 初始化IIC */
  2. void bsp_iic_init(void)
  3. {
  4.     I2C_Config_T i2cConfig;
  5.    
  6.     RCM_ConfigI2CCLK(RCM_I2C1CLK_SYSCLK);
  7.     RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);   
  8.     bsp_iic_gpio_init();   
  9.    
  10.     I2C_Reset(I2C1);
  11.     I2C_ConfigStructInit(&i2cConfig);
  12.     i2cConfig.timing   = 0x80220707; /* 400KHz */
  13.     i2cConfig.address1 = 0xA0;
  14.     i2cConfig.mode     = I2C_MODE_I2C;
  15.     i2cConfig.analogfilter  = I2C_ANALOG_FILTER_ENABLE;
  16.     i2cConfig.digitalfilter = I2C_DIGITAL_FILTER_0;
  17.     i2cConfig.ack = I2C_ACK_ENABLE;
  18.     i2cConfig.ackaddress = I2C_ACK_ADDRESS_7BIT;
  19.     I2C_Config(I2C1, &i2cConfig);
  20.     I2C_Enable(I2C1);
  21.    
  22.     GPIO_SetBit(GPIOB, GPIO_PIN_8);
  23.     GPIO_SetBit(GPIOB, GPIO_PIN_9);
  24. }


EEPROM驱动代码如下:
  1. /* 最大容量 1KB */
  2. #define AT24C08_MAX_CAPACITY        ((uint32_t)0x400)
  3. /* 单页大小 */
  4. #define AT24C08_PAGE_SIZE           ((uint8_t)16)
  5. /* 设备地址 */
  6. #define AT24C08_DEV_ADDR            ((uint8_t)0xA0)
  7. /* 超时 */
  8. #define I2CT_TIMEOUT                ((uint32_t)0xFF000)
  1. /*
  2. * @brief       延时
  3. *
  4. * @param       None
  5. *
  6. * @retval      None
  7. *
  8. */
  9. static void bsp_delay(void)
  10. {
  11.     volatile uint32_t ms = 0x3FFF;  /* 2.5ms */
  12.     while (--ms);
  13. }
  1. /*
  2. * @brief       写数据
  3. *
  4. * @param       addr: 存储地址
  5. *              buf: 数据缓存
  6. *              size: 数据大小
  7. *
  8. * @retval      None
  9. *
  10. */
  11. uint16_t bsp_at24c08_write(uint16_t addr, uint8_t *buf, uint16_t size)
  12. {
  13.     uint16_t write_bytes = 0;
  14.     uint32_t iic_timeout = I2CT_TIMEOUT;
  15.     uint8_t dev_addr = AT24C08_DEV_ADDR;    /* 设备地址 */
  16.     uint8_t mem_addr = addr;                /* 存储地址 */
  17.     uint16_t write_index = 0;
  18.     uint8_t current_page_write_size = 0;    /* 当前页写大小 */
  19.    
  20.     /* 入参检查 */
  21.     if ((addr >= AT24C08_MAX_CAPACITY) || (size == 0) || ((addr + size) > AT24C08_MAX_CAPACITY)) {
  22.         return write_bytes;
  23.     }
  24.    
  25.     do {
  26.         /* 计算地址 */
  27.         dev_addr = AT24C08_DEV_ADDR + (((addr / AT24C08_PAGE_SIZE) >> 4) << 1);
  28.         mem_addr = (addr % AT24C08_PAGE_SIZE) + (((addr / AT24C08_PAGE_SIZE) & 0x0F) << 4);
  29.         current_page_write_size = AT24C08_PAGE_SIZE - (addr % AT24C08_PAGE_SIZE);
  30.         current_page_write_size = (current_page_write_size <= (size - write_bytes)) ? current_page_write_size : (size - write_bytes);
  31.         write_index = 0;
  32.         
  33.         /* 等待IIC空闲 */
  34.         iic_timeout = I2CT_TIMEOUT;
  35.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSY) == SET) {
  36.             if ((iic_timeout--) == 0) {
  37.                 I2C_EnableGenerateStop(I2C1);
  38.                 return write_bytes;
  39.             }
  40.         }
  41.         
  42.         /* 发送起始位和设备地址 */
  43.         I2C_HandlingTransfer(I2C1, dev_addr, 1, I2C_RELOAD_MODE_RELOAD, I2C_GENERATE_START_WRITE);
  44.         iic_timeout = I2CT_TIMEOUT;
  45.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET) {
  46.             if ((iic_timeout--) == 0) {
  47.                 I2C_EnableGenerateStop(I2C1);
  48.                 return write_bytes;
  49.             }
  50.         }
  51.         
  52.         /* 发送存储地址 */
  53.         I2C_TxData(I2C1, mem_addr);
  54.         iic_timeout = I2CT_TIMEOUT;
  55.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TCRF) == RESET) {
  56.             if ((iic_timeout--) == 0) {
  57.                 I2C_EnableGenerateStop(I2C1);
  58.                 return write_bytes;
  59.             }
  60.         }
  61.         
  62.         /* 配置写入的数据数量 */
  63.         I2C_HandlingTransfer(I2C1, dev_addr, current_page_write_size, I2C_RELOAD_MODE_AUTOEND, I2C_GENERATE_NO_STARTSTOP);
  64.         I2C_ClearStatusFlag(I2C1, I2C_FLAG_TCRF);
  65.         iic_timeout = I2CT_TIMEOUT;
  66.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET) {
  67.             if ((iic_timeout--) == 0) {
  68.                 I2C_EnableGenerateStop(I2C1);
  69.                 return write_bytes;
  70.             }
  71.         }
  72.         
  73.         /* 写数据 */
  74.         while (write_index++ < current_page_write_size) {
  75.             I2C_TxData(I2C1, buf[write_bytes]);
  76.             iic_timeout = I2CT_TIMEOUT;
  77.             while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET) {
  78.                 if ((iic_timeout--) == 0) {
  79.                     I2C_EnableGenerateStop(I2C1);
  80.                     return write_bytes;
  81.                 }
  82.             }
  83.             write_bytes++;
  84.         }
  85.         
  86.         /* 等待结束 */
  87.         iic_timeout = I2CT_TIMEOUT;
  88.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_STOP) == RESET) {
  89.             if ((iic_timeout--) == 0) {
  90.                 I2C_EnableGenerateStop(I2C1);
  91.                 return write_bytes;
  92.             }
  93.         }
  94.         I2C_ClearStatusFlag(I2C1, I2C_FLAG_STOP);
  95.         addr += current_page_write_size;
  96.         bsp_delay();    /* 等待存储完成,否则异常 */
  97.     } while (write_bytes < size);
  98.    
  99.     return write_bytes;
  100. }
  1. /*
  2. * @brief       读数据
  3. *
  4. * @param       addr: 存储地址
  5. *              buf: 数据缓存
  6. *              size: 数据大小
  7. *
  8. * @retval      None
  9. *
  10. */
  11. uint16_t bsp_at24c08_read(uint16_t addr, uint8_t *buf, uint16_t size)
  12. {
  13.     uint16_t read_bytes = 0;
  14.     uint32_t iic_timeout = I2CT_TIMEOUT;
  15.     uint8_t dev_addr = AT24C08_DEV_ADDR;    /* 设备地址 */
  16.     uint8_t mem_addr = addr;                /* 存储地址 */
  17.     uint16_t read_index = 0;
  18.     uint16_t current_page_read_size = 0;    /* 当前页读大小 */
  19.    
  20.     /* 入参检查 */
  21.     if ((addr >= AT24C08_MAX_CAPACITY) || (size == 0) || ((addr + size) > AT24C08_MAX_CAPACITY)) {
  22.         return read_bytes;
  23.     }
  24.    
  25.     do {
  26.         /* 计算地址 */
  27.         dev_addr = AT24C08_DEV_ADDR + (((addr / AT24C08_PAGE_SIZE) >> 4) << 1);
  28.         mem_addr = (addr % AT24C08_PAGE_SIZE) + (((addr / AT24C08_PAGE_SIZE) & 0x0F) << 4);
  29.         current_page_read_size = AT24C08_PAGE_SIZE - (addr % AT24C08_PAGE_SIZE);
  30.         current_page_read_size = 255;   /* 寄存器只有8bit,限制单次最多255个字节 */
  31.         current_page_read_size = (current_page_read_size <= (size - read_bytes)) ? current_page_read_size : (size - read_bytes);
  32.         read_index = 0;
  33.         
  34.         /* 等待IIC空闲 */
  35.         iic_timeout = I2CT_TIMEOUT;
  36.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSY) == SET) {
  37.             if ((iic_timeout--) == 0) {
  38.                 I2C_EnableGenerateStop(I2C1);
  39.                 return read_bytes;
  40.             }
  41.         }
  42.         
  43.         /* 发送起始位和写设备地址 */
  44.         I2C_HandlingTransfer(I2C1, dev_addr, 1, I2C_RELOAD_MODE_AUTOEND, I2C_GENERATE_START_WRITE);
  45.         iic_timeout = I2CT_TIMEOUT;
  46.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET) {
  47.             if ((iic_timeout--) == 0) {
  48.                 I2C_EnableGenerateStop(I2C1);
  49.                 return read_bytes;
  50.             }
  51.         }
  52.         
  53.         /* 发送地址 */
  54.         I2C_TxData(I2C1, mem_addr);
  55.         iic_timeout = I2CT_TIMEOUT;
  56.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET) {
  57.             if ((iic_timeout--) == 0) {
  58.                 I2C_EnableGenerateStop(I2C1);
  59.                 return read_bytes;
  60.             }
  61.         }
  62.         
  63.         /* 等待结束 */
  64.         iic_timeout = I2CT_TIMEOUT;
  65.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_STOP) == RESET) {
  66.             if ((iic_timeout--) == 0) {
  67.                 I2C_EnableGenerateStop(I2C1);
  68.                 return read_bytes;
  69.             }
  70.         }
  71.         I2C_ClearStatusFlag(I2C1, I2C_FLAG_STOP);
  72.         
  73.         /* 发送起始位和读设备地址 */
  74.         I2C_HandlingTransfer(I2C1, dev_addr, current_page_read_size, I2C_RELOAD_MODE_AUTOEND, I2C_GENERATE_START_READ);
  75.         iic_timeout = I2CT_TIMEOUT;
  76.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET) {
  77.             if ((iic_timeout--) == 0) {
  78.                 I2C_EnableGenerateStop(I2C1);
  79.                 return read_bytes;
  80.             }
  81.         }
  82.         
  83.         /* 读数据 */
  84.         while (read_index++ < current_page_read_size) {
  85.             iic_timeout = I2CT_TIMEOUT;
  86.             while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_RXBNE) == RESET) {
  87.                 if ((iic_timeout--) == 0) {
  88.                     I2C_EnableGenerateStop(I2C1);
  89.                     return read_bytes;
  90.                 }
  91.             }
  92.             buf[read_bytes++] = I2C_RxData(I2C1);
  93.         }
  94.         
  95.         /* 等待结束 */
  96.         iic_timeout = I2CT_TIMEOUT;
  97.         while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_STOP) == RESET) {
  98.             if ((iic_timeout--) == 0) {
  99.                 I2C_EnableGenerateStop(I2C1);
  100.                 return read_bytes;
  101.             }
  102.         }
  103.         I2C_ClearStatusFlag(I2C1, I2C_FLAG_STOP);
  104.         addr += current_page_read_size;
  105.     } while (read_bytes < size);
  106.    
  107.     return read_bytes;
  108. }


测试代码如下:
  1. uint8_t w_buf[1024];
  2. uint8_t r_buf[1024];
  3. int8_t result = -1;


  4. // 应用初始化
  5. void app_init(void)
  6. {
  7.     /* 硬件IIC */
  8.     bsp_iic_init();   
  9.     for (uint16_t i = 0; i < sizeof(w_buf); i++) {
  10.         w_buf[i] = 10 + i;
  11.     }
  12.     bsp_at24c08_write(0, w_buf, sizeof(w_buf));
  13.     bsp_at24c08_read(0, r_buf, sizeof(r_buf));
  14.    
  15.     result = memcmp(w_buf, r_buf, sizeof(w_buf));
  16. }

  17. // 应用任务
  18. void app_task(void)
  19. {
  20. }


详细代码,请查看附件:
AT24C08_Hardware.zip (2 MB, 下载次数: 1)



9204668bbdaee025e5.png
天鹅绒之夜 发表于 2025-9-7 23:13 | 显示全部楼层
我每次使用库函数转入I2C从地址的时候都要试试,其值是不是需要左移1位
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

44

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部