在STM32F103中使用空闲中断的时候,经常会出现丢数据的情况,我猜测是因为连接环境中有延时,造成标志位误触发的情况。
解决思路,直接使用LL库代替HAL库,不用DMA也不用空闲中断,用最原始的办法就是直接接收中断触发的方式做。
使用定时器1,用于接收延时处理,达到不定长字符串接收的目的。
1,CUBEMX配置
不用DMA
中断勾选
定时器配置
2 部分工程代码
需要定义的变量
#define DEBUG 1
#define ERROR_LOG(x) if(DEBUG)printf("error_%d:%s.\r\n",__LINE__,x);
#ifndef NULL
#define NULL ((void*)0)
#endif
//用于包缓冲或者组包的Buf
#define BUFFER_SIZE 256
int8_t S1recvEnd=0;
int8_t S1TimeOut=0;
int16_t S1recvLen=0;
int8_t S2recvEnd=0;
int8_t S2TimeOut=0;
int16_t S2recvLen=0;
int8_t S3recvEnd=0;
int8_t S3TimeOut=0;
int16_t S3recvLen=0;
uint8_t mS1SendBuf[BUFFER_SIZE];
uint8_t mS1RecvBuf[BUFFER_SIZE];
uint8_t mS2SendBuf[BUFFER_SIZE];
uint8_t mS2RecvBuf[BUFFER_SIZE];
uint8_t mS3SendBuf[BUFFER_SIZE];
uint8_t mS3RecvBuf[BUFFER_SIZE];
void TestUsartRecvTask(void const * argument)
{
//串口初始化
LL_USART_EnableIT_RXNE(USART1);
LL_USART_EnableIT_PE(USART1);
LL_USART_EnableIT_RXNE(USART2);
LL_USART_EnableIT_PE(USART2);
LL_USART_EnableIT_RXNE(USART3);
LL_USART_EnableIT_PE(USART3);
//定时器开中断
HAL_TIM_Base_Start_IT(&htim1);
//I2C_Init();
while(1)
{
if(S1recvEnd)
{
S1recvEnd = 0;
USART_SendData(USART1,mS1RecvBuf,S1recvLen);
HAL_GPIO_WritePin(RS485_DE3_GPIO_Port,RS485_DE3_Pin,GPIO_PIN_SET);
USART_SendData(USART3,mS1RecvBuf,S1recvLen);
HAL_GPIO_WritePin(RS485_DE3_GPIO_Port,RS485_DE3_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(RS485_DE2_GPIO_Port,RS485_DE2_Pin,GPIO_PIN_SET);
USART_SendData(USART2,mS1RecvBuf,S1recvLen);
HAL_GPIO_WritePin(RS485_DE2_GPIO_Port,RS485_DE2_Pin,GPIO_PIN_RESET);
//HAL_UART_Transmit(&huart1,mS1RecvBuf,S1recvLen,0xFFFFFFFF);
//HAL_UART_Receive_DMA(&huart1,mS1RecvBuf,BUFFER_SIZE);
S1recvLen = 0;
}
if(S2recvEnd)
{
S2recvEnd = 0;
USART_SendData(USART1,mS2RecvBuf,S2recvLen);
//HAL_UART_Transmit(&huart1,mS2RecvBuf,S2recvLen,0xFFFFFFFF);
//HAL_UART_Receive_DMA(&huart2,mS2RecvBuf,BUFFER_SIZE);
S2recvLen =0;
}
if(S3recvEnd)
{
S3recvEnd = 0;
USART_SendData(USART1,mS3RecvBuf,S3recvLen);
//HAL_UART_Transmit(&huart1,mS3RecvBuf,S3recvLen,0xFFFFFFFF);
//HAL_UART_Receive_DMA(&huart3,mS3RecvBuf,BUFFER_SIZE);
S3recvLen = 0;
}
ReadSensor();
//HAL_Delay(1000);
}
//HAL_Delay(10);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==&htim1)
{
static uint32_t timeLed=1000;
static GPIO_PinState msate = GPIO_PIN_RESET;
if(msate)msate = GPIO_PIN_RESET;
else msate = GPIO_PIN_SET;
if(timeLed--==0)
{
timeLed = 1000;
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,msate);
}
if(S1TimeOut)S1TimeOut--;
else if(S1recvLen>1)
{
S1recvEnd =1;
}
if(S2TimeOut)S2TimeOut--;
else if(S2recvLen>1)
{
S2recvEnd =1;
}
if(S3TimeOut)S3TimeOut--;
else if(S3recvLen>1)
{
S3recvEnd =1;
}
//HAL_UART_Transmit(&huart1,"heesl",5,20);
//printf("m\r\n");
}
}
void USART_SendData(USART_TypeDef *uart,uint8_t *tmpData,int16_t len)
{
int16_t iLen=0;
for(iLen=0;iLen
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if(LL_USART_IsActiveFlag_RXNE(USART1))
{
S1TimeOut =UART_TIMEOUT;
mS1RecvBuf[S1recvLen] = LL_USART_ReceiveData8(USART1);
//LL_USART_TransmitData8(USART1,mS1RecvBuf[S1recvLen]);
S1recvLen++;
if(S1recvLen >=BUFFER_SIZE)S1recvLen=0;
//LL_USART_TransmitData8(USART1,tmp);
}
/* USER CODE END USART1_IRQn 0 */
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
/**
* @brief This function handles USART2 global interrupt.
*/
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
if(LL_USART_IsActiveFlag_RXNE(USART2))
{
S2TimeOut =UART_TIMEOUT;
if(S2recvLen >=BUFFER_SIZE)S2recvLen=0;
mS2RecvBuf[S2recvLen++] = LL_USART_ReceiveData8(USART2);
//LL_USART_TransmitData8(USART1,tmp);
}
/* USER CODE END USART2_IRQn 0 */
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
if(LL_USART_IsActiveFlag_RXNE(USART3))
{
S3TimeOut =UART_TIMEOUT;
if(S3recvLen >=BUFFER_SIZE)S3recvLen=0;
mS3RecvBuf[S3recvLen++] = LL_USART_ReceiveData8(USART3);
//LL_USART_TransmitData8(USART1,tmp);
}
/* USER CODE END USART3_IRQn 0 */
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
大致思路就是: 产生中断--》缓存-》定时器检查》超时接收完成。
完整工程