(三)STM32F407 cubemx串口中断通讯

(三)STM32F407 cubemx串口中断通讯

这篇文章主要是个人的学习经验,想分享出来供大家提供思路,如果其中有不足之处请批评指正哈。

废话不多说直接开始主题,本人是基于STM32F407VET6芯片,但是意在你看懂这篇文章后,不管是F1,F4,H7等一系列系统串口通讯配置都能明白如何通过参考手册去学习配置。而不是Ctrl c,Ctrl v。
串口通讯其实cubemx已经把步骤精简的不能再精简了,但是秉持着不断学习的理念,有必要去大概学习一下串口协议,以及cubemx是如何根据参考手册封装的。

在这里插入图片描述以上是串口协议比较重要的几个点,跟着参考手册一个一个点的讲解,了解串口协议的重点。首先串口主要有3根线TX、RX、GND。根据以上的几个点知一个串口数据包主要由1.起始位 2.数据字 3.停止位构成其他的寄存器都是围绕它们为它们服务。

在这里插入图片描述接下来我将参照串口助手一步步讲解。
在这里插入图片描述
1)波特率
发送和接收由一共用的波特率发生器驱动,当发送器和接收器的使能位分别置位时,分别为其产生时钟。波特率从某种意义上来说,它就是时钟的一种表现形式,115200意思是1秒内产生115200个高低电平变化。一个8位字长的串口数据=8字长+1起始位+1停止位=10;也就是1秒钟能发送115200/10=11520个数据,也就是1/11520=86us平均86us发一个‘A’(数据)。

在这里插入图片描述2)停止位
USART支持多种停止位的配置:0.5、1、1.5和2个停止位。
1.1个停止位:停止位位数的默认值。
2.2个停止位:可用于常规USART模式、单线模式以及调制解调器模式
3. 0.5个停止位:在智能卡模式下接收数据时使用。
4.1.5个停止位:在智能卡模式下发送和接收数据时使用。空闲帧包括了停止位
在这里插入图片描述停止位是通讯双方需要一致的,通常情况都是默认为1。在USART__CR2中编程停止位的位数。
若停止位需要更改长度
方一cubemx自动配置在这里插入图片描述
方二代码hal库代码调用
在这里插入图片描述在这里插入图片描述hal库只提供了两种一个停止位,和两个停止位的定义

3)起始位中断信号产生
在USART中,如果辨认出一个特殊的采样序列,那么就认为侦测到一个起始位。该序列为:1110X0X0X0000
在这里插入图片描述
起始位的开始标志是1110低电平下降沿,当下降沿触发时它会间隔采样,X就是它采样的信号是不确定的,但是若需要进入串口中断必须每一次采样的X(采样点为3,5,7,8,9,10)都为0才可确认收到起始位,这时设置RXNE标志位,如果RXNEIE=1,则产生中断。若其中采样X为1不管什么原因,返回空闲状态等待下降沿。

4)数据位
USART可以根据USART_CR1的M位接收8位或9位的数据字
8位数据的信号是和ASCLL码表一一对应的比如‘A’=65=0x41=01000001 8位传输的数据就是低高低低低低低高
在这里插入图片描述
5)奇偶校验
设置USART_CR1寄存器上的PCE位,可以使能奇偶控制(发送时生成一个奇偶位,接收时进行奇偶校验)。根据M位定义的帧长度,可能的USART帧格式列在下表中。
在这里插入图片描述偶校验:校验位使得一帧中的7或8个LSB数据以及校验位中’1’的个数为偶数。
例如:数据=00110101,有4个1’,如果选择偶校验(在USART_CR1中的PS=0),校验位将是’0’。4个1凑个偶数,校验位为0
奇校验:此校验位使得一帧中的7或8个LSB数据以及校验位中’1’的个数为奇数。
例如:数据=00110101,有4个’1’,如果选择奇校验(在USART_CR1中的PS=1),校验位将是’1’。4个1凑个奇数,还需一个1,校验位为1
这是参考手册的例子很清楚,但是可能是自己才疏学浅本人并不知道校验位有什么很大的作用,有大佬的话可以评论区指导一下。
在这里插入图片描述

我们默认使用的是第一种00
在这里插入图片描述

0x0000u这样的常数一律默认为int型0,不是什么字节。

关键内容讲完了开始cubemx配置实现功能

基础时钟配置等请见:http://t.csdnimg.cn/XQ0L6
在这里插入图片描述中断勾上
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
keil5处点击魔术棒,给红框处打上勾。

