xhx321 发表于 2018-9-3 21:43:13

请教USART接收的问题

现在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):

void USARTx_IRQHandler(void)
{
        iCnt++;
        USART_FUNCTION_ISR = 0;          
        if (LL_USART_IsActiveFlag_RXNE(USARTx_INSTANCE) && LL_USART_IsEnabledIT_RXNE(USARTx_INSTANCE))
        {
                uiRxByte = (uint32_t)LL_USART_ReceiveData8(USARTx_INSTANCE);
                //LL_USART_TransmitData8(USARTx_INSTANCE, (uint8_t) uiRxByte);
                  //LL_USART_TransmitData8(USARTx_DEBUG_INSTANCE, (uint8_t) uiRxByte);
                  //printf("(%d)-rev(0x%02x)\n",iCnt, uiRxByte);
                USART_FUNCTION_ISR |= USART_ISR_RXNE_Msk;

        }
        if (LL_USART_IsActiveFlag_TXE(USARTx_INSTANCE) && LL_USART_IsEnabledIT_TXE(USARTx_INSTANCE))
        {
                   USART_FUNCTION_ISR |= USART_ISR_TXE_Msk;
                   //printf ("(%d)-USARTx_IRQHandler-LL_USART_IsActiveFlag_TXE\n",iCnt);
        }
        if (LL_USART_IsActiveFlag_ORE(USARTx_INSTANCE))
        {
                   //printf("(%d)-OVERUN happened\n",iCnt);
                   LL_USART_ClearFlag_ORE(USARTx_INSTANCE);
                      LL_USART_ReceiveData8(USARTx_INSTANCE);
                   USART_FUNCTION_ISR |= USART_ISR_ORE_Msk;
        }
        if (LL_USART_IsActiveFlag_NE(USARTx_INSTANCE))
        {
                      //printf("(%d)-Noise detected\n", iCnt);
                   LL_USART_ClearFlag_NE(USARTx_INSTANCE);
                      //LL_USART_ReceiveData8(USARTx_INSTANCE);
                   USART_FUNCTION_ISR |= USART_ISR_NE_Msk;
        }
        if (LL_USART_IsActiveFlag_FE(USARTx_INSTANCE))
        {
                   //printf("(%d)-Frame Error\n",iCnt);
                   LL_USART_ClearFlag_FE(USARTx_INSTANCE);
                      //LL_USART_ReceiveData8(USARTx_INSTANCE);
                   USART_FUNCTION_ISR |= USART_ISR_FE_Msk;
        }
        if (LL_USART_IsActiveFlag_PE(USARTx_INSTANCE))
        {
       //printf("(%d)-Parity Error\n",iCnt);
                   LL_USART_ClearFlag_PE(USARTx_INSTANCE);
                      //LL_USART_ReceiveData8(USARTx_INSTANCE);
                   USART_FUNCTION_ISR |= USART_ISR_PE_Msk;
        }
}

void USART_Init(       \
      uint32_t uiBoudRate,\
      uint32_t uiDataWidth, \
      uint32_t uiParity,    \
      uint32_t uiStopBits)
{
    //TODO: Parameters checking

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

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

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

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

    /* (2) NVIC Configuration for USART interrupts */
    /*- Set priority for USARTx_IRQn */
    /*- Enable USARTx_IRQn */
    NVIC_SetPriority(USARTx_IRQn, 0);
    NVIC_EnableIRQ(USARTx_IRQn);

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

    /* Set clock source */
    USARTx_CLK_SOURCE();

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

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

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

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

    LL_USART_SetBaudRate(USARTx_INSTANCE, SystemCoreClock, LL_USART_OVERSAMPLING_16, uiBoudRate);

    /* (4) Enable USART *********************************************************/
    LL_USART_Enable(USARTx_INSTANCE);

    /* Polling USART initialisation */
    while((!(LL_USART_IsActiveFlag_TEACK(USARTx_INSTANCE))) || (!(LL_USART_IsActiveFlag_REACK(USARTx_INSTANCE))))
    {
    }

    /* Enable RXNE and Error interrupts */
    LL_USART_EnableIT_ERROR(USARTx_INSTANCE);
}

void main(void)
{
   ...
    while(1)
    {
               if (i == iCnt) continue;
           
               __disable_irq();
                  i = iCnt;
               if (pSerialGetByte(&cReadByte))
                   {
                               printf("(%d) - Read(0x%02x)\n", i , cReadByte);
                   }
                   if (USART_ISR_TXE_Msk & USART_FUNCTION_ISR)
                   {
                                       printf("(%d) - USART_ISR_TXE_Msk\n", i );
                   }
                   if (USART_ISR_ORE_Msk & USART_FUNCTION_ISR)
                   {
                                       printf("(%d) - USART_ISR_ORE_Msk\n", i );
                   }
                   if (USART_ISR_FE_Msk & USART_FUNCTION_ISR)
                   {
                                           printf("(%d) - USART_ISR_FE_Msk\n", i );
                   }
                   if (USART_ISR_NE_Msk & USART_FUNCTION_ISR)
                   {
                                           printf("(%d) - USART_ISR_NE_Msk\n", i );
                   }
                   if (USART_ISR_PE_Msk & USART_FUNCTION_ISR)
                   {
                                           printf("(%d) - USART_ISR_PE_Msk\n", i );
                   }
                   __enable_irq();
    }
}


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”打开工程。
官方的串口中断处理回调函数是这样的,参考一下:


void USART_CharReception_Callback(void)
{
uint8_t *ptemp;

/* Read Received character. RXNE flag is cleared by reading of DR register */
pBufferReadyForReception = LL_USART_ReceiveData8(USARTx_INSTANCE);

/* Checks if Buffer full indication has been set */
if (uwNbReceivedChars >= RX_BUFFER_SIZE)
{
    /* Set Buffer swap indication */
    uwBufferReadyIndication = 1;

    /* Swap buffers for next bytes to be received */
    ptemp = pBufferReadyForUser;
    pBufferReadyForUser = pBufferReadyForReception;
    pBufferReadyForReception = ptemp;
    uwNbReceivedChars = 0;
}
}

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

chifen 发表于 2018-9-4 08:30:05

__disable_irq(); 不能关闭中断,这样来数据时就会丢失数据
页: [1]
查看完整版本: 请教USART接收的问题