【蓝桥杯】嵌入式编程_UASRT模块
目录
理论部分
在通信领域内,有两种数据通信方式:并行通信和串行通信。串口的数据传输是以串行方式进行的。串口在数据通信中,一次只能传输一个比特的数据。串行数据的传输速度用bps或波特率来描述每秒传输的二进制位数,单位为bps(bit per second)也称波特率
本次模块USART采用串口通信
串行通信又可分为 单工通信 半双工通信 全双工通信
串行异步通信要素 1.数据位长度 2.有无奇偶位 3.停止位长度 4.波特率
UASRT通信应用场合
CPU与CPU之间通信 芯片(开发板)与PC机之间的通信(printf)(串口调试助手)RS232转换器 ttl 转usb————USART 芯片(开发板)与外围模块之间的通信
(图来源:CT117E-M4产品手册.pdf)
STM32G4系列微控制器参考手册.pdf
分析可知 要想正确搭建USART模块 就要从PA9 与PA10引脚配置入手( 一个为接收 一个发送) 打开相应的USART1 也要注意相应的时钟(RCC) APB2总线使能。
USART如何接收数据?
采用中断接收。
认识中断
中断就是cpu检测到某种信号时 转去执行相应的操作 执行完毕后继续原本的工作 例如 pc向USART发送了数据 USART产生接收中断 cpu转去USART执行相关接收数据工作
不止USART有中断 其他外设也有相应的中断 多个中断在一起 ,就不得不解决谁先去执行的问题 。这就引出了异常向量表&优先级的概念
且看文件startup_stm32g431xx.s
可以看到 内部的中断 (核内)与 扩展的中断
在中断优先级与抢占优先级相等的情况下 芯片会采用 顺序的方式决定谁先去执行。注意要尽量避免中断嵌套(在中断再次使用中断 这样的程序较为复杂不好控制)我们搭建模块的过程中也不需要考虑优先级的问题了 按照默认的来就足够了。
谁来管理中断的使能失能?
NVIC:向量中断控制器 所有和中断有关的操作都由NVIC来管理
使用中断 不得不提文件stm32g4xx_it.c 这里配置了产生中断要执行的函数,不过我们一般才用 回调函数的方式在其他位置写中断函数。
USART模块搭建
1.GPIO引脚
配置复用漏极开路输出
2.USART 配置
模式:异步模式
配置:波特率+数据长度+校验位+停止位
3.开启USART中断
4.相关时钟配置
注意!由于重新配置了rcc 待会要覆盖掉原先的时钟配置函数代码
5.Keil5预配置
1)双击Drivers添加相关库文件
2)头文件main.h跟过去 --->stm32g4xx_hal.h --->stm32g4xx_hal_conf--->stm32g4xx_hal_conf.h 将相关头文件定义注释消掉
6.代码移植
将新生成的 在Src文件下的usart.c复制到 目标Src文件下 头文件usart.h复制到相应\Inc下
main.c 要包含头文件usart.h #include "usart.h"
在文件下stm32g4xx_it.c添加该usart的中断配置
/* External variables --------------------------------------------------------*/
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN 1 */
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
函数SystemClock_Config() 要覆盖掉
7.程序设计文件参考
mian.c
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "usart.h"
//设置周期的变量
__IO uint32_t uwTick_uart;
void uart_proc(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_USART1_UART_Init();
sprintf(&UART_string[0],"欢迎使用uart\n");
HAL_UART_Transmit(&huart1, (uint8_t *)UART_string,strlen(UART_string),50);
//*串口接收中断打开 接收长度为1
HAL_UART_Receive_IT(&huart1,&UART_Receive,1);
while (1)
{
uart_proc();
}
}
void uart_proc(void)
{
if((uwTick-uwTick_uart)<500) return;
uwTick_uart = uwTick;
if(counter == 7)//接收7个数据 产生7此中断
{
sprintf(UART_string, "success:%s\r\n",&UART_REceive[0]);
HAL_UART_Transmit(&huart1,(unsigned char *)UART_string, strlen(UART_string), 50);
counter = 0;
}
// sprintf(&UART_string[0],"hello world\n");
// HAL_UART_Transmit(&huart1, (uint8_t *)UART_string,strlen(UART_string),50);
}
usart.c
#include "usart.h"
/* USER CODE BEGIN 0 */
char UART_string[40];
uint8_t UART_REceive[8]={0};
uint8_t UART_Receive;
uint8_t counter = 0;
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/*由CubeMx自动生成 无需修改*/
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
/*由CubeMx自动生成 无需修改*/
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
/*由CubeMx自动生成 无需修改*/
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/*相应的中断配置函数 接收个字符*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UART_REceive[counter] = UART_Receive;
counter++;
HAL_UART_Receive_IT(&huart1,&UART_Receive,1);
}
/* USER CODE END 1 */
uart.h
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
extern char UART_string[40];
extern uint8_t UART_REceive[8];
extern uint8_t UART_Receive;
extern uint8_t counter;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */
8.串口调试工具测试
UART接收特定字符练习
现实现
1.uart 接收6个数字字符 其他字符返回error
void uart_fun(void)
{
if(uwTick-uwTick_uart<300) return;
uwTick_uart=uwTick;
if(uart_counter==6){
for(int i =0;i<6;i++)
{
int rex =uart_Rx[i]-'0';
if(rex<0||rex>9)
{
sprintf((char *)&uart_string[0],"error \n");
HAL_UART_Transmit(&huart1,(uint8_t *)&uart_string[0],strlen((char *)&uart_string[0]),20);
uart_counter=0;
HAL_UART_Receive_IT(&huart1,(unsigned char *)&uart_code,1);
return;
}
}
//
sprintf((char *)&uart_string[0],"successful:%s \n",&uart_Rx[0]);
HAL_UART_Transmit(&huart1,(uint8_t *)&uart_string[0],strlen((char *)&uart_string[0]),20);
uart_counter=0;
HAL_UART_Receive_IT(&huart1,(unsigned char *)&uart_code,1);
}
}
2.uart 接收6个字母 前3个字母为大写 后3个字母为小写字母 其他字符返回error
void uart_fun(void)
{
if(uwTick-uwTick_uart<300) return;
uwTick_uart=uwTick;
if(uart_counter==6){
for(int i =0;i<3;i++)
{
//int rex =uart_Rx[i]-'0';
if(uart_Rx[i]<'A'||uart_Rx[i]>'Z')
{
sprintf((char *)&uart_string[0],"error \n");
HAL_UART_Transmit(&huart1,(uint8_t *)&uart_string[0],strlen((char *)&uart_string[0]),20);
uart_counter=0;
HAL_UART_Receive_IT(&huart1,(unsigned char *)&uart_code,1);
return;
}
}
for(int i =3;i<6;i++)
{
//int rex =uart_Rx[i]-'0';
if(uart_Rx[i]<'a'||uart_Rx[i]>'z')
{
sprintf((char *)&uart_string[0],"error \n");
HAL_UART_Transmit(&huart1,(uint8_t *)&uart_string[0],strlen((char *)&uart_string[0]),20);
uart_counter=0;
HAL_UART_Receive_IT(&huart1,(unsigned char *)&uart_code,1);
return;
}
}
sprintf((char *)&uart_string[0],"successful:%s \n",&uart_Rx[0]);
HAL_UART_Transmit(&huart1,(uint8_t *)&uart_string[0],strlen((char *)&uart_string[0]),20);
uart_counter=0;
HAL_UART_Receive_IT(&huart1,(unsigned char *)&uart_code,1);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」