GD32F30x系列的芯片,IIC使用DMA和EEPROM通信总线无法正常关闭总线

[复制链接]
 楼主| JOJO2025 发表于 2025-6-3 09:06 | 显示全部楼层 |阅读模式
公司需求更换GD32的芯片替换STM32,程序流程基本照着实例和网上找的弄的,第一次写入能正常开关总线,但是第一次读取虽然能读到正确数值,但是在完成后无法正常关闭总线,while(I2C_CTL0(I2C0) & 0x0200);会在这个地方卡死,如果删去这里,第二次写入外设也会在while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));这里卡死。
搞了几天,各种资料看的头都大了,希望各位能来帮忙解答,拜!
下面是代码:
  1. void I2C_config(void)
  2. {
  3.     rcu_periph_clock_enable(RCU_GPIOB);
  4.     rcu_periph_clock_enable(RCU_I2C0);
  5.     rcu_periph_clock_enable(RCU_DMA0);
  6.    
  7.     gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
  8.    
  9.     i2c_deinit(I2C0);
  10.    
  11.     i2c_clock_config(I2C0, 1000000, I2C_DTCY_16_9);
  12.     i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x11);
  13.     i2c_enable(I2C0);
  14.     i2c_ack_config(I2C0, I2C_ACK_ENABLE);
  15. }

  16. uint8_t I2C(uint8_t Addr, uint8_t *TRxData,uint16_t Size)
  17. {
  18.     if(Addr == SLAVE1ADDR_W)
  19.     {
  20.         dma_deinit(DMA0, DMA_CH5);//复位外设DMAx的通道y的所有寄存器
  21.         dma_struct_para_init(&dma_init_struct);//将DMA结构体中所有参数初始化为默认值

  22.         dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;//读取存储器中数据,写入外设(写入)
  23.         dma_init_struct.memory_addr = (uint32_t)TRxData;
  24.         dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  25.         dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
  26.         dma_init_struct.number = Size;//数据传输数量
  27.         dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0);//**
  28.         dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  29.         dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
  30.         dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
  31.         dma_init(DMA0, DMA_CH5, &dma_init_struct);
  32.         
  33.         while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
  34.         i2c_start_on_bus(I2C0);
  35.         while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
  36.            i2c_master_addressing(I2C0, Addr, I2C_TRANSMITTER);
  37.         while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
  38.         i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
  39.         
  40.         i2c_dma_config(I2C0, I2C_DMA_ON);
  41.         dma_channel_enable(DMA0, DMA_CH5);
  42.         while(!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF));
  43.         dma_flag_clear(DMA0, DMA_CH5, DMA_FLAG_FTF);
  44.         
  45.     i2c_stop_on_bus(I2C0);
  46.     while(I2C_CTL0(I2C0)<span style="color: rgb(77, 77, 77); font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun; font-variant-ligatures: common-ligatures; background-color: rgb(255, 255, 255);"> & </span>0x0200);
  47.     i2c_dma_config(I2C0, I2C_DMA_OFF);
  48.     dma_channel_disable(DMA0, DMA_CH5);
  49.     }
  50.     else if(Addr == SLAVE1ADDR_R)
  51.     {
  52.         dma_deinit(DMA0, DMA_CH6);//复位外设DMAx的通道y的所有寄存器
  53.         dma_struct_para_init(&dma_init_struct);//将DMA结构体中所有参数初始化为默认值

  54.         dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;//读取外设中数据,写入存储器(读取)
  55.         dma_init_struct.memory_addr = (uint32_t)TRxData;
  56.         dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  57.         dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
  58.         dma_init_struct.number = Size;//数据传输数量
  59.         dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0);//**
  60.         dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  61.         dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
  62.         dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
  63.         dma_init(DMA0, DMA_CH6, &dma_init_struct);
  64.         
  65.         while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
  66.         i2c_start_on_bus(I2C0);
  67.         while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
  68.         i2c_master_addressing(I2C0, Addr, I2C_RECEIVER);
  69.         while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
  70.         i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
  71.         
  72.         i2c_dma_config(I2C0, I2C_DMA_ON);
  73.         dma_channel_enable(DMA0, DMA_CH6);
  74.         while(!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF));
  75.         dma_flag_clear(DMA0, DMA_CH6, DMA_FLAG_FTF);
  76.         
  77.      i2c_stop_on_bus(I2C0);
  78.      while(I2C_CTL0(I2C0)<span style="color: rgb(77, 77, 77); font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun; font-variant-ligatures: common-ligatures; background-color: rgb(255, 255, 255);"> & </span>0x0200);
  79.      i2c_dma_config(I2C0, I2C_DMA_OFF);
  80.      dma_channel_disable(DMA0, DMA_CH6);
  81.     }
  82.     return 1;
  83. }

  84. int main(void)
  85. {
  86.     I2C_config();
  87.    
  88.     uint8_t IICTXData[3] = {0,0,100};
  89.     uint8_t IICRXData[3] = {0,0,0};
  90.    
  91.     I2C(SLAVE1ADDR_W,IICTXData,3);
  92.    
  93.     I2C(SLAVE1ADDR_R,IICTXData,3);

  94.     if(IICRXData[0] == 100)
  95.         {
  96.             gpio_bit_reset(GPIOG, GPIO_PIN_15);//亮灯
  97.         }
  98.   
  99.         delay_1ms(10);
  100.   
  101.         IICTXData[2] = 99;
  102.             
  103. I2C(SLAVE1ADDR_W,IICTXData,3);

  104. I2C(SLAVE1ADDR_R,IICTXData,3);
  105.    
  106.     if(IICRXData[0] == 99)
  107.         {
  108.             gpio_bit_set(GPIOG, GPIO_PIN_15);//灭灯
  109.         }
  110. }


