今天测试用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不正常
下面是逻辑分析仪的显示
前面一段很长的是用轮询方式发送的,屏幕现象和逻辑分析都正常。后面一段是用DMA发送的,发送了一点后就停了,而且时钟线也被锁在了低。
下图是DMA传输结束时候的细节。
在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
一周热门 更多>