STM32—串口

2023-05-16

串口介绍

串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢是设备间接线通信的一种方式数据一位一位地顺序传送双向通信,全双工传送速度相对较慢
UART是异步串行接口,通信双方使用时钟不同,因为双方硬件配置不同,但是需要约定通信 速度,叫做波特率。对于单片机和pc之间通信,pc端用软件配置,则单片机需要用代码完成配置,也可以用波特率配置软件直接生成
在这里插入图片描述

常用函数的介绍

串口发送/接收函数:

 - HAL_UART_Transmit();//串口发送数据,使用超时管理机制
 - HAL_UART_Receiver();//串口接收数据,使用超时管理机制
 - 
 - 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)
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数1:UART_HandleTypeDef 结构体类型指针变量
参数2:指向要发送的数据地址
参数3:要发送的数据大小,以字节为单位
参数4:设置的超时时间,ms为单位
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数1:UART_HandleTypeDef 结构体类型指针变量
参数2:指向接收数据缓存区
参数3:要接收的数据大小,以字节为单位
参数4:设置的超时时间,ms为单位

串口中断回调函数

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)//串口中断处理函数
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)//发送中断回调函数
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//接受中断回调函数

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

串口接收中断流程
在这里插入图片描述

串口实验(非中断)

需求:接收串口工具发送的字符串,并且将其发送回串口工具
TX——PA10 RX——PA9(交叉接线)
使用CubeMX配置工程,串口配置
1.选定串口
2.选择模式
异步通信
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
效果:在这里插入图片描述

如何使用printf打印数据到串口调试助手
1.重写fputc函数

int fputc(int ch,FILE *f)
{
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);
	return ch;

2.添加#include stdio.h头文件,使用MicroLIB库
在这里插入图片描述

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		//HAL_UART_Transmit(&huart1,"hello\n",strlen("hello\n"),100);
		HAL_UART_Receive(&huart1,buff,19,100);
	//	HAL_UART_Transmit(&huart1,buff,strlen(buff),100);
	//	printf("hello wrold\n");
		printf(buff);//打印到串口调试助手
		memset(buff,0,20);//清空buff
  }
  /* USER CODE END 3 */

串口实验(中断)

需求:通过中断的方法接收串口工具发送的字符串,并将其发送回串口工具
串口配置
1.选定串口
2.选择模式
异步通信
前面步骤与上面一样
打开串口中断
在这里插入图片描述
根据中断接收流程可知,最后会在UART_Receive_IT函数中调用HAL_UART_RxCpltCallback函数,该函数为一个虚函数,我们可以在main.c中重写,接收到一个数据,就在函数中处理
在这里插入图片描述

在这里插入图片描述

//定义最大接收字节数200
#define USART_REC_LEN 200
 

//接收缓冲,串口接收到的数据放到这个数组里面,最大USART_REC_LEN字节
uint8_t UART1_RX_Buffer[USART_REC_LEN];
uint8_t buf = 0;
uint16_t USART_RX_STA = 0;

//接收完成回调函数,收到一个数据后,在这里处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//1.判断中断是由哪个串口触发
	if(huart->Instance == USART1){
		//判断接收是否完成(USART_RX_STA的bit15位置为1)
		if((USART_RX_STA & 0x8000) == 0){//等于0则表示没有接收完成
			//如果收到了0x0d(回车),看bit14是否为1
			if(USART_RX_STA & 0x4000){
					//则继续判断是否收到0x0a(换行)
					if(buf == 0x0a){
						//如果0x0a和0x0d都收到,则将bit15位置置1
						USART_RX_STA |= 0x8000;
					}else {
						//否则认为接收错误,USART_RX_STA置0
						USART_RX_STA = 0;
						
					}
			}else {  //如果没有收到0x0d回车
				//先判断这个字符是否是0x0d回车
				if(buf == 0x0d){
					//是的话就将bit14置1
					USART_RX_STA |= 0x4000;
				}else {
					//不是的话,就将接收到的数据保存到缓存数组里面去
					UART1_RX_Buffer[USART_RX_STA & 0x3FFF] = buf;
					USART_RX_STA++;
					
					//如果接收数据大于USART_REC_LEN(200字节),则重新开始接收
					if(USART_RX_STA > USART_REC_LEN - 1 ){
						USART_RX_STA = 0;
						
					}
				}
				
			}
			
		}
		//重新开启中断
		HAL_UART_Receive_IT(&huart1,&buf,1);
	}
	

}

