求助HAL库 IIC的DMA传输字节限制问题。

2019-07-20 06:28发布

今天测试用IIC驱动SSD1306的12864OLED.
使用轮询模式IIC发送整屏一切正常,但是使用DMA模式发送,只发送出前面大概200多个字节,后面就发不出去了,时钟信号也被拉低没有变高。
DMA是普通模式。之前也用DMA读写IIC的传感器,但是字节数很少,没出过问题,这次全屏操作不问题了,不知前辈们有何办法。(拒绝模拟IIC,速度太慢)

整个程序只有IIC的OLED操作,不存在被打断的问题吧。。。

HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT, BMP1, 128*8, 1000);//轮询正常
HAL_Delay(50);
HAL_I2C_Mem_Write_DMA(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT, BMP1, 128*8);//DMA不正常

下面是逻辑分析仪的显示
逻辑分析图.JPG
前面一段很长的是用轮询方式发送的,屏幕现象和逻辑分析都正常。后面一段是用DMA发送的,发送了一点后就停了,而且时钟线也被锁在了低。
下图是DMA传输结束时候的细节。
问题处细节.JPG


在stm32f3xx_hal_i2c.c中,关于size超过255的处理是这样的:
轮询方式中:
***************无关代码*************
    hi2c->XferCount = Size;

***************无关代码*************

    /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */
    if (hi2c->XferCount > MAX_NBYTE_SIZE)
    {
      hi2c->XferSize = MAX_NBYTE_SIZE;
      I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
    }
    else
    {
      hi2c->XferSize = hi2c->XferCount;
      I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
    }

***************无关代码*************


然后进入循环,没法送一个hi2c->XferCount--,这样吧所有数据发送完。


在DMA方式中:


***************无关代码*************


    hi2c->XferCount   = Size;


***************无关代码*************



if (hi2c->XferCount > MAX_NBYTE_SIZE)
    {
      hi2c->XferSize = MAX_NBYTE_SIZE;
      xfermode = I2C_RELOAD_MODE;
    }
    else
    {
      hi2c->XferSize = hi2c->XferCount;
      xfermode = I2C_AUTOEND_MODE;
    }

***************无关代码*************


    /* Send Slave Address */
    /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
    I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_NO_STARTSTOP);
    /* Update XferCount value */
    hi2c->XferCount -= hi2c->XferSize;


***************无关代码*************






也没有循环,然后这这么两句就完了, I2C_TransferConfig传入了xfermode,但是


static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c,  uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request)
{
  /* Check the parameters */
  assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
  assert_param(IS_TRANSFER_MODE(Mode));
  assert_param(IS_TRANSFER_REQUEST(Request));
  /* update CR2 register */
  MODIFY_REG(hi2c->Instance->CR2, ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - I2C_CR2_RD_WRN_Pos))) | I2C_CR2_START | I2C_CR2_STOP)),
             (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | (uint32_t)Mode | (uint32_t)Request));
}



这个里面我就在看不懂了。不知道是哪里出的问题,应该如何配置,请求各路大侠指点。
我的工程在百度云分享里,接线就是默认的PB6和PB7。
链接:https://pan.baidu.com/s/1UMNmUNI_a79-PGt5Byd-Nw 密码:sxgb



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。