前言:
在整个蓝桥杯考试中涉及串口的次数还是较多,这里写下这篇博客,记录一下自己的学习过程。
STM32Cubemx配置:
首先,我们点击左侧的Connectivity选择USART1进行如下配置。
使能串口中断
在左侧的管脚配置上也要做出修改
到此为止,我们就配置完了,点击生成代码即可。
代码部分:
发送的代码:
我是直接将上一篇博客采集到的电压值直接发送给了串口助手。
首先在main.c中引入头文件string.h,并定义一个数组专门用来存储要发送的数据
#include "string.h"
char temp[20]; //定义数组,用来发送串口数据
将发送代码放到主循环中
sprintf(temp,"ADC_value:%.2f\r\n",adc_value1);
HAL_UART_Transmit(&huart1,(unsigned char *)temp,strlen(temp),50);
最终效果
接收部分:
接收部分最重要的就是串口中断回调函数,这个函数的位置在stm32g4xx_hal_uart.h里面,在1632行的位置(如果记不住,就记1600多行的位置)
我们新建一个文件,叫做myusart.c里面写一下我们的中断服务函数
char rxdata[20];
unsigned char rxdat;
unsigned char rx_pointer;
char car_type[5];
char car_num[5];
char car_time[13];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rxdata[rx_pointer++] = rxdat; //++在后面,是先用,在自加
HAL_UART_Receive_IT(&huart1,&rxdat,1);
}
void uart_rx_proc()
{
if(rx_pointer > 0) //大于0说明接收到数据
{
if(rx_pointer == 22) //判断是否接收成功
{
sscanf(rxdata,"%4s:%4s:%12s",car_type,car_num,car_time);//对接收的数据进行解析
}
else//发生错误输出Error
{
char temp[10];
sprintf(temp,"Error\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);
}
rx_pointer = 0; //指针归位
memset(rxdata,0,sizeof(rxdata)); //初始化为0
}
}
我们再同样定义一个myusart.h的文件
#ifndef __MYUSART_H
#define __MYUSART_H
#include "main.h"
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void uart_rx_proc(void);
extern char car_type[5];
extern char car_num[5];
extern char car_time[13];
#endif
我们只需要在main.c的while新婚换里面调用以下代码即可完成串口的接收
if(rx_pointer != 0)
{
int media = rx_pointer;
HAL_Delay(1);
if(media == rx_pointer) uart_rx_proc();
}
我们简单的显示一下:
sprintf(text,"car_type:%s",car_type);
LCD_DisplayStringLine(Line5,(uint8_t *)text);
sprintf(text,"car_num:%s",car_num);
LCD_DisplayStringLine(Line6,(uint8_t *)text);
sprintf(text,"tim:%s",car_time);
LCD_DisplayStringLine(Line7,(uint8_t *)text);
最终效果实现:
补发:
这里我曾经出现了一个小BUG,在这里记录一下,就是无论如何在发送数据的时候,不要人为的给数据加上\r\n,因为这个串口助手的界面不如原子哥的界面,所以我经常使用正点原子提供的串口助手,在使用这个串口助手的时候,我会不经意间加上“\r\n”,所以代码就会出现一些BUG,而蓝桥杯官方提供的串口助手就不会出现这个问题,因为你没办法加上回车。而且在判断接收字符的代码中,我们一般不把'\r\n''计入字符串的总数,这点一定要注意。比如这里
这里我就设定的字符数据是22个。
此外,还有一个小BUG,就是有时候我发现串口接收到的数据最后一位始终为0,这个让我百思不得其解,最后在调试的时候,我发现了问题所在 用来接收数据的字符设定的少了一些, 所以导致最后一位始终为0。
接收不定长数据
这里我用的写法非常简单,仅仅用作记录自己的学习过程
#include "myusart.h"
#include "string.h"
#include "usart.h"
#include "stdio.h"
char temp[20];//用来发送数据的字符串
char rxdata[20];//用来接收数据的字符串
unsigned char rxdat;
unsigned char rx_point;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rxdata[rx_point++] = rxdat;
HAL_UART_Receive_IT(&huart1,&rxdat,1);
}
void RX_process(void)
{
if(rx_point > 0) //如果接收到数据
{
if(rxdata[rx_point] == '\0')
{
sprintf(temp,"ok\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50);
}
rx_point = 0; //指针归位
memset(rxdata,0,sizeof(rxdata)); //初始化为0
}
}
void uart_process()
{
if(rx_point != 0)
{
int media = rx_point;
HAL_Delay(1);
if(media == rx_point)RX_process();
}
}
通过判断字符串最后一位是不是‘\0’,来确定字符串是否发送完毕,如果发送完毕的话,再给串口助手回馈‘ok\r\n’。
接收指定的数据:
这里我通过发送指定样式的数据,在LCD上显示,使用sscanf函数可以对发送过来的数据进行分割,strcmp函数多是用来对比两个字符串的内容,我这里写的功能是如果串口助手发送的是light那么我就让LED进行闪烁。
void uart_process(void)
{
if(rx_point > 0) //如果有数据传过来
{
if(rxdata[rx_point] == '\0')
{
sprintf(temp,"ok\r\n");
HAL_UART_Transmit(&huart1,(unsigned char*)temp,strlen(temp),50);
if(strcmp(led_command,rxdata)==0)
{
light_flag = !light_flag;
}
if(rx_point == 12)
{
sscanf(rxdata,"A:%dB:%dC:%d",&A,&B,&C);
}
}
rx_point = 0;
memset(rxdata,0,sizeof(rxdata));
}
}