STM32串口认识

常用函数介绍

串口发送/接收函数

HAL_UART_Transmit(); 串口发送数据,使用超时管理机制(即在发送成功前一直阻塞,相当于有个delay()在卡住主函数

HAL_UART_Receive(); 串口接收数据,使用超时管理机制

HAL_UART_Transmit_IT(); 串口中断模式发送  

HAL_UART_Receive_IT(); 串口中断模式接收

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart,
uint8_t *pData, uint16_t Size, uint32_t Timeout)
作用:以 阻塞 的方式发送指定字节的数据

UART_HandleTypeDef *huart串口的编号(结构体类型指针变量)

uint8_t *pData指向要发送的数据地址

uint16_t Size:要发送的数据大小,以字节为单位

uint32_t Timeout设置的超时时间,以ms为单位

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart,
uint8_t *pData, uint16_t Size)
作用:以中断的方式接收指定字节的数据

UART_HandleTypeDef *huart串口的编号(结构体类型指针变量)

uint8_t *pData是指向接收数据缓冲区

uint16_t Size要接收的数据大小,以字节为单位

此函数执行完后将清除中断,需要再次调用以重新开启中断

串口中断回调函数

HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断处理函数

HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //发送中断回调函数

HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //接收中断回调函数

状态标记变量

USART_RX_STA(可自命名)

从0开始,串口中断接收到一个数据(一个字节)就自增1。当数据读取全部OK时候(回车和换行 符号来的时候),那么 USART_RX_STA的最高位置1,表示串口数据接收全部完毕了,然后main 函数里面可以处理数据了。

 串口接收中断流程

串口实验(非中断)

需求: 接受串口工具发送的字符串,并将其发送回串口工具。
硬件接线: 使用之前用到的CH340接到STM32的1号串口:
TX -- A10
RX -- A9

一. 打开CubeMX:

1.0 惯例配置,不再展示

1.1 选择左侧的Connectivity--> USART1(共有三路口,随便选一路).

1.2 在右侧设置为 异步通信(Asynchronous)

1.3 在上图的下侧可以看到参数,暂时不做修改
1.4 惯例配置,生成项目

2. 打开Keil

2.1 实现方式1,直接用刚刚UART(使用超时管理机制)的接收和发送的函数

#include "string.h"
 
int main()
{
    unsigned char buff[20] = {0};
 
    while (1)
    {	
		HAL_UART_Receive(&huart1, buff, 19, 100);//19是因为我定义了20位字节的缓冲区,但实际字符串的发送结束会有\0,所以要预留一位,也就是说最多接收19个字符
		HAL_UART_Transmit(&huart1, buff, strlen(buff), 100);
		memset(buff,0,strlen(buff));//如果不清空buff,单片机则会一直发送buff存储的数据
    }
}

2.2 实现方式2,通过重写printf 

2.2.1 首先要打开MicroLIB的库

2.2.2

#include "stdio.h"
#include "string.h"
 
int fputc(int a,FILE *f)//一个字符一个字符发送
{
	unsigned char temp[1] = {a};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);
	return a;
}
 
int main(void)
{
  unsigned char buff[20] = {0};
  
  while (1)
  {	
	HAL_UART_Receive(&huart1, buff, 19, 100);//19是因为我定义了20位字节的缓冲区,但实际字符串的发送结束会有\0,所以要预留一位,也就是说最多接收19个字符
	printf(buff);
	memset(buff,0,strlen(buff));
  }
 
}

使用中断的串口实验

需求:通过中断的方法接受串口工具发送的字符串,并将其发送回串口工具。

接线:同上。

1. CubeMX配置,同上,在之前的基础上打开中断:

在这两个地方打开哪个都行

2. 打开Keil 

通过stm32f1xx_it.c --> USART1_IRQHandler() --> HAL_UART_IRQHandler() --> UART_Receive_IT() / UART_Transmit_IT()

UART_Receive_IT()UART_Transmit_IT()就是本节开篇提到的“ 串口中断模式 接收发送 ”,这也是本节提到的串口接收中断流程的第三步,下一步就是回调函数:

HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //发送中断回调函数

HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //接收中断回调函数

  而其中的“接收中断回调函数”,就是要在main函数中需要重写的函数了:

#include "stdio.h"
 
#define UART1_REC_LEN 200 //定义最大接收字节数 200,可根据需求调整
 
uint8_t buf=0; //串口接收缓存(1字节)
uint8_t UART1_RX_Buffer[UART1_REC_LEN];//接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
 