kaif2n9j 发表于 2025-6-4 12:46 | 显示全部楼层
在将STM32代码迁移到GD32芯片时,可能会遇到一些由于硬件差异或寄存器配置不同导致的问题
suw12q 发表于 2025-6-4 12:49 | 显示全部楼层
确保使用的I2C状态标志与GD32的I2C寄存器定义一致。查阅GD32的数据手册,确认I2C_CTL0和I2C_FLAG_I2CBSY的定义。
g0d5xs 发表于 2025-6-4 13:51 | 显示全部楼层
I2C_CTL0(I2C0) & 0x0200:这个条件检查I2C控制寄存器0中的某个位状态,可能是用于检测I2C总线的忙状态。如果这个位在GD32中与STM32中的定义不同,可能会导致错误的判断。
b5z1giu 发表于 2025-6-4 15:14 | 显示全部楼层
I2C_FLAG_I2CBSY,这个标志位用于检查I2C总线是否忙。如果在GD32中这个标志位的定义或行为与STM32不同,可能会导致代码卡死
l1uyn9b 发表于 2025-6-4 16:08 | 显示全部楼层
I2C外设的初始化配置(如时钟速度、模式设置等)可能不正确,导致总线无法正确释放或进入错误状态。
lamanius 发表于 2025-6-4 18:01 | 显示全部楼层
硬件连接(如上拉电阻、信号线长度等)可能导致I2C总线信号不稳定,从而无法正确完成总线操作。
cen9ce 发表于 2025-6-4 19:06 | 显示全部楼层
在I2C操作完成后,没有正确清除中断标志或状态标志,导致总线状态判断错误。
w2nme1ai7 发表于 2025-6-5 08:12 | 显示全部楼层
仔细检查I2C的初始化代码,确保时钟配置、模式设置等与GD32的I2C外设要求一致。确保I2C时钟速度设置合理,避免因时钟速度不匹配导致总线错误。
y1n9an 发表于 2025-6-5 10:25 | 显示全部楼层
使用示波器或逻辑分析仪监测I2C总线信号,确保总线操作(如START、STOP、ACK等)正常完成。检查I2C外设的中断配置,确保在操作完成后能正确清除中断标志。
dffzh 发表于 2025-6-5 11:08 | 显示全部楼层

我从GD32官网https://www.gd32mcu.com/上下载了demo程序,结果发现I2C_EEPROM_dma文件夹里面好像没有关于dma的,神奇了!
2187268410a32a38cb.png
547766841099644d23.png
你可以下载下来看下。
p0gon9y 发表于 2025-6-5 13:26 | 显示全部楼层
查找GD32的I2C官方例程,确保代码逻辑与官方例程一致。官方例程通常会提供经过验证的I2C读写流程,可以参考其状态检查和配置方法。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

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