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

请教USART接收的问题

[复制链接]
xhx321 提问时间:2018-9-3 21:43 /
现在USART接受上遇到两个问题,想请教一下。
1. USART参数设为 19200 + 8Bit + Even + 1 Stop. 用 IRNE 中断来接受从串口来的字符输入。
   现在能接收到IRNE的中断并能正确读到字符,但是中断例程里同时能检测到帧错误(FE)或者校验错误(PE)。
   而且有这样的规律,若键入字符ASCII码为EVEN位数,则报PE,如果是ODD位数则包FE。
   请问有谁知道这种问题的是什么原因吗?

2. 还是USART接受字符问题。配置同上,接收字串在IRNE中断例程里读取单字节数据。正常串口输入能接收到正确字符,现象同1。
   如果用串口助手发送一串字符串,如“ABCDEFG”,中断里总是检测到 ORE的错误,并且会丢到几个字符。之前以为是系统时钟频率低导致的,
   于是将系统时钟频率由2MHz升到32MHz,问题依旧。请问这是什么原因?

附代码(stm32L07x):

  1. void USARTx_IRQHandler(void)
  2. {
  3.         iCnt++;
  4.         USART_FUNCTION_ISR = 0;          
  5.         if (LL_USART_IsActiveFlag_RXNE(USARTx_INSTANCE) && LL_USART_IsEnabledIT_RXNE(USARTx_INSTANCE))
  6.         {
  7.                 uiRxByte = (uint32_t)LL_USART_ReceiveData8(USARTx_INSTANCE);
  8.                   //LL_USART_TransmitData8(USARTx_INSTANCE, (uint8_t) uiRxByte);
  9.                   //LL_USART_TransmitData8(USARTx_DEBUG_INSTANCE, (uint8_t) uiRxByte);
  10.                   //printf("(%d)-rev(0x%02x)\n",iCnt, uiRxByte);
  11.                 USART_FUNCTION_ISR |= USART_ISR_RXNE_Msk;

  12.         }
  13.         if (LL_USART_IsActiveFlag_TXE(USARTx_INSTANCE) && LL_USART_IsEnabledIT_TXE(USARTx_INSTANCE))
  14.         {
  15.                    USART_FUNCTION_ISR |= USART_ISR_TXE_Msk;
  16.                    //printf ("(%d)-USARTx_IRQHandler-LL_USART_IsActiveFlag_TXE\n",iCnt);
  17.         }
  18.         if (LL_USART_IsActiveFlag_ORE(USARTx_INSTANCE))
  19.         {
  20.                    //printf("(%d)-OVERUN happened\n",iCnt);
  21.                    LL_USART_ClearFlag_ORE(USARTx_INSTANCE);
  22.                           LL_USART_ReceiveData8(USARTx_INSTANCE);
  23.                    USART_FUNCTION_ISR |= USART_ISR_ORE_Msk;
  24.         }
  25.         if (LL_USART_IsActiveFlag_NE(USARTx_INSTANCE))
  26.         {
  27.                           //printf("(%d)-Noise detected\n", iCnt);
  28.                    LL_USART_ClearFlag_NE(USARTx_INSTANCE);
  29.                           //LL_USART_ReceiveData8(USARTx_INSTANCE);
  30.                    USART_FUNCTION_ISR |= USART_ISR_NE_Msk;
  31.         }
  32.         if (LL_USART_IsActiveFlag_FE(USARTx_INSTANCE))
  33.         {
  34.                    //printf("(%d)-Frame Error\n",iCnt);
  35.                    LL_USART_ClearFlag_FE(USARTx_INSTANCE);
  36.                           //LL_USART_ReceiveData8(USARTx_INSTANCE);
  37.                    USART_FUNCTION_ISR |= USART_ISR_FE_Msk;
  38.         }
  39.         if (LL_USART_IsActiveFlag_PE(USARTx_INSTANCE))
  40.         {
  41.        //printf("(%d)-Parity Error\n",iCnt);
  42.                    LL_USART_ClearFlag_PE(USARTx_INSTANCE);
  43.                           //LL_USART_ReceiveData8(USARTx_INSTANCE);
  44.                    USART_FUNCTION_ISR |= USART_ISR_PE_Msk;
  45.         }
  46. }

  47. void USART_Init(       \
  48.         uint32_t uiBoudRate,  \
  49.         uint32_t uiDataWidth, \
  50.         uint32_t uiParity,    \
  51.         uint32_t uiStopBits)
  52. {
  53.     //TODO: Parameters checking

  54.     /* (1) Enable GPIO clock and configures the USART pins *********************/

  55.     /* Enable the peripheral clock of GPIO Port */
  56.     USARTx_GPIO_CLK_ENABLE();

  57.     /* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
  58.     LL_GPIO_SetPinMode(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_MODE_ALTERNATE);
  59.     USARTx_SET_TX_GPIO_AF();
  60.     LL_GPIO_SetPinSpeed(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
  61.     LL_GPIO_SetPinOutputType(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
  62.     LL_GPIO_SetPinPull(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_PULL_UP);

  63.     /* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */
  64.     LL_GPIO_SetPinMode(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_MODE_ALTERNATE);
  65.     USARTx_SET_RX_GPIO_AF();
  66.     LL_GPIO_SetPinSpeed(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
  67.     LL_GPIO_SetPinOutputType(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
  68.     LL_GPIO_SetPinPull(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_PULL_UP);

  69.     /* (2) NVIC Configuration for USART interrupts */
  70.     /*  - Set priority for USARTx_IRQn */
  71.     /*  - Enable USARTx_IRQn */
  72.     NVIC_SetPriority(USARTx_IRQn, 0);
  73.     NVIC_EnableIRQ(USARTx_IRQn);

  74.     /* (2) Enable USART peripheral clock and clock source ***********************/
  75.     USARTx_CLK_ENABLE();

  76.     /* Set clock source */
  77.     USARTx_CLK_SOURCE();

  78.     /* (3) Configure USART functional parameters ********************************/

  79.     /* Disable USART prior modifying configuration registers */
  80.     /* Note: Commented as corresponding to Reset value */
  81.     LL_USART_Disable(USARTx_INSTANCE);

  82.     /* TX/RX direction */
  83.     LL_USART_SetTransferDirection(USARTx_INSTANCE, LL_USART_DIRECTION_TX_RX);

  84.     /* 8 data bit, 1 start bit, 1 stop bit, no parity */
  85.     LL_USART_ConfigCharacter(USARTx_INSTANCE, uiDataWidth, uiParity, uiStopBits);

  86.     LL_USART_SetBaudRate(USARTx_INSTANCE, SystemCoreClock, LL_USART_OVERSAMPLING_16, uiBoudRate);

  87.     /* (4) Enable USART *********************************************************/
  88.     LL_USART_Enable(USARTx_INSTANCE);

  89.     /* Polling USART initialisation */
  90.     while((!(LL_USART_IsActiveFlag_TEACK(USARTx_INSTANCE))) || (!(LL_USART_IsActiveFlag_REACK(USARTx_INSTANCE))))
  91.     {
  92.     }

  93.     /* Enable RXNE and Error interrupts */
  94.     LL_USART_EnableIT_ERROR(USARTx_INSTANCE);
  95. }

  96. void main(void)
  97. {
  98.    ...
  99.     while(1)
  100.     {
  101.                if (i == iCnt) continue;
  102.              
  103.                __disable_irq();
  104.                       i = iCnt;
  105.                if (pSerialGetByte(&cReadByte))
  106.                      {
  107.                                printf("(%d) - Read(0x%02x)\n", i , cReadByte);
  108.                      }
  109.                      if (USART_ISR_TXE_Msk & USART_FUNCTION_ISR)
  110.                      {
  111.                                        printf("(%d) - USART_ISR_TXE_Msk\n", i );
  112.                      }
  113.                      if (USART_ISR_ORE_Msk & USART_FUNCTION_ISR)
  114.                      {
  115.                                        printf("(%d) - USART_ISR_ORE_Msk\n", i );
  116.                      }
  117.                      if (USART_ISR_FE_Msk & USART_FUNCTION_ISR)
  118.                      {
  119.                                              printf("(%d) - USART_ISR_FE_Msk\n", i );
  120.                      }
  121.                      if (USART_ISR_NE_Msk & USART_FUNCTION_ISR)
  122.                      {
  123.                                              printf("(%d) - USART_ISR_NE_Msk\n", i );
  124.                      }
  125.                      if (USART_ISR_PE_Msk & USART_FUNCTION_ISR)
  126.                      {
  127.                                              printf("(%d) - USART_ISR_PE_Msk\n", i );
  128.                      }
  129.                      __enable_irq();
  130.     }
  131. }
复制代码



收藏 评论3 发布时间:2018-9-3 21:43

举报

3个回答
feixiang20 回答时间:2018-9-3 23:27:08
可能是处理时间已经过载,或是接收标志位没清除之类的配置问题。有人说,出现ORE错误是因为上一帧数据未取走下一帧数据就来了,可以尝试2个方向解决问题:1降低波特率,2,改用DMA方式
奏奏奏 回答时间:2018-9-4 07:06:07
LL_USART_ReceiveData8 这个函数是不是一次只能接收一个字节?
如果是的话,那么问题来了:按照楼主的说法,用串口助手发送一串字符串,如“ABCDEFG”,这是多个字节,如果中断处理函数没有一个字节处理完再打开中断处理 下一个字节,肯定是有问题的。


当我授渔好了,根据 官方 例程“stm32cube_fw_f1_v160.zip”(下载官方软件STM32CubeMX底下搜索路径“STM32Cube\Repository”,L0系列也有自己找
路径下找到自己要的应用例程,例如楼主找 LL库下用 串口中断方式通讯,而且是连续不断的打开中断处理,那么找路径“Cube_FW_F1_V1.6.0\Projects\STM32F103RB-Nucleo\Examples_LL\USART\USART_Communication_Rx_IT_Continuous\MDK-ARM”下点击“Project.uvprojx”打开工程。
官方的串口中断处理回调函数是这样的,参考一下:


  1. void USART_CharReception_Callback(void)
  2. {
  3. uint8_t *ptemp;

  4.   /* Read Received character. RXNE flag is cleared by reading of DR register */
  5.   pBufferReadyForReception[uwNbReceivedChars++] = LL_USART_ReceiveData8(USARTx_INSTANCE);

  6.   /* Checks if Buffer full indication has been set */
  7.   if (uwNbReceivedChars >= RX_BUFFER_SIZE)
  8.   {
  9.     /* Set Buffer swap indication */
  10.     uwBufferReadyIndication = 1;

  11.     /* Swap buffers for next bytes to be received */
  12.     ptemp = pBufferReadyForUser;
  13.     pBufferReadyForUser = pBufferReadyForReception;
  14.     pBufferReadyForReception = ptemp;
  15.     uwNbReceivedChars = 0;
  16.   }
  17. }
复制代码


官方有轮子,就不需要自己造轮子,关注怎么用官方给的轮子去造车子就好了。

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

chifen 回答时间:2018-9-4 08:30:05
__disable_irq(); 不能关闭中断,这样来数据时就会丢失数据

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

所属标签

相似问题

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