文章

蓝桥杯嵌入式外设开发记录 - 串口通信

本文记录了学习蓝桥杯嵌入式开发过程中的串口通信的记录

蓝桥杯嵌入式外设开发记录 - 串口通信

蓝桥杯嵌入式外设开发记录 - PWM输出&输入捕获

基本信息

项目 内容
开发板型号 CT117E(STM32G431RBT6)
开发环境 STM32CubeMX 6.6.1, Keil uVision5 MDK 5.38
记录日期 2025-3-4

1.CubeMX 配置

2.基础代码

发送函数(初始化时需要在main内加入一句作为使能):

1
HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)

接收中断回调:

1
2
3
4
5
6
7
8
9
10
uint8_t rec_data;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        HAL_UART_Transmit(huart,&rec_data,1,50);
        HAL_UART_Receive_IT(huart,&rec_data,1);
    }

}

3.串口接收不定长数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
uint8_t rx_data,count;
bool rx_flag;
char rx_buff[40];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        TIM4->CNT = 0;
        rx_flag =1;
        rx_buff[count] = rx_data;
        count++;
        HAL_UART_Receive_IT(huart,&rx_data,1);
    }

}
const char* txt = "lan";
const char* Er = "Error\n";
void uart_data_rx()
{
    if(rx_flag)
    {
        if(TIM4->CNT >= 15)
        {
            rx_buff[count] = '\0';
            if(strcmp(rx_buff,txt) == 0)
            {
               HAL_UART_Transmit(&huart1,(uint8_t *)rx_buff,strlen(rx_buff),50);
            }
            else
            {

                HAL_UART_Transmit(&huart1,(uint8_t *)Er,strlen(Er),50);


            }
            rx_flag=0;
            memset(rx_buff,0,40);
            count =0;
        }
    }
}

\(CNT一个计数:CNT_{1} = \frac{1}{\frac{Freq}{PSC+1}} = \frac{1}{\frac{80\text{MHz}}{8000}} = \frac{1}{10\text{kHz}} = 0.1\text{ms}\)

2>使用串口中断+DMA+空闲中断来实现

加入新方法

1
2
3
4
5
6
7
8
9
10
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if(huart->Instance == USART1)
    {
        HAL_UART_DMAStop(huart);
        rx_flag =1;
        rx_Size = Size;
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1,(u8 *)rxbuff,128);
    }
}

在初始化时使用 HAL_UARTEx_ReceiveToIdle_DMA(&huart1,(u8 *)rxbuff,128);打开接收

以下方法为旧方法,不推荐使用》》》》

stm32g4xx_it.c中加入以下代码 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//用户自定义中断
void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
{
    if(__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE))
    {
        __HAL_UART_CLEAR_IDLEFLAG(huart);//清除空闲中断
        USER_UART_IDLE_CallBack(huart); //用户回调,在需要的地方定义并编写

    }
}
//找到以下函数 并加入
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
    USER_UART_IRQHandler(&huart1); /////用户自定义中断
  /* USER CODE END USART1_IRQn 1 */
}

定义并编写void USER_UART_IDLE_CallBack(UART_HandleTypeDef *huart);PS:必须要和用户中断内的回调名一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
char rx_buff[128];
void USER_UART_IDLE_CallBack(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        HAL_UART_DMAStop(huart);
       // rx_buff[strlen(rx_buff)] = '\0';
       HAL_UART_Transmit(huart,(uint8_t *)rx_buff,strlen(rx_buff),50);
       memset(rx_buff,0,128);
        HAL_UART_Receive_DMA(huart,(uint8_t *)rx_buff,128);
    }



}

最后在主函数内初始化

__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);

HAL_UART_Receive_DMA(&huart1,(uint8_t *)rx_buff,128);

注意:上面两个函数下不应该有HAL库的函数 否则会出现初始化后进入一次串口中断

本文由作者按照 CC BY 4.0 进行授权