打印
[信息]

【实战经验】增加UART接口应用时的异常分析

[复制链接]
1180|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 香水城 于 2017-8-11 14:27 编辑

增加UART接口应用时的异常分析

前言
Cube软件包的提供,极大的降低了开发难度。使用者在开发的过程中,只需参考Cube包中提供的例程就能快速的实现对应功能开发。开发者为了快速开发UART功能,参考Cube包中的UART例程,并根据应用情况,扩展了另一组UART接口。但是在应用过程中,发现两路UART不能共存。本文分析了这种情况出现的原因。

背景介绍
在Cube软件包中CDC例程实现了虚拟串口通信功能,数据传输链路如下图所示。

在开发者的应用中,需要实现下图数据传输链路。根据应用需求,推荐参考Cube软件包中的USB CDC例程。


问题描述
问题复现平台: STM324xG-Eval
例程路径:STM32Cube_FW_F4_V1.15.0\Projects\STM324xG_EVAL\Applications\USB_Device\CDC_Standalone
在对CDC例程了解后,参考已有的UART应用,新增了一路UART。对应初始化程序如下所示。其中USARTx为例程原有部分,而USARTy为新增的一路UART初始化部分。



在之前的UART发送和接收处,同样新增了一路UART的发送和接收。为了方便描述,这里不对应用层面进行描述。而是直接在例程中,时钟配置后执行下述语句,复现问题。


结果如下表。


问题分析
不同UART接口相互独立。UART IP设计上,不同UART同时发送不会相互影响。初步判断应该是UART初始化过程中,存在冲突。
通过对结果分析,在UARTx和UARTy都进行初始化后,只执行UARTx DMA 发送时,执行异常;只执行UARTy DMA发送时,执行正常。而在初始化中,UARTx先于UARTy初始化,进一步确认是初始化时,存在冲突。并且将问题范围缩小到HAL_UART_MspInit()函数中。
在线调试,发现在执行UARTy初始化时(UARTx已经在之前初始化结束),UARTx 发送DMA对应的Instant和Channel值都被改变。其中Instant中保存着对应DMA的寄存器基地址。
仔细检查HAL_UART_MspInit()函数,发现对于DMA的初试化,两个UART共用了例程中原有的DMA句柄变量,为上述程序中的static DMA_HandleTypeDef hdma_tx;
而在HAL_UART_Transmit_DMA函数中,会对对应的DMA进行配置并使能,而配置过程会依据DMA句柄中的参数。从而导致发送异常。
对问题的产生原因清楚后,在新增UART接口的时候,初始化函数HAL_UART_MspInit()中同样需要新增DMA句柄变量,并利用在新增UART的DMA初始化中。如下所示。



总结
所描述的问题,可以归结为一个开发漏洞。而导致这个开发漏洞的原因,更多的可能是在参考Cube例程时,对于各函数的了解以及变量的使用情况,没有逐个了解。建议在基于Cube例程进行开发时,能够对各函数及变量等加以了解,在针对应用进行修改过程中,能够减小错误率,从而减少排错时间。

对应的PDF: 增加UART接口应用时的异常分析
更多实战经验请看:【ST MCU实战经验汇总贴】

沙发
qq12344321| | 2017-5-17 17:00 | 只看该作者
香水大哥你好,最近遇到一个串口问题,想麻烦你有空的时候帮看下:
最近公司一个项目,使用的核心板是正点原子的F767,自己设计了外部电路,现在在串口通讯是有点问题无法解决。
其中用到几个串口,和定时器,其中串口1是和上位机通讯,串口1的优先级最高,抢占优先级是1,其他串口和定时器都是2和3,串口1需要将ADC采集的数据每100ms一次上传给上位机;同时接收上位机的控制指令。串口1我只打开了接收中断,在接受中断中的唯一操作是将接收到的字节存入到我事先准备好的缓存数组中。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)      
{
if(huart->Instance==USART1)
{
   UART1_RX_BUF[++UART1_ReceiveBuf_Count] = aRxBuffer_UART1[0];   //将接收到的字节存入自己定义的接收缓存数组中
  if(UART1_ReceiveBuf_Count%50==0) LED1_Toggle;
}
每次ADC采集完成(100ms),将采集的值存入到我自己定义的发送缓存数组中,串口1的发送是循环发送,主循环中每次最多发送一个字节,主循环很快。
  if(ADC_Sampling_Enable==0)   //1组采样完成
  {
    Vin1=2.5*ADS1251_Read_middle(ADC_Sample)/0x7fffff;
    ADC_Sampling_Enable=1;    //开启下一组采样
   UART1_DisposalTemp[0]='?';    //头
   UART1_DisposalTemp[1]='1';    //表示主板的信息
   UART1_DisposalTemp[2]='1';    //表示测量的电压
   UART1_DisposalTemp[3]='1';    //对应的档位
      ADC_float_to_ascll(Vin1,UART1_DisposalTemp) ;
     UART1_DisposalTemp[11]='#';
     //printf(urt_disposaltemp);
    for(i=0;i<12;i++)
    {
     UART1_TX_BUF[++UART1_SendBuf_Count]=UART1_DisposalTemp[i];   //ADC采样值存入到自己定义的发送缓存数组中,等待发送
   }
   }


   if(UART1_SendBuf_Count!=UART1_SendBuf_Current)  //main循环中发送串口数据,此处每次最多发一个字节
  {
     HAL_UART_Transmit(&UART1_Handler,(uint8_t*)(&UART1_TX_BUF[++UART1_SendBuf_Current]),1,1000); //发送接收到的数据
   while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);  //等待发送结束
  }

问题如下:
串口1发送没问题,但是接收一段时间后会出现无法接收的现象,程序没有卡死,因为串口还在定时发送,但是就是无法进入串口接收中断。当我串口不发送时(把这句注释掉://UART1_TX_BUF[++UART1_SendBuf_Count]=UART1_DisposalTemp[i]; ),则串口接收就没问题。一开始以为接收中断是不是打开,调试时确认没打开(TXEIE和TCIE都是0);请教,这个可能是什么原因?

使用特权

评论回复
板凳
updownq| | 2017-5-17 23:04 | 只看该作者
虚拟串口?

使用特权

评论回复
地板
updownq| | 2017-5-17 23:05 | 只看该作者
异常表现都自己配置能够消除吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:STM32技术专家

596

主题

17106

帖子

287

粉丝