在这里插入图片描述
dubug处我用的下载器是DAP可能和你们的不一样,勾上重新下载程序后复位功能。

  uint8_t AA='A';HAL_UART_Transmit(&huart1,&AA,1,10000);

HAL_UART_Transmit函数语法很简单,只要配置串口号,内容,内容长度,发送时间即可
主函数

int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */uint8_t AA='A';HAL_UART_Transmit(&huart1,&AA,1,10000);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

考虑到重定义函数printf只有一个串口可用,本人给大家提供了printf转译其他串口也可使用printf
主函数部分

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern UART_HandleTypeDef huart1;
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
extern uint8_t uart1_rxbuf[10];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */uint8_t AA='A';HAL_UART_Transmit(&huart1,&AA,1,10000);u1_printf("您的身高:%.0f cm\r\n",2);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 4;RCC_OscInitStruct.PLL.PLLN = 168;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 4;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){Error_Handler();}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}
#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

usart.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "main.h"
#include "stdarg.h"		//包含需要的头文件 
#include "string.h"     //包含需要的头文件
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN Private defines */
#define USART1_RX_ENABLE     0      //是否开启接收功能  1:开启  0:关闭
#define USART1_TXBUFF_SIZE   256    //定义串口1 发送缓冲区大小 256字节
#define USART1_RXBUFF_SIZE   256               //定义串口1 接收缓冲区大小 256字节
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);
/* USER CODE BEGIN Prototypes */
void u3_printf(char* fmt,...) ;
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */

usart.c

/* Includes ------------------------------------------------------------------*/
#include "usart.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */UART_HandleTypeDef huart1;/* USART1 init function */void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* USER CODE END USART1_Init 2 */}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF7_USART1;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}
}void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);/* USART1 interrupt Deinit */HAL_NVIC_DisableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */
__align(8) char Usart1_TxBuff[USART1_TXBUFF_SIZE];  
void u1_printf(char* fmt,...) 
{  unsigned int i,length;va_list ap;va_start(ap,fmt);vsprintf(Usart1_TxBuff,fmt,ap);va_end(ap);	length=strlen((const char*)Usart1_TxBuff);		while((USART1->SR&0X40)==0);for(i = 0;i < length;i ++){			USART1->DR = Usart1_TxBuff[i];while((USART1->SR&0X40)==0);	}	
}
/* USER CODE END 1 */

实验效果
在这里插入图片描述
串口发送中断主函数

	HAL_UART_Receive_IT(&huart1,&Data, sizeof(Data));//开启中断接收数据uint8_t IT_SEND[]="IT_SEND";HAL_UART_Transmit_IT(&huart1,IT_SEND, sizeof(IT_SEND)/sizeof(IT_SEND[0]));u1_printf("\r\n");

