基于STM32H563 USART演示DMA链表功能

发布时间:2023-10-20  

这里选用STM32H563Nucleo开发板,使用USART3外设演示DMA链表模式的实现过程。大致过程是这样的:

STM32H563芯片上的USART3与板载STLINK的VCP相连,通过PC端串口助手软件先后发送3串字符给MCU,MCU的USART3通过DMA以链表模式依次接收并存到相应内存,同时在相应的调试界面的观察窗口加以显示。接收过程对应3个DMA接收节点,他们构成1个DMA接收队列。当MCU接收到3串字符后,也以DMA 链表模式依次发送3串字符到PC端的串口助手并显示出来。同样,USART3的DMA 发送也用到3个节点以组成1个DMA发送队列。


GPDMA1的2个通道CH0,CH1,配置在链表模式。其中CH0用于USART3 RX DMA队列,CH1用于USART3 TX DMA队列。这个通道安排可以在用户代码里调整。

下面使用STM32CbueMx图形化工具进行基本配置后创建测试工程。【注:手机模式下文中图片可放大查看】

85549b76-37d8-11ee-9e74-dac502259ad0.png

859f4e6e-37d8-11ee-9e74-dac502259ad0.png

85c49232-37d8-11ee-9e74-dac502259ad0.png

3个USART3 DMA RX节点的配置如下【3个配置类似,只是源地址、目标地址有差异】:

85d64a9a-37d8-11ee-9e74-dac502259ad0.png

861507ee-37d8-11ee-9e74-dac502259ad0.png

864672fc-37d8-11ee-9e74-dac502259ad0.png

867a37f4-37d8-11ee-9e74-dac502259ad0.png

3个USART3 DMA TX节点的配置如下【3个配置类似,只是源地址、目标地址有差异】:

8690f37c-37d8-11ee-9e74-dac502259ad0.png

86c97e72-37d8-11ee-9e74-dac502259ad0.png

87027132-37d8-11ee-9e74-dac502259ad0.png

相关的用户参考代码如下:

 

#define RXBUFFERSIZE  (8)


#define TXBUFFERSIZE  (22)


volatile uint8_t RxComplete=0;//DMA接收完成标志


ALIGN_32BYTES (uint8_t aTxBuffer0[])="
STM32H5_DMA_LIST_0
";
ALIGN_32BYTES (uint8_t aTxBuffer1[])="
STM32H5_DMA_LIST_1
";
ALIGN_32BYTES (uint8_t aTxBuffer2[])="
STM32H5_DMA_LIST_2
";


ALIGN_32BYTES (uint8_t aRxBuffer0[RXBUFFERSIZE]);
ALIGN_32BYTES (uint8_t aRxBuffer1[RXBUFFERSIZE]);
ALIGN_32BYTES (uint8_t aRxBuffer2[RXBUFFERSIZE]);


DMA_HandleTypeDef handle_GPDMA1_Channel1;
DMA_HandleTypeDef handle_GPDMA1_Channel0;UART_HandleTypeDef huart3;


int main(void)
{


/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();


/* Configure the system clock */
  SystemClock_Config();


/* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_GPDMA1_Init();
//MX_ADC1_Init();
  MX_ICACHE_Init();
  MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */


  MX_Uart_tx_queue_Config();
  MX_Uart_rx_queue_Config();


/* Link UART queue to DMA channel */
  HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &Uart_tx_queue);


/* Associate the initialized GPDMA handle to the UART handle */
  __HAL_LINKDMA(&huart3, hdmatx, handle_GPDMA1_Channel0);


/* Link UART queue to DMA channel */
  HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel1, &Uart_rx_queue);


/* Associate the initialized GPDMA handle to the UART handle */
  __HAL_LINKDMA(&huart3, hdmarx, handle_GPDMA1_Channel1);


HAL_UART_Receive_DMA(&huart3, (uint8_t *)aRxBuffer0, RXBUFFERSIZE);


/* USER CODE END 2 */


