系列文章目录
文章目录
目录
前言
本文主要涉及到常规的定长数据接收和使用串口空闲中断来实现的不定长数据接收
定长数据接收
一、创建工程
最开始依旧是选择芯片型号、配置时钟树、debug等,具体操作可跳到LED一文查看
本文主要涉及串口的配置
老规矩,查看手册,蓝桥杯嵌入式开发板的串口1是接在PA9、PA10的,但是注意G431的默认串口1并不是PA9、PA10,所以一定记得修改串口引脚!!!
串口配置成异步模式,波特率本文使用115200作测试,蓝桥杯一般要求9600,根据要求选择
记得打开串口的中断,至于优先级,根据实际情况设定,本文使用默认优先级,配置完成后生成keil工程
二、代码编写
1.串口接收中断回调函数
此函数为HAL库中的弱函数,用户可重写该函数来编写接收后需要实现的功能,其中用到了一些C语言库函数,如sprintf、strncmp,具体用法可自行了解,此处仅简单介绍
sprintf(),与printf类似,只是将输出打印到一个字符数组
strcmp(),其中三个参数str1,str2,n分别为字符串1,字符串2,比较的长度,如果相等返回0
该函数主要实现当串口接收数据为LED1时,翻转LED1的电平,且通过串口发送LED1当前的电平状态,若接收其他字符则返回ERROR
其中HAL_UART_Receive_IT(&huart1,(uint8_t *)rx_buffer,sizeof(rx_buffer));须在初始化时调用一次
uint8_t rx_buffer[4];
char temp[20];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//如果是串口1触发的中断
if(huart == &huart1)
{
if(strncmp((char *)rx_buffer,"LED1",4) == 0)
{
HAL_GPIO_TogglePin(GPIOC,LED1_Pin);
sprintf(temp,"LED_PinLevel:%d\n",HAL_GPIO_ReadPin(GPIOC,LED1_Pin));
HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),0xffff);
}
else
{
HAL_UART_Transmit(&huart1,(uint8_t *)"ERROR\n",strlen("ERROR\n"),0xffff);
}
//再次调用
HAL_UART_Receive_IT(&huart1,(uint8_t *)rx_buffer,sizeof(rx_buffer));
}
}
2.现象
串口接收定长数据
串口+DMA+空闲中断接收不定长数据
1.串口空闲中断
串口在空闲时,也就是说串口在一段时间里没有接收到新数据,则会触发空闲中断,且空闲中断不会在没有数据时触发,也就是说,空闲中断触发必须是已经接收到数据,然后在一段时间内没有数据继续发进来,则会触发空闲中断,此时认为一帧数据接收完成
2.串口配置
相对于上面的配置,主要是多了DMA的配置
数据长度:由于串口数据发送寄存器只能存储8bit,每次发送一个字节,所以数据长度选择Byte
3.代码编写
串口接收处理函数,此函数实现的功能是把接收到的字符串再发送给上位机
extern DMA_HandleTypeDef hdma_usart1_rx;
void uart_handle(void)
{
uint8_t len;
//如果空闲中断标志位被置位
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET)
{
//清除空闲中断标志位
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
//停止DMA传输
HAL_UART_DMAStop(&huart1);
//获取接收字符长度
len = 100 - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
//发送接收到的字符串
HAL_UART_Transmit(&huart1,(u8 *)rx_buffer,len,0xffff);
}
//再次调用
HAL_UART_Receive_DMA(&huart1,(uint8_t *)rx_buffer,100);
}
此函数在stm32g4xx_it.c中的串口1中断处理函数中调用,所有该函数其实就是中断所要实现的功能,逻辑就在这个函数中编写
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
uart_handle();
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
由于CubeMX生成的工程中并没有使能空闲中断(IDIE),所以我们还要在usart.c里面,找到
MX_USART1_UART_Init函数,在用户代码位置加上空闲中断的使能和初次DMA传输的开启
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
//使能空闲中断
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
//开启DMA传输
HAL_UART_Receive_DMA(&huart1,(uint8_t *)rx_buffer,100);
/* USER CODE END USART1_Init 2 */
}
以上就是有关空闲中断实现的代码以及使能的相关代码
现象
串口接收不定长数据
总结
以上就是关于蓝桥杯串口的使用,本文简单介绍了常规的定长数据接收以及串口+DMA+空闲中断实现不定长数据的接收