只需要在主函数处添加这一部分代码。
效果图
在这里插入图片描述串口中断接收本人采用的方式是结束位为0x5c串口接收结束,长度不可大于15个字节,实例代码如下

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart == &huart1){if(recv_end_flag_1==1){for(int i=0;i<sizeof(rx_buffer1)/sizeof(rx_buffer1[0]);i++){rx_buffer1[i]=0;}recv_end_flag_1 = 0;          //数据清空}rx_buffer1[Cnt]=Data;Cnt++;if(rx_buffer1[Cnt-1] == 0x5C)//判断是否为'\'结尾{//rx_buffer1[Cnt-1] = 0x0a; u1_printf("\n接收到的数据为:\n");HAL_UART_Transmit(&huart1,rx_buffer1,Cnt,10000);//显示在串口助手Cnt = 0;recv_end_flag_1 = 1;          //数据接收完成for(int i=0;i<sizeof(rx_buffer1)/sizeof(rx_buffer1[0]);i++){rx_buffer1[i]=0;}}HAL_UART_Receive_IT(&huart1,&Data,1);//继续接收数据}
} 

在这里插入图片描述显示效果如图。

整体的所有代码以及数据手册链接:
链接:https://pan.baidu.com/s/1xmEUNd82dunSmh_NyI09fg?pwd=6dqr
提取码:6dqr
希望这篇文章对你有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/323935.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构学习 jz16 数值的整数次方

关键词&#xff1a;快速幂 位运算 之前已经学过快速幂了&#xff0c;所以只是回忆。快速幂有递归版和非递归版。 题目&#xff1a; 这道题和之前的快速幂的区别是 n可能为负数。分类讨论即可。 思路&#xff1a; 区分正负&#xff1a; if (n < 0) return POW(1.0 / x, …

电源测试系统与传统测试有什么不同?又有哪些突破?

电源测试系统是电源模块测试中非常常见的一种自动化测试软件&#xff0c;系统一般会将测试所需的仪器与软件集成到机柜中&#xff0c;这样方便对开关电源等产品进行批量化、自动化测试&#xff0c;那么电源测试系统是对比传统测试方法有哪些优势呢? 传统电源模块的测试一般都会…

专业实习day3、4(路由器做内网访问公网)

专业实习 代码 display ip interface brief 显示当前设备下所有接口IP undo IP地址支持覆盖&#xff0c;但是正常的命令不能覆盖必须undo&#xff08;删除&#xff09;掉 un in en 在做配置的过程中&#xff0c;设备系统一般都会出现一些提示或者告警之类的东西&#xff0c;从…

开发者必备的 Github 加速工具(截至2024年01月)

开始闲聊前&#xff0c;我要感谢大神小青龍总结的博文&#xff1a;作为程序员不得不知道的几款Github加速神器&#xff0c;给我们介绍了常用&#xff08;较为合规&#x1f604;&#xff09;的加速方法。毕竟 github 是开发者绕不过的宝库。 背景 我用 Github 将近12年&#x…

国产服务器操作系统PXE安装脚本 可重复执行(rc08版本)

执行效果如下&#xff1a; #!/bin/bash #Date:2023/12/25 #Func:一键部署pxe服务器 #Author:Zhanghaodong #Version:2023.12.25.05 #Note:仅适用x86架构uefi安装 # 1.此脚本可多次重复执行。 # 2.如遇到某个服务异常退出&#xff0c;检查响应状态码排错后&#xff0c…

上门回收小程序开发的优势,顺应时代发展

当下&#xff0c;人们的生活水平不断提高&#xff0c;相应产生的闲置物品也在不断增加&#xff0c;回收行业因此得到了快速发展。 同时&#xff0c;在互联网的发展下&#xff0c;回收行业也慢慢转到了线上&#xff0c;人们在卖闲置物品时不需要到门店内&#xff0c;只需要在手…

Golang里空结构体struct{}的介绍和使用

s t r u c t struct struct是 G o l a n g Golang Golang里的关键字&#xff0c;用于定义结构类型 比如 type Student struct{id intname string }struct{}是有 0 0 0个元素的结构体. struct{}{}表示类型struct{}的值为空{} 1.性质 1.1不占用内存 大小为 0 0 0&#xff0c;…

python-查漏补缺笔记-更新中

包导入时__init__.py中命令的执行顺序和sys.modules变化 ref: https://edu.csdn.net/skill/practice/python-3-6/164 在有父包和子包的情况下&#xff0c;父包中的“ __ init__.py”语句会在子包的“ __ init__.py”语句之前执行&#xff0c;然后按下列顺序执行导入子包和模块…

Mac 安装Nginx教程

Nginx官网 Nginx官网英文 1.在总段输入brew search nginx 命令检查nginx是否安装了 2. 安装命令&#xff1a;brew install nginx 3. 查看Nginx信息命令brew info nginx 4. 启动 nginx方式&#xff1a;在终端里输入 nginx 5.查看 nginx 是否启动成功 在浏览器中访问http://l…

如何打造家居产业数字化转型范式?林氏家居以数智供应链作答

近年来&#xff0c;我国房地产行业逐步进入深度调整期。作为下游产业&#xff0c;家居家装行业的发展也来到了新阶段。业内人士指出&#xff0c;新房市场成交规模收缩&#xff0c;家居家装企业们开始整合资源&#xff0c;向存量房市场、产品科技化以及数字化转型。 国家层面出…

实验4.4 动态路由OSPF协议的配置

实验4.4 动态路由OSPF协议的配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.配置交换机和路由器的接口的IP地址等参数。2.配置动态路由OSPF协议&#xff0c;实现全网互通。 六、任务验收七、任务小结八、知识链接1&#xff0e;OSPF协议概念2&#xff0e;…

qiankun 公共依赖

1、提取公共依赖的目的 减少相同资源的重复加载资源版本不同步打包文件庞大2、如何提取公共依赖 基本思路&#xff1a;1、相同依赖 采用 CDN 的方式加载&#xff0c;并把 所有依赖的 CDN 链接 统一放到一个文件中进行管理 2、把存放 CDN 链接的文件&#xff0c;引入到 vue.conf…