
上期我们解决了STM32H5中DCMI无法工作的问题,但是DCMI与DMA通讯一直出现了问题。本期详细介绍下是如何一步一步Debug排除错误的。


开启H563的GPDMA,之前是没怎么搞明白GPDMA的各项设置,因此基本都是默认配置。所以最开始的DataWidth是默认HalfWord也就是16位的,结果DMA一直不会开启传输。
得幸于找到ST的一篇应用笔记。
其中推荐了配置,并且强调了应该使用Word(32位)设置来使用GPDMA。
启动DCMI之后,发现DMA传输依旧有问题,缓存区只有第一个有数据,其他都是0x00;ErrorCode是0x20(图中是正常的)。DCMI的ErrorCode是0x41.
互联网上基本没有关于具体ErrorCode的描述,因此只能依靠自己来解决这个问题。
查看关于DMA的ErrorCode的定义,表示大概是传输目标出现了问题 ,而DCMI的ErrorCode 0x41正是表明这DMA传输出现了Error因此首先要解决的是GPDMA传输的问题。
在Debug的过程中我突然发现(注意力惊人)缓存区的第一个数据在极快的情况下更新,之后不更新。
会不会是缓存区实际更新到了缓存区的第一个位置,而不是整个缓存区?

DMA的参数不是必须传入一个指针,而是传入一个整型数(注意嗷,指针代表的是地址,32单片机是32位的,所以也可以用uint32_t来存放指针)。

在常规的DMA中右边有一个Increment Address它默认是开启的。
它的作用的每次传输完成后,将目标地址的值递增。

前面的Peripheral是外设地址,外设地址是不变的,它永远指向DCMI的SR指针。
但是我们的缓存区,也就是内存地址Memory地址是需要递增的,以便我们的数据可以顺序的存储下去。

因此需要在GPDMA中开启目标地址的递增。这样子就可以成功的实现DMA传输。
void DMA2_Stream1_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream1_IRQn 0 */
/* USER CODE END DMA2_Stream1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_dcmi);
/* USER CODE BEGIN DMA2_Stream1_IRQn 1 */
frame_complete_flag = 1;
/* USER CODE END DMA2_Stream1_IRQn 1 */
}
定义一个传输完成的标志变量,当这个变量是1的时候开始将DCMI的数据转到屏幕中。这一步也可以用中断来实现。
if(frame_complete_flag)
{
HAL_DCMI_Stop(&hdcmi);
frame_complete_flag = 0;
//ST7789_DrawImage(0,0,IMAGE_WEIGH,IMAGE_HEIGH,frame_buffer);
ST7789_Fill_Image(frame_buffer);
HAL_DCMI_Start_DMA(&hdcmi,DCMI_MODE_CONTINUOUS,(uint32_t)frame_buffer,IMAGE_WEIGH*IMAGE_HEIGH/2);
}
if(hdcmi.Instance->RISR & 0x02)
{
hdcmi.Instance->ICR = 0x02;//清除损坏位
}
if(!(hdcmi.Instance->CR & 0x01))
{
HAL_DCMI_Start_DMA(&hdcmi,DCMI_MODE_CONTINUOUS,(uint32_t)frame_buffer,IMAGE_WEIGH*IMAGE_HEIGH/2);
}
主循环中添加轮询的代码,包括错误处理和图像捕获完成之后的图像传输。
这样子就完成了我们的代码实现。


登录 或 注册 后才可以进行评论哦!
还没有评论,抢个沙发!