STM32CubeMx软件设置
首先选好自己的板子并打开软件设置,本实验基于STM32F103ZET6实现,打开软件后如图:
打开外部高速晶振,然后接着配置时钟:
将时钟频率修改为72MHz,接着设置接线方式为SW
接下来需要使用串口中断通讯,打开我们的串口设置并打开中断
这里波特率设置为115200,数据位为8位,无校验位,停止位为1位,通信模式设置为异步通信,以及可以接受及发送数据。
接着打开中断,并设置抢占优先级和响应优先级,这里设置为0,0。
至此STM32CubeMx就设置完成了。
Keil软件及代码编写
打开Keil以后生成以下文件:
这里的uart.c是我自己编写的,方便后续管理,我们先来看看usart.c中的初始化函数:
分别有两个函数,一个设置我们的串口相关功能,一个则是打开我们所需要功能的时钟、配置相应的IO口,以及打开中断。
接下来看中断的相关处理
Hal库的中断处理函数都会放在这个it.c文件中,然后函数内部会调用关于串口的中断公共处理函数,并且会在里面失能中断,所以添加一个while重新使能中断。
关于函数的快速查找可以点击左边窗口下方的functions打开对应的文件就能找到我们所需的函数:
接着通过跳转功能进入中断的公共处理函数,并找到对应的中断回调函数,即:
这里是一个弱定义,里面是空,即用户需要使用到时可以自己进行改写,所以下一步就是来编写所需要的功能:
串口的功能设计
uart.h编写
#ifndef __UART_H
#define __UART_H
#include "usart.h"
#define uart_len 200
#define hal_uart_len 1
extern uint8_t g_rx[uart_len]; //存放字符串数组
extern uint8_t g_rx_buffer[hal_uart_len]; //HAL库用存放缓存区
/* 存放数据标志位
以回车换行符进行判断接收完毕
15位置1表示接收到换行符,14位置1表示接收到回车
*/
extern uint16_t g_usart1_rx_sta;
#endif
uart.c编写
uint8_t g_rx[uart_len]; //存放字符串数组
uint8_t g_rx_buffer[hal_uart_len]; //HAL库用存放缓存区
uint16_t g_usart1_rx_sta = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if((g_usart1_rx_sta & 0x8000) == 0) //判断标志位15位是否被置1,若为0则接受还没结束
{
if(g_usart1_rx_sta & 0x4000) //判断标志位14位是否被置1
{
if(g_rx_buffer[0] != 0x0a)
{
g_usart1_rx_sta = 0; //若接收到回车后下一位不为换行则接收失败
}
else
{
g_usart1_rx_sta |= 0x8000;
}
}
else
{
if(g_rx_buffer[0] == 0x0d) //判断缓存器中当前是否接收到回车
{
g_usart1_rx_sta |= 0x4000;
}
else
{
//数据转移
g_rx[g_usart1_rx_sta & 0x3fff] = g_rx_buffer[0];
g_usart1_rx_sta++;
//超出数组存放上限
if(g_usart1_rx_sta > (uart_len-1))
{
g_usart1_rx_sta = 0;
}
}
}
}
}
这里通过设定一个g_usart1_rx_sta标志位来判断接收到的数据有多长,这里设定字符串加上回车就代表发送完成,即需要判断是否收到\r\n来判断接收是否终止。\r的ascii值为0x0d,\n的ascii值为0x0a。
主函数的编写
/* USER CODE BEGIN 2 */
//接收数据使能中断
HAL_UART_Receive_IT(&huart1, (uint8_t*)g_rx_buffer, hal_uart_len);
uint8_t len = 0;
uint16_t time = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (g_usart1_rx_sta & 0x8000) /* 接收到了数据? */
{
len = g_usart1_rx_sta & 0x3fff; /* 得到此次接收到的数据长度 */
printf("\r\n您发送的消息为:\r\n");
HAL_UART_Transmit(&huart1,(uint8_t*)g_rx, len, 1000); /* 发送接收到的数据 */
while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC) != SET); /* 等待发送结束 */
printf("\r\n\r\n"); /* 插入换行 */
g_usart1_rx_sta = 0;
}
else
{
time++;
if (time % 5000 == 0)
{
printf("\r\n串口实验\r\n");
}
if (time % 200 == 0) printf("请输入数据,以回车键结束\r\n");
HAL_Delay(10);
}
}
/* USER CODE END 3 */
这里是需要使用到串口中断接收,所以我们第一步是需要使能我们的串口中断接收,即下面这个函数:
HAL_UART_Receive_IT(&huart1, (uint8_t*)g_rx_buffer, hal_uart_len);
这个函数的第一个参数是句柄,也就是对应的初始化串口的结构体,可在usart.c中找到,第二个参数是接收的缓冲寄存器,即用户自己设定的寄存器,第三个则是接收长度。
然后接收完成后,通过len参数判断接收到的长度,在通过发送函数将数据发送回去,即下面这个函数:
HAL_UART_Transmit(&huart1,(uint8_t*)g_rx, len, 1000);
这个函数的参数跟使能中断接收差不多,多了最后一个参数为超时时间,同时这个函数为阻塞发送,即数据没发送完就会一直发送无法处理其他事情。
同时还在这个主函数中添加了printf函数代表我们的STM32正常工作,需要用到这个printf函数我们就需要在usart.c中添加一个重定向函数:
/* USER CODE BEGIN 1 */
//串口打印重定向
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/* USER CODE END 1 */
添加完成后再包含stdio.h头文件即可。文章来源:https://www.toymoban.com/news/detail-704816.html
效果实现
文章来源地址https://www.toymoban.com/news/detail-704816.html
到了这里,关于基于STM32F1以及STM32CubeMx实现串口中断通讯(字符串发送与接收)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!