uint16_t UART1_RX_STA=0; //bit15,接收完成标志 //bit14,接收到0x0d //bit13~0,接收到的有效字节数目
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // 接收完成回调函数,每收到一个字符(字节)后,就会在这里处理
{
	if(huart->Instance == USART1){ // 判断中断是由哪个串口触发的
		if((UART1_RX_STA & 0x8000) == 0){ // 判断接收是否完成(UART1_RX_STA bit15 位是否为1)
			if(UART1_RX_STA & 0x4000){ // 如果已经收到了 0x0d (回车)
				// 则接着判断是否收到 0x0a (换行)
				if(buf == 0x0a){ // 如果 0x0a 和 0x0d 都收到,
					UART1_RX_STA |= 0x8000; //则将 bit15 位 置为1
				}else{ // 否则认为接收错误,重新开始
					UART1_RX_STA = 0;
				}
			}else{ // 如果没有收到 0x0d (回车)
				//则先判断收到的这个字符是否是 0x0d (回车)
				if(buf == 0x0d){ // 是的话则将 bit14 位置为1
					UART1_RX_STA |= 0x4000;
				}else{ // 否则将接收到的数据保存在缓存数组里
					UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf; //因为UART1_RX_STA只有前14位为有效数据,所以缓存数组UART1_RX_Buffer[X]中的X作为16位的二进制数,最高两位的判断应该写在前面代码的判断中,在此处不用
          UART1_RX_STA++;
					if(UART1_RX_STA > UART1_REC_LEN - 1){ //如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收
							UART1_RX_STA = 0;
					}
				}
			 }
			}
	HAL_UART_Receive_IT(&huart1, &buf, 1); // 重新开启中断
			
	}
}
 
int fputc(int a, FILE *f) //一个字符一个字符发送
{
	unsigned char temp[1] = {a};
	HAL_UART_Transmit(&huart1, temp, 1, 0xffff);
	return a;
}
 
 
int main(void)
{
 
  HAL_UART_Receive_IT(&huart1, &buf, 1);//开启中断,并把数据存到buf里
 
  while (1)
  {
		if(UART1_RX_STA & 0x8000){//不断的判断串口是否接收完成
			printf("收到数据:"); 
			HAL_UART_Transmit(&huart1, UART1_RX_Buffer, UART1_RX_STA & 0x3fff, 0xffff);// 将收到的数据发送到串口(此处也可以使用printf)
 
			while(huart1.gState != HAL_UART_STATE_READY);// 等待发送完成
			printf("\r\n");
			
			UART1_RX_STA = 0;// 重新开始下一次接收
		}
		printf("hello shion\r\n");
		HAL_Delay(1000);
  }
 
}

 PS:重新定义了printf函数一定要记得打开MicroLIB的库(打开方法在上方有说明)

3. 打开之前使用到的串口助手

按照刚刚的设置,调整波特率,打开串口,可以看到每秒从单片机发来的心跳包:

并且如果此时发送字符串给单片机,也会立刻收到单片机回传的这个字符串:

注意,此时必须勾选上“发送新行”,原因是在单片机的函数中,判断字符串是否传输完毕的方法就是检测最后的换行!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

极简云验证 download.php 文件读取漏洞复现

0x01 产品简介 极简云验证是一款开源的网络验证系统,支持多应用卡密生成:卡密生成 单码卡密 次数卡密 会员卡密 积分卡密、卡密管理 卡密长度 卡密封禁 批量生成 批量导出 自定义卡密前缀等;支持多应用多用户管理:应用备注 应用版…

Android JNI基础

