STM32CubeMX串口通信调试避坑(胎教级教程)

2024-03-07 17:58

本文主要是介绍STM32CubeMX串口通信调试避坑(胎教级教程),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CubeMX 的下载还有安装的避坑上篇文章写了,有兴趣的可以去看,这里就直接用了。

我的平台是STM32F407ZG,其他平台同理,没什么太大区别。好了,正片开始。

这篇主要是UART通信,首先要配置外部晶振,我这里是25Mhz的外部晶振

在这里插入图片描述
这里因为我要用到网络部分,所以就先打开了Master Clock Output,因为网络模块没有使用独立的50MHZ晶振,所以使用STM32的MCO2输出50Mhz来驱动网口正常工作,也可以用MCO1。这里的详细倍频分频选择网口模块的配置再详细说明。不需要MCO输出频率的可以不勾选Master Clock Output。

在这里插入图片描述
这里也设置一下SYS,虽然没太理解到底干啥,但是有用,预设一下,别忘记了,这个太容易忘记了,因为这段话是我回过头来补上的。

在这里插入图片描述

接下来就是USART1的配置,这里选择Asynchronous异步通信模式,然后打开中断

在这里插入图片描述
接下来需要注意一个地方,就是GPIO口设置

在这里插入图片描述

在这里一定要检查GPIO是不是和原理图对应的引脚一致,因为在软件设置多个功能之后再来设置UART串口时,可能会去复用其他一些引脚来实现UART功能。我就遇到了这个情况,想当然的以为引脚会自动选择最常见的PA9 PA10。这里一定要检查是不是对应上了

如果没有对应上,那么就要去手动修改

在这里插入图片描述
一定要是打开了这个异步通信模式之后再去找自己原理图对应的IO口

这里UART串口的频率我就使用的默认115200

在这里插入图片描述
来到时钟树的配置界面,先自动选择一下子

在这里插入图片描述
这里是M=25 N=300 P=2,也就是先分频25,然后倍频300,最后再分频2,得到了PLLCLK频率为150Mhz,因为我这个板子需要MCO2输出50Mhz才把PLLCLK拉到了150Mhz,一般情况可以是168Mhz,这个比较常见,也是F407的最大频率,具体怎么算到168Mhz方法同上。

在这里插入图片描述

目录一定是纯英文,这样不会出错。然后IDE也别忘了选择Keil软件,还有对应的版本。

在这里插入图片描述

第一点是这里可以选择只生成需要用的hal库,可以让生成的代码小一些,不然的话会非常的大。

第二点就是勾选了 c/h 那个,可以让函数分文件,而不是都生成在了main函数里。

在这里插入图片描述

代码生成文件的按钮在这个位置,当时我真的是找了半天哈哈哈哈,真的有可能看不到啊。

在这里插入图片描述
在这里插入图片描述

直接打开工程就可以了,我用的Keil5不知道是版本问题还是什么,打开cubemx生成的文件总要弹出来这个窗口,以及选择驱动,回头我去找一找解决方法,然后更新

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里一步一步的选择就可以了

在这里插入图片描述

这里写自己的代码时候可以注意下,写在begin和end之间,这样的话可以在更新cubemx配置后保留自己写的代码。

在这里插入图片描述
这里一大堆,就不去一个一个说了,也不去说原理,我也理解的不太好,就说说咋用吧,一个是非中断,一个是中断。

非中断

重新定义printf函数
stm32f4xx_hal.c中包含#include <stdio.h>
stm32f4xx_hal.c 中重写fget和fput函数


#include <stdio.h>
extern UART_HandleTypeDef huart1;   //声明串口/*** 函数功能: 重定向c库函数printf到DEBUG_USARTx* 输入参数: 无* 返 回 值: 无* 说    明:无*/
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;
}/*** 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx* 输入参数: 无* 返 回 值: 无* 说    明:无*/
int fgetc(FILE *f)
{uint8_t ch = 0;HAL_UART_Receive(&huart1, &ch, 1, 0xffff);return ch;
}

main.c中添加