参考博文:http://t.csdn.cn/q4IPk
解释:从串口接收到的数据只有一个字节的,也就是串口是一个字节一个字节进行判断的,每次buf里面都是最新的字节,所以我们要读到一条完整的或者指定的数据长度,我们就要用UART1_RX_Buffer来存储,而USART_RX_STA就是辅助判断数据状态的。
在这里插入图片描述
两个表对应看,想要知道触发串口中断后,串口是否接收完成所有数据(0代表没有接收完成,1代表完成。)

UART1_RX_Buffer是专门存放数据的,串口接收到一个字节的数据,USART_RX_STA就会累加,UART1_RX_Buffer[USART_RX_STA]=buf就可以按顺序保存数据,但是bit15和bit14位指定进行两个判断功能,就不能拿来使用保存数据,所以我们这里&0X3FFF来截断数据。

//不是的话,就将接收到的数据保存到缓存数组里面去
UART1_RX_Buffer[USART_RX_STA & 0x3FFF] = buf;
USART_RX_STA++;				
//如果接收数据大于USART_REC_LEN(200字节),则重新开始接收
if(USART_RX_STA > USART_REC_LEN - 1 ){
		USART_RX_STA = 0;						
	}

main函数

int main(void)
{
  /* USER CODE BEGIN 1 */
	// unsigned char buff[20] = {0};
	
  /* 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 */

	HAL_UART_Receive_IT(&huart1,&buf,1);


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {	
		//判断串口是否接收完成
		if(USART_RX_STA & 0x8000){
				printf("收到数据:");
			//将收到的数据发送到串口
			HAL_UART_Transmit(&huart1,UART1_RX_Buffer,USART_RX_STA & 0x3FFF,0xffff);
			//等待发送完成
			while(huart1.gState != HAL_UART_STATE_READY);
			
			printf("\r\n");
			//重新开始下一次接收
			USART_RX_STA = 0;
		}
		printf("hello world\n");
		HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32—串口 的相关文章

  • stm32的HAL库函数flash无法写入的问题

    记录一下对flash编程操作时出现的问题以及解决办法 问题 在使用HAL库中的HAL FLASH Program uint32 t TypeProgram uint32 t Address uint64 t Data 函数时发现总是没办法写
  • 以字符串形式接收数字(uart)

    我正在尝试通过 uart 接收一个包装为字符串的数字 我发送数字 1000 所以我得到 4 个字节 空字符 但是 当我使用 atoi 将数组转换为数字并将整数与 1000 进行比较时 我并不总是得到正确的数字 这是我用于接收号码的中断处理函
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • HAL库STM32常用外设教程(二)—— GPIO输入\输出

    HAL库STM32常用外设教程 二 GPIO输入 输出 文章目录 HAL库STM32常用外设教程 二 GPIO输入 输出 前言 一 GPIO功能概述 二 GPIO的HAl库驱动 三 GPIO使用示例 1 示例功能 四 代码讲解 五 总结
  • STM32用一个定时器执行多任务写法

    文章目录 main c include stm32f4xx h uint32 t Power check times 电量检测周期 uint32 t RFID Init Check times RFID检测周期 int main Timer
  • STM32超声波——HC_SR04

    文章目录 一 超声波图片 二 时序图 三 超声波流程 四 单位换算 五 取余计算 六 换算距离 七 超声波代码 一 超声波图片 测量距离 2cm 400cm 二 时序图 1 以下时序图要先提供一个至少10us的脉冲触发信号 告诉单片机我准备
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 在 Atollic TrueStudio、STM32CubeMX 中导入 C 库

    我目前正在开发 STM32F767ZI Nucleo 板和一个小安全芯片 microchip atecc508a 通过 i2c 连接进行连接 该芯片有一个可用的库加密验证库 https github com MicrochipTech cr
  • 擦除后无法写入闪存

    所以我不能在擦除后直接写入内部闪存 如果写操作之前没有擦除操作 那么我可以 有什么想法吗 编程函数返回 成功写入 值 但查看内存时 没有写入任何数据 这是代码 uint32 t pageAddress 0x08008000 uint16 t
  • Arm:objcopy 如何知道 elf 中的哪些部分要包含在二进制或 ihex 中?

    我正在开发一个项目 其中涉及解析arm elf 文件并从中提取部分 显然 elf 文件中有很多部分没有加载到闪存中 但我想知道 objcopy 到底如何知道要在二进制文件中包含哪些部分以直接闪存到闪存中 以arm elf文件的以下reade
  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧 说起来很简单 就是几行代码的事 但楞是折腾了我大半天时间才搞定 原因后面说 先看代码吧 读操作 读操作很简单 以32位方式读取的时候是这样的 data IO uint32 t 0x0800F000 需要注意的是 当以32位方式读
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • Cortex-M3与M4权威指南

    处理器类型 所有的ARM Cortex M 处理器是32位的精简指令集处理器 它们有 32位寄存器 32位内部数据路径 32位总线接口 除了32位数据 Cortex M处理器也可以有效地处理器8位和16位数据以及支持许多涉及64位数据的操作
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • STM32 上的 ADC 单次转换

    我正在研究 STM32 F103x 上的 ADC 编程 并从最简单的情况 单次转换开始 测量内部温度传感器 连接到 ADC1 的值 并使用 USART 将其发送到 COM 端口 目标似乎很明确 但是当我尝试将源代码下载到闪存时 它不会向 C
  • STM32内部时钟

    我对 STM32F7 设备 意法半导体的 Cortex M7 微控制器 上的时钟系统感到困惑 参考手册没有充分阐明这些时钟之间的差异 SYSCLK HCLK FCLK 参考手册中阅读章节 gt RCC 为 Cortex 系统定时器 SysT
  • 在 Contiki 程序中使用 malloc

    考虑以下 Contiki 程序 include
  • HAL_Delay() 陷入无限循环

    我被 HAL Delay 函数困住了 当我调用此函数 HAL Delay 时 控制陷入无限循环 在寻找问题的过程中 我发现了这个 http www openstm32 org forumthread2145 threadId2146 htt
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE

随机推荐

  • 常用CORS账号设置方法(千寻CORS、中国移动CORS、六分CORS、北斗CORS、迅腾CORS)

    1 千寻CORS账号设置方法 2 中国移动CORS账号设置方法 3 六分CORS账号设置方法 4 北斗CORS账号设置方法 5 讯腾CORS账号设置方法 格林恩德专注GPS北斗高精度定位 北斗短报文通信与无线传输应用产品的开发与市场拓展
  • NTRIPClient_1.7 工具使用方法分享

    1 打开NTRIPClient 1 7软件 2 选择串口和波特率 xff0c 正确的与板卡或者模块连接 点击编辑 xff0c 进入串口配置界面 选择正确的端口和波特率 3 输入正确的差分账号 输入千寻差分账号地址 端口 用户名 账号密码 4
  • 导航卫星的时间系统

    1 GPS时间系统 xff08 GPST xff09 GPS系统是测时测距系统 时间在 GPS测量中是一个基本的观测量 卫星的信号 xff0c 卫星的运动 xff0c 卫星的坐标都与时间密切相关 对时间的要求既要稳定又要连续 为此 xff0
  • JT808协议介绍 --- 格林恩德 CR202 RTK 高精度车载定位器协议解读

    部标808又称为JT808 xff0c JT808标准的全称是 道路运输车辆卫星定位系统终端通讯协议及数据格式 808协议适用于GPS定位车载终端和监控平台之间的通信 当前市面上 xff0c 普通车辆监测设备所安装的GPS定位器 xff0c
  • C++析构函数调用顺序

    文章目录 析构函数工作过程 1 执行析构函数的函数体 2 如果该类中拥有类对象成员 xff0c 且类对象有析构函数 xff0c 则以类对象成员声明次序的相反顺序调用其析构函数 xff0c 销毁类对象成员 3 按原来构造顺序的相反顶序向上依次
  • TCP通信C++实现小例子

    TCP通信C 43 43 实现案例 https www bilibili com video BV1Dt411p74c t 61 1746 61 61 全部来自以上视频 xff0c 纯属搬运 xff0c 小可爱有问题可以举手提问哈 61 6
  • 串行通信简介

    一 串行通信与并行通信 计算机与外界的数据交换称为通信 xff0c 通信分为并行通信和串行通信两种基本方式 并行通信 串行通信 并行通信 xff1a 并行通信指各个数据位同时进行传送的数据通信方式 xff0c 因此有多少个数据位 xff0c
  • 使用寄存器点亮一个LED灯 普中科技stm32(stm32f1103zeb6)

    板子 xff1a 普中科技stm32F1 芯片stm32f1103zet6 1 程序如下 xff1a include 34 stm32f10x h 34 导入头文件 typedef unsigned int u32 typedef是系统关键
  • day 5 select服务器和客户端

    select客户端代码 xff1a include lt stdio h gt include lt string h gt include lt sys socket h gt include lt netinet in h gt inc
  • python Requests添加Auth和Cert

    最近通过postman发起另外一个项目的请求 xff0c 鉴权较为复杂 xff0c 首先需要设置cert xff0c postman中设置如下 xff1a 需要设置basic auth的参数 然后将接口返回的token放入auth的bear
  • STM32笔记(三)---寄存器映射--BSRR分析

    STM32笔记 xff08 三 xff09 寄存器映射 BSRR分析 GPIO与引脚区别 GPIO包含在引脚内 xff08 引脚内还有电源 晶振等特殊功能引脚 xff09 xff0c 除GPIO拓展内容即为单片机最小系统 GPIO功能如何检
  • ROS赵虚左6.5 Rviz中控制机器人模型运动_选了odom坐标系后小车变白不能动

    原因 xff1a 配置文件中的参考坐标不应该是base footprint xff0c 而是你自己小车最下面那个 小脚 的坐标系 xff0c 我的是footprint 所以把参考坐标换一下就可以了
  • 超声波传感器的基础

    超声波传感器已经有几十年的历史了 xff0c 但是由于它们的性能 灵活性和低成本 xff0c 它们仍然占据着传感市场的很大一部分 随着越来越多的产品实现了自动化 xff0c 随着机器人 自动驾驶汽车和无人驾驶飞机的出现 xff0c 需求进一
  • pthread_create未定义的引用

    在ubuntu使用gcc编译时出现 pthread create未定义的引用 问题 解决如下 xff1a 在编译时加入 l pthread 例如gcc thread c o thr l pthread 原因 xff1a pthread不是l
  • Linux下vscode实现调试

    1 安装好vscode xff0c 安装对应的插件 2 编写代码 xff0c 点击右上角的三角形 xff0c 生成对应可执行文件 3 点击菜单栏中的终端 配置任务 xff0c 选择 c c 43 43 xff1a GCC build act
  • 二进制数与十进制之间的转换以及使用一个函数实现任意进制之间的转换

    其他进制转为十进制都可以实现 xff0c 只需要将函数中的10和2换掉你需要的就行 include lt stdio h gt include lt math h gt 1 二进制转换为十进制 int twoConvertTen long
  • vscode配置C语言编译调试的方法

    一 安装GCC 官方下载 如果你能从在线安装 xff0c 那最好就在线安装吧 不过在线安装太容易中断失败了 如果你能连上官网 xff0c 也可以选择从官网去下载离线安装包 https sourceforge net projects min
  • C语言之补漏(1)

    typedef 1 define与typedef区别 xff1f 相比起宏定义的直接替换 xff0c typedef是对类型的封装 xff08 通俗说就是对类型起一个别名 xff09 2 typedef可以给多个别名 typedef int
  • 关于学习如何组装基于F4V3S飞控的竞速穿越机

    广西 河池学院 广西高校重点实验室培训基地 系统控制与信息处理重点实验室 本篇博客来自河池学院 智控无人机小组 创作时间2020 8 22 组装一架穿越机 xff0c 你需要的一些最基本的 xff0c 能让它飞起来的配件有 xff1a 机架
  • STM32—串口

    串口介绍 串行接口简称串口 xff0c 也称串行通信接口或串行通讯接口 xff08 通常指COM接口 xff09 xff0c 是采用串行通信方式的扩展接口 串行接口 xff08 Serial Interface xff09 是指数据一位一位