目录 一、JNI简介1.1 什么是JNI1.2 用途1.3 优点 二、初探JNI2.1 新建cpp\cmake2.2 build.gradle配置2.3 java层配置2.4 cmake和c 三、API详解3.1 JNI API3.1.1 数据类型3.1.2 方法 3.2 CMake脚本 四、再探JNI 一、JNI简介 1.1 什么是JNI JNI(Java Native Interfa…

开源软件技术社区方案

开源软件技术社区是一个由开发者、贡献者、用户和维护者组成的共享平台,主要目的是打造技术、软件产品良性互动、开源技术安全可控的软件生态环境,实现可复用应用或服务的快速部署与使用、完成资源与能力的高度共享、促进社区成员的共建共赢,…

面试复盘1 - 测试相关(实习)

写在前:hello,大家早中晚上好~这里是西西,最近有在准备测试相关的面试,特此开设了新的篇章,针对于面试中的问题来做一下复盘,会把我自己遇到的问题进行整理,除此之外还会进行对一些常见面试题的…

什么是异地组网?

在当今互联网普及的背景下,异地组网已成为许多企业和个人日常工作中不可或缺的一部分。异地组网的核心目的是实现不同地区间的快速、高效的局域网连接。在这个过程中,延迟(即网络数据传输的时间延迟)是一个关键影响因素。我们来看…

还得是抖音,字节推出竖屏视频理解数据集,入选CVPR2024

ChatGPT狂飙160天,世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 短视频在当下社交媒体逐渐成为主导的视频格式。传统视频处理技术和研究一般都专注于横屏视频…

【快速解决】python缺少了PyQt5模块的QtMultimedia子模块

目录 问题描述 问题原因 解决方法 成功示范 问题描述 Traceback (most recent call last): File "d:\桌面\python项目\DesktopWords-master\main.py", line 4, in <module> from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent ModuleNotFoundEr…

Unity自定义icon

Unity自定义icon 1. 新建文件夹 OfficeFabricIconSet2. 新建Iconset3. 新建子文件夹Textures并添加icon图片4. 向iconset添加Quad Icons5. 最终效果 教程来源处&#xff1a; https://365xr.blog/build-your-own-button-icon-set-for-microsoft-hololens-2-apps-with-mrtk-using…

stm32之基本定时器的使用

在上文我们使用到了HAL库的自带的延时函数&#xff0c;HAL_Delay&#xff08;&#xff09;&#xff1b;我们来看一下函数的原型 __weak void HAL_Delay(uint32_t Delay) {uint32_t tickstart HAL_GetTick();uint32_t wait Delay;/* Add a freq to guarantee minimum wait */…

程序员为什么不能一次性写好,需要一直改Bug?

程序员为什么不能一次性写好&#xff0c;需要一直改Bug&#xff1f; 我有一问&#xff1a; 你为什么不上清华呢&#xff0c;高考答满分不就行了&#xff1f; 程序员在软件开发过程中可能会遇到需要不断修改Bug的情况&#xff0c;这主要是由以下几个原因造成的&#xff1a; 复杂…

5.3.1 配置交换机 SSH 管理和端口安全

5.3.1 实验1:配置交换机基本安全和 SSH管理 1、实验目的 通过本实验可以掌握&#xff1a; 交换机基本安全配置。SSH 的工作原理和 SSH服务端和客户端的配置。 2、实验拓扑 交换机基本安全和 SSH管理实验拓扑如图所示。 交换机基本安全和 SSH管理实验拓扑 3、实验步骤 &a…

FreeBSD下如何进行添加路由等配置?

FreeBSD系统可以当作一台路由器来使用&#xff0c;实际上当年路由器刚刚出来的时候&#xff0c;有很大一部分就是用主机安装FreeBSD来提供路由功能的。 路由的基础知识 路由&#xff0c;就是计算机网络中决定数据包从源地址到目的地址路径的一种传输过程。路由表&#xff0c;就…

基于Springboot学生考勤管理系统

采用技术 基于Springboot学生考勤管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 功能清单 系统登录注册 系统登录 学生注册 管理员功能模…

【C+ +】第一个C+ + 项目的创建及namespace命名空间解释C++中的输入输出

目录 1.创建第一个c项目 1.1项目创建 1.2 .cpp源文件建立 1.3 第一个c程序hello world对比c语言hello world 2.命名空间 2.1 C关键字 2.2 命名空间---解决c语言中的命名冲突 2.2.1 namespace命名空间用法 2.2.2 &#xff1a;&#xff1a; 预作用限定符 2.2.3 命名空间的嵌套…

VSCode常用修改默认设置(settings.json)

❓ 问题1 我现在在vscode中鼠标选中某个单词&#xff0c;相同的单词都会自动出现一个高亮背景色&#xff0c;我需要怎么关闭这个功能呢&#xff1f; ⚠️ 注意 selectionHighlight 这个是鼠标双击后的高亮匹配&#xff0c;可以保留默认开启的配置&#xff0c;不用去改它。 …

【Redis基础篇】详细讲解Redis

这篇文章让你详细了解Redis的相关知识&#xff0c;有代码讲解以及图片剖析&#xff0c;让你更轻松掌握 制作不易&#xff0c;感觉不错&#xff0c;请点赞收藏哟 &#xff01;&#xff01;&#xff01; 目录 1 redis基础 1.1 定义 1.2 SQL和NOSQL不同点 1.3 特征 1.4 Redis…

Electron 打包自定义NSIS脚本为安装向导增加自定义页面增加输入框

Electron 打包工具有很多&#xff0c;如Electron-build、 Electron Forge 等&#xff0c;这里使用Electron-build&#xff0c;而Electron-build使用了nsis组件来创建安装向导&#xff0c;默认情况nsis安装向导不能自定义安装向导界面&#xff0c;但是nsis提供了nsis脚本可以扩展…

探索未来外贸电商系统的创新架构

在全球化、数字化的时代背景下&#xff0c;外贸电商行业呈现出蓬勃发展的态势。为了适应市场竞争的激烈和用户需求的多样化&#xff0c;外贸电商系统的架构设计显得尤为重要。本文将深入探讨未来外贸电商系统的创新架构&#xff0c;以期为行业发展提供新的思路和方向。 随着全…

UE4_X光效果设置_法线图影响透明度

UE4_X光效果设置_法线图影响透明度 2019-03-22 13:37 Exponentin 设置轮廓光扩散度 baseReflectFactionIn 设置内部黑色的亮度值。nromal&#xff0c;连接应用一张法线图&#xff0c;Lerp两色插值&#xff0c;给两个数值&#xff0c;制造一个渐变。 法线图影响透明度&#xf…