#include "stdio.h"#define RXBUFFERSIZE  256
char RxBuffer[RXBUFFERSIZE]; 
 while (1){/* USER CODE END WHILE */printf("Hello World!\r\n");//经典的Hello World!哈哈哈哈哈HAL_Delay(1000);/* USER CODE BEGIN 3 */}

现在开始编译,然后准备下载,在下载之前,还要准备一下,这个经常忘

在这里插入图片描述
外部晶振25Mhz,这里匹配上吧,虽然不匹配也都没发现什么问题

在这里插入图片描述
这里我用的jlink下载,习惯SW模式了,这里的下载速度默认是20Mhz,尽量改的低一些,因为太高了好像无法开启调试模式

这时候打开串口调试助手就可以了,记得匹配好波特兰115200

在这里插入图片描述
Bingo,成功了哈哈哈(小声嘀咕,为了写总结,我又重新写了一遍,大晚上的蓝色小灯要闪瞎我的眼了)

像这里,单独的接收和发送也都是可以的

HAL_UART_Transmit(&huart1,(uint8_t*)aRxBuffer,10,0xFFFF);
HAL_UART_Receive(&huart1,(uint8_t*)aRxBuffer,10,0xFFFF);

中断

因为中断接收函数只能触发一次接收中断,所以我们需要在中断回调函数中再调用一次中断接收函数

具体流程:

1、初始化串口

2、在main中第一次调用接收中断函数

3、进入接收中断,接收完数据 进入中断回调函数

4、修改HAL_UART_RxCpltCallback中断回调函数,处理接收的数据,

5 回调函数中要调用一次HAL_UART_Receive_IT函数,使得程序可以重新触发接收中断

HAL_UART_Receive_IT(中断接收函数)
-> USART2_IRQHandler(void)(中断服务函数)
-> HAL_UART_IRQHandler(UART_HandleTypeDef *huart)(中断处理函数)
-> UART_Receive_IT(UART_HandleTypeDef *huart) (接收函数)
-> HAL_UART_RxCpltCallback(huart);(中断回调函数)

main.c中添加下列定义:

#include <string.h>#define RXBUFFERSIZE  256     //最大接收字节数
char RxBuffer[RXBUFFERSIZE];   //接收数据
uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数

在==main()==主函数中,调用一次接收中断函数

/* USER CODE BEGIN 2 */HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
/* USER CODE END 2 */

main.c下方添加中断回调函数

/* USER CODE BEGIN 4 */void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{/* Prevent unused argument(s) compilation warning */UNUSED(huart);/* NOTE: This function Should not be modified, when the callback is needed,the HAL_UART_TxCpltCallback could be implemented in the user file*/if(Uart1_Rx_Cnt >= 255)  //溢出判断{Uart1_Rx_Cnt = 0;memset(RxBuffer,0x00,sizeof(RxBuffer));HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF); 	}else{RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位{HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束Uart1_Rx_Cnt = 0;memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组}}HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
/* USER CODE END 4 */

这里有接受和发送全流程,记得串口助手发送了才能接收到哦。

这篇关于STM32CubeMX串口通信调试避坑(胎教级教程)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/784352

相关文章

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Ubuntu固定虚拟机ip地址的方法教程

《Ubuntu固定虚拟机ip地址的方法教程》本文详细介绍了如何在Ubuntu虚拟机中固定IP地址,包括检查和编辑`/etc/apt/sources.list`文件、更新网络配置文件以及使用Networ... 1、由于虚拟机网络是桥接,所以ip地址会不停地变化,接下来我们就讲述ip如何固定 2、如果apt安

PyCharm 接入 DeepSeek最新完整教程

《PyCharm接入DeepSeek最新完整教程》文章介绍了DeepSeek-V3模型的性能提升以及如何在PyCharm中接入和使用DeepSeek进行代码开发,本文通过图文并茂的形式给大家介绍的... 目录DeepSeek-V3效果演示创建API Key在PyCharm中下载Continue插件配置Con

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

MySQL8.2.0安装教程分享

《MySQL8.2.0安装教程分享》这篇文章详细介绍了如何在Windows系统上安装MySQL数据库软件,包括下载、安装、配置和设置环境变量的步骤... 目录mysql的安装图文1.python访问网址2javascript.点击3.进入Downloads向下滑动4.选择Community Server5.

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee

MySql9.1.0安装详细教程(最新推荐)

《MySql9.1.0安装详细教程(最新推荐)》MySQL是一个流行的关系型数据库管理系统,支持多线程和多种数据库连接途径,能够处理上千万条记录的大型数据库,本文介绍MySql9.1.0安装详细教程,... 目录mysql介绍:一、下载 Mysql 安装文件二、Mysql 安装教程三、环境配置1.右击此电脑