请教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();
}
}
可能是处理时间已经过载,或是接收标志位没清除之类的配置问题。有人说,出现ORE错误是因为上一帧数据未取走下一帧数据就来了,可以尝试2个方向解决问题:1降低波特率,2,改用DMA方式 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;
}
}
官方有轮子,就不需要自己造轮子,关注怎么用官方给的轮子去造车子就好了。
__disable_irq(); 不能关闭中断,这样来数据时就会丢失数据
页:
[1]