/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
  {




  if(RxComplete)  //check uart Rx DMA transfer complete or not


  {
  RxComplete=0;
  huart3.gState = HAL_UART_STATE_READY;
  HAL_UART_Transmit_DMA(&huart3, (uint8_t*)aTxBuffer0, TXBUFFERSIZE);


  }


  }


}


/* UART3 DMA 接收完成中断回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  RxComplete++; //DMA transfer completed
}

 

下面开始运行程序以验证结果。

PC串口终端先发送三串字符被MCU USART3通过DMA接收,然后MCU以DMA链表的形式发送三串字符到串口终端。下图中右边观察串口的字符为USART3通过DMA以链表形式接收的来自串口助手的数据。下图中绿色方框内三串字符为STM32H563 USART3以DMA链表形式3次发送出来的。

874001c8-37d8-11ee-9e74-dac502259ad0.png

在上面测试中,关于DMA传输完成事件的配置,我选择的针对整个DMA传输链完成传输后才产生完成事件。以上面的USART3 RX DMA接收为例,当3个节点都完成DMA接收时才触发DMA传输完成事件。当然,我们也可以基于每个DMA传输节点来产生DMA传输完成事件,比如按下面的配置修改。

876bd302-37d8-11ee-9e74-dac502259ad0.png

如果这样修改之后,其它地方不动,这时USART3 通过DMA每收到一串数据都会触发传输完成事件,并在相应中断里设置完成事件标志【RxComplete】,进而启动USART3发送的DMA 链式传输。见下图结果【褐紫色字符是USART3通过DMA接收到的数据】:

877e0324-37d8-11ee-9e74-dac502259ad0.png

其实,在前面验证过程中,发生了点小波折也顺便分享出来。

当我做完基本的配置,创建工程、添加用户代码。编译、除错后,开始运行程序时并不顺利。

我先使用串口助手发送字符串给MCU,可是在USART3的DMA接收队列里,只有第一个节点有反应。通过开发环境的观察窗口看到的接收数据跟我发出去的字符大相径庭,其它2个DMA接收节点不论我发送多少数据就根本没反应。因为我设计的就是只有当接收队列即3个接收节点都正常接收后才会启动USART3的DMA发送队列。所以此时USART3也就没有任何数据发送出来。检查配置和用户代码,但没有很快发现问题原因。

后来在检查USART3的基本通信配置时,无意中发现了一点异样。就是有关接收数据是否需要翻转的配置项不知何时变成Enable了。

87c25df8-37d8-11ee-9e74-dac502259ad0.png

显然,这个地方不能翻转,不然发送的数据跟接收的数据肯定不一样了。我清楚地记得这个地方我是没动的,不知是不是某个时候不小心碰着而改动了。立即将其Disable掉后进行测试验证。

测试结果发现第一个DMA接收节点的数据正常了。但奇怪的是第2个、第3个接收节点仍然接收不到数据。又是一番配置和代码核对,无果。

后来,先干脆不管接收队列,而试着直接启动USART3的DMA发送队列。庆幸的是,发送很正常。看来,USART3 TX DMA发送队列的配置是靠谱的。其实USART3 RX DMA接收队列的配置跟发送队列配置很相似,只是请求源、传输端地址的配置差异。再次逐个核对DMA接收节点2和3的配置。功夫不负有心人,果真发现乌龙了。在DMA接收节点2的DMA请求配置那里,我竟然不小心选成USART1的了,一字之差,谬以千里。节点3的配置没有问题。看来问题就出在接收节点2的那个误选项。立马验证,结果一切正常了。

为什么只是节点2配置有问题,节点3也不能接收数据呢?因为这3个节点构成了一条关于DMA传输的时序、事件配合链,节点2没有正常完成,节点3也没法正常启动。

另外,还解释一个变量。我在代码里设置了RxComplete变量,是用来标记DMA接收完成事件的,在主程序和中断里都用到了。记得定义它时加上volatile,不然当优化等级调至较高时,可能出现程序运行异常情况。

OK,今天的DMA 链表功能的应用演示就到分享这里,下次再聊。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>