你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 USART3使用DMA接收数据被覆盖出错

[复制链接]
Johnson wang 提问时间:2016-1-22 11:25 /
最近一项目调试中发现stm32的usart3在工作在dma接收模式下,如果接收数据超出了DMA1_Channel3->CNDTR的指定的长度,会覆盖且只覆盖接收buf[0]。
比如:参数配置CNDTR=3,而当发送在单片机接收引脚上的帧数据为0x01,0x02,0x03,0x04,0x05共5个字节,当DMA接收第3个字节0x03后,CNDTR=0 DMA停止读取串口接收数据,然后软件重新修改CNDTR=3,开启MDA接收功能等待发送到RX上的下一帧数据。问题来了,此时如果RX上没有接收到任何数据的情况先,DMA会自动将上一帧的0x04写入到buf[0],同时CNDTR被减一变为2。
感觉上一帧数据在CNDTR等于0时还是会触发一次DMA接收,当CNDTR重新不等于0以后就开始执行读操作。

附上调试代码,请高手指点,谢谢!!


  • #include "stm32f10x.h"
  • #include <string.h>
  • /* 无符号类型 */
  • typedef uint8_t           INT8U;
  • typedef uint16_t          INT16U;
  • typedef uint32_t          INT32U;
  • typedef uint64_t          INT64U;
  • /* 有符号类型 */
  • typedef int8_t            INT8;
  • typedef int16_t           INT16;
  • typedef int32_t           INT32;
  • typedef int64_t           INT64;
  • typedef ErrorStatus       RESULT_STATE;
  • #define DEF_COM_RECV_BUF_SIZE  50
  • #define DEF_COM_SEND_BUF_SIZE  50
  • struct
  • {
  •   INT8U SendBuf[DEF_COM_SEND_BUF_SIZE];
  •   INT8U RecvBuf[DEF_COM_RECV_BUF_SIZE];
  •   INT16U RecvLen;
  •   INT8U fSending :1;
  •   INT8U fRecv :1;
  • }sCom;
  • static void HW_ComCfg (void)
  • {
  •   /* GPIOB & AFIO Periph clock enable */
  •   RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
  •   RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
  •   /* PB10 USART3_Tx */
  •   GPIOB->CRH = (GPIOB->CRH & (~GPIO_CRH_MODE10)) | GPIO_CRH_MODE10_1; /* Output mode, max speed 2 MHz */
  •   GPIOB->CRH = (GPIOB->CRH & (~GPIO_CRH_CNF10)) | GPIO_CRH_CNF10_1; /* Alternate functionoutput Push-pull */
  •   /* PB11 USART3_Rx */
  •   GPIOB->CRH = (GPIOB->CRH & (~GPIO_CRH_MODE11)); /* input */
  •   GPIOB->CRH = (GPIOB->CRH & (~GPIO_CRH_CNF11)) | GPIO_CRH_CNF11_0; /* Floating input */
  •   /* Enable USART3 Clock */
  •   RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
  •   /* 1Start/9Data/1Stop */
  •   USART3->CR1 |= USART_CR1_M; /* 1 Start bit, 9 Data bits, n Stop bit */
  •   USART3->CR1 |= USART_CR1_PCE; /* Parity control enable */
  •   USART3->CR1 |= USART_CR1_PS; /* Odd parity */
  •   USART3->CR2 &= ~USART_CR2_STOP; /* 1 Stop bit */
  •   /* baud 115200bps */
  •   USART3->BRR = (INT32U)(((72000000ul/2)/115200/16 << 4) /* DIV_Mantissa */
  •                        | ((INT64U)(72000000ul/2)*10000/115200/16 - (72000000ul/2)/115200/16*10000)*16/10000); /* DIV_Fraction */
  •   /* DMA for transmission */
  •   USART3->CR3 |= USART_CR3_DMAT; /* transmission DMA enabled */
  •   /* DMA1 channel2 */
  •   RCC->AHBENR |= RCC_AHBENR_DMA1EN; /* Enable DMA1 Clock */
  •   DMA1_Channel2->CCR = (DMA1_Channel2->CCR & (~DMA_CCR2_PL)) | DMA_CCR2_PL_0; /* Channel priority level: medium */
  •   DMA1_Channel2->CCR = (DMA1_Channel2->CCR & (~DMA_CCR2_MSIZE)); /* Memory size:8-bits */
  •   DMA1_Channel2->CCR = (DMA1_Channel2->CCR & (~DMA_CCR2_PSIZE)); /* Peripheral size:8-bits */
  •   DMA1_Channel2->CCR |= DMA_CCR2_MINC; /* Memory increment mode enabled */
  •   DMA1_Channel2->CCR &= ~DMA_CCR2_PINC; /* Peripheral increment mode disabled */
  •   DMA1_Channel2->CCR |= DMA_CCR2_DIR; /* Read from memory */
  •   DMA1_Channel2->CPAR = (INT32U)&USART3->DR; /* Peripheral address */
  •   /* DMA for receive */
  •   USART3->CR3 |= USART_CR3_DMAR; /* receive DMA enabled */
  •   /* DMA1 channel3 */
  •   DMA1_Channel3->CCR = (DMA1_Channel3->CCR & (~DMA_CCR3_PL)) | DMA_CCR3_PL_1; /* Channel priority level: high */
  •   DMA1_Channel3->CCR = (DMA1_Channel3->CCR & (~DMA_CCR3_PSIZE)); /* Peripheral size:8-bits */
  •   DMA1_Channel3->CCR = (DMA1_Channel3->CCR & (~DMA_CCR3_MSIZE)); /* Memory size:8-bits */
  •   DMA1_Channel3->CCR &= ~DMA_CCR3_PINC; /* Peripheral increment mode disabled */
  •   DMA1_Channel3->CCR |= DMA_CCR3_MINC; /* Memory increment mode enabled */
  •   DMA1_Channel3->CCR &= ~DMA_CCR3_DIR; /* Read from Peripheral */
  •   DMA1_Channel3->CPAR = (INT32U)&USART3->DR; /* Peripheral address */
  •   /* interrupt */
  •   USART3->CR1 |= USART_CR1_IDLEIE; /* IDLE */
  •   /* USART enable */
  •   USART3->CR1 |= USART_CR1_TE | USART_CR1_RE; /* Transmitter and Receiver enable */
  •   USART3->CR1 |= USART_CR1_UE; /* USART prescaler and outputs enabled */
  • }
  • RESULT_STATE Com_Send (INT8U *p_data, INT16U len)
  • {
  •   if (sCom.fSending)
  •   {
  •     return ERROR;
  •   }
  •   if (len > DEF_COM_SEND_BUF_SIZE || len == 0)
  •   {
  •     return ERROR;
  •   }
  •   memcpy(&sCom.SendBuf[0], p_data, len);
  •   DMA1_Channel2->CCR &= ~DMA_CCR2_EN; /* Channel disabled */
  •   DMA1_Channel2->CNDTR = (INT32U)len; /* Number of data to transfer */
  •   DMA1_Channel2->CCR |= DMA_CCR2_EN; /* Channel enabled */
  •   USART3->CR1 |= USART_CR1_TCIE; /* TC */
  •   sCom.fSending = 1;
  •   return SUCCESS;
  • }
  • void ComInit (void)
  • {
  •   DMA1_Channel2->CMAR = (INT32U)&sCom.SendBuf[0]; /* Memory address */
  •   DMA1_Channel3->CCR &= ~DMA_CCR3_EN; /* Channel disabled */
  •   DMA1_Channel3->CMAR = (INT32U)&sCom.RecvBuf[0]; /* Memory address */
  •   DMA1_Channel3->CNDTR = (INT32U)sizeof(sCom.RecvBuf); /* Number of data to transfer */
  •   DMA1_Channel3->CCR |= DMA_CCR3_EN; /* Channel enabled */
  • }
  • static void HW_InterruptCfg (void)
  • {
  •   NVIC_InitTypeDef NVIC_InitStructure;
  •   /* Configures the priority grouping */
  •   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  •   /* COM */
  •   NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  •   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  •   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  •   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  •   NVIC_Init(&NVIC_InitStructure);
  • }
  • void USART3_IRQHandler(void)
  • {
  •   /* Transmission complete */
  •   if (sCom.fSending && (USART3->SR & USART_SR_TC))
  •   {
  •     USART3->CR1 &= ~USART_CR1_TCIE; /* TCIE */
  •     sCom.fSending = 0;
  •   }
  •   /* IDLE line detected */
  •   if (USART3->SR & USART_SR_IDLE)
  •   {
  •     sCom.RecvLen = (INT32U)sizeof(sCom.RecvBuf) - DMA1_Channel3->CNDTR;
  •     DMA1_Channel3->CCR &= ~DMA_CCR3_EN; /* Channel disabled */
  •     DMA1->IFCR |= DMA_IFCR_CGIF3;
  •     DMA1_Channel3->CNDTR = (INT32U)sizeof(sCom.RecvBuf); /* Number of data to transfer */
  •     DMA1_Channel3->CCR |= DMA_CCR3_EN; /* Channel enabled */
  •     if (USART3->SR & (USART_SR_NE | USART_SR_FE | USART_SR_PE)) /* Noise/Framing/Parity error is detected */
  •     {
  •     }
  •     else
  •     {
  •       sCom.fRecv = 1;
  •     }
  •     INT32U sr = USART3->SR; /* clear sr */
  •     INT32U dr = USART3->DR; /* clear dr */
  •   }
  • }
  • void main (void)
  • {
  •   HW_ComCfg();
  •   HW_InterruptCfg();
  •   ComInit();
  •   while (1)
  •   {
  •     if (sCom.fRecv)
  •     {
  •       Com_Send(&sCom.RecvBuf[0], sCom.RecvLen);
  •       sCom.fRecv = 0;
  •     }
  •   }
  • }



收藏 评论1 发布时间:2016-1-22 11:25

举报

1个回答
xmshao 回答时间:2016-1-22 17:30:50
既然要这样的话,再重启DMA前,你把RXNE也清下看看。

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版