STM32 串口实验(学习一)

本章将实现如下功能:STM32通过串口和上位机对话,STM32在收到上位机发过来的字符串后,原原本本返回给上位机。

STM32 串口简介

串口作为MCU的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。现在基本上所有的MCU都会带有串口,STM32自然也不例外。

通过USB串口和电脑通信

串口最基本的设置,就是波特率的设置。只要开启了串口时钟,设置相应IO口的模式,然后配置一下波特率,数据位长度,奇偶校验位等信息,就可以使用。

  1. 串口时钟使能。串口作为STM32的一个外设,其时钟由外设时钟使能寄存器控制,串口1是在APB2ENR寄存器的第14位。除了串口1的时钟使能在APB2ENR寄存器,其它串口的时钟使能位都在APB1ENR寄存器,而APB2的频率一般是APB1的一倍。
  2. 串口复位。当外设出现异常的时候可以通过复位寄存器里面的对应位设置,实现该外设的复位,然后重新配置这个外设让其重新工作。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。

在这里插入图片描述
串口1的复位设置位在APB2RSTR的第14位,通过向该位写1复位串口1,写0结束复位。

串口设置的一般步骤

  1. 串口时钟使能,GPIO时钟使能。
  2. 设置引脚复用器映射:调用GPIO_PinAFConfig函数。
  3. GPIO初始化设置:要设置模式为复用功能。
  4. 串口参数初始化:设置波特率,字长,奇偶校验等参数。
  5. 开启中断并且初始化NVIC,使能中断。
  6. 使能串口。
  7. 编写中断处理函数:函数名格式为USART1IRQHandler。

在HAL库中,串口相关的函数和定义主要在文件stm32f1xx_hal_uart.c和stm32f1xx_hal_uart.h中。

串口参数初始化

串口作为STM32的一个外设,HAL库为其配置了串口初始化函数。

HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);typedef struct
{USART_TypeDef *Instance; UART_InitTypeDef Init; uint8_t *pTxBuffPtr; uint16_t TxXferSize; __IO uint16_t TxXferCount;uint8_t *pRxBuffPtr; uint16_t RxXferSize; __IO uint16_t RxXferCount; DMA_HandleTypeDef *hdmatx; DMA_HandleTypeDef *hdmarx; HAL_LockTypeDef Lock; __IO HAL_UART_StateTypeDef gState; __IO HAL_UART_StateTypeDef RxState;__IO uint32_t ErrorCode; 
}UART_HandleTypeDef;

Instance是结构体指针类型变量,如果是串口11,取值为 USART1 即可。
Init 是 UART_InitTypeDef 结构体类型变量,它是用来设置串口的各个参数,包括波特率,停止位等。

typedef struct
{uint32_t BaudRate; //波特率uint32_t WordLength; //字长uint32_t StopBits; //停止位uint32_t Parity; //奇偶校验uint32_t Mode; //收/发模式设置uint32_t HwFlowCtl; //硬件流设置uint32_t OverSampling; //过采样设置
}UART_InitTypeDef

该结构体第一个参数 BaudRate 为串口波特率,波特率可以说是串口最重要的参数了,它用来确定串口通信的速率。第二个参数 WordLength 为字长,可以设置为 8 位字长或者 9 位字长,这里我们设置为 8 位字长数据格式 UART_WORDLENGTH_8B。第三个参数 StopBits 为停止位设置,可以设置为 1 个停止位或者 2 个停止位,这里我们设置为 1 位停止位 UART_STOPBITS_1。第四个参数 Parity 设定是否需要奇偶校验,我们设定为无奇偶校验位。第五个参数 Mode 为串口模式,可以设置为只收模式,只发模式,或者收发模式。这里我们设置为全双工收发模式。第六个参数 HwFlowCtl 为是否支持硬件流控制,我们设置为无硬件流控制。第七个参数OverSampling 用来设置过采样为 16 倍还是 8 倍。

pTxBuffPtr,TxXferSize 和 TxXferCount 三个变量分别用来设置串口发送的数据缓存指针,发送的数据量和还剩余的要发送的数据量。而接下来的三个变量pRxBuffPtr,RxXferSize 和RxXferCount 则是用来设置接收的数据缓存指针,接收的最大数据量以及还剩余的要接收的数据量。

UART_HandleTypeDef UART1_Handler; //UART 句柄
UART1_Handler.Instance=USART1; //USART1
UART1_Handler.Init.BaudRate=115200; //波特率
UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B; //字长为 8 位格式
UART1_Handler.Init.StopBits=UART_STOPBITS_1; //一个停止位
UART1_Handler.Init.Parity=UART_PARITY_NONE; //无奇偶校验位
UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE; //无硬件流控
UART1_Handler.Init.Mode=UART_MODE_TX_RX; //收发模式
HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能 UART1

函数HAL_UART_Init内部会调用串口使能函数使能相应串口,所以调用了该函数之后就不需要重复使能串口了。

在调用初始化函数HAL_UART_Init内部,会先调用MSP初始化回调函数进行MCU相关初始化,函数为:

void HAL_UART_MspInit(UART_HandleTypeDef *huart);

该函数内部用来编写IO口初始化,时钟使能以及NVIC配置。

使能串口和GPIO口时钟

要使用串口,必须使能串口时钟和使用到的GPIO口时钟。

例如我们要使用串口 1,所以我们必须使能串口 1 时钟和 GPIOA 时钟(串口 1 使用的是 PA9 和 PA10)。

__HAL_RCC_USART1_CLK_ENABLE(); //使能 USART1 时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能 GPIOA 时钟

GPIO口初始化设置以及复用映射配置

在HAL库中IO口初始化参数设置和复用映射配置是在函数HAL_GPIO_Init中一次性完成的。

GPIO_Initure.Pin=GPIO_PIN_9; //PA9
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化 PA9
GPIO_Initure.Pin=GPIO_PIN_10; //PA10
GPIO_Initure.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式!
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化 PA10

开启串口相关中断,配置串口中断优先级

HAL库中定义了一个使能串口中断的标识符__HAL_UART_ENABLE_IT。

使能接收完成中断

__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);

第一个参数为串口句柄,第二个参数为要开启的中断类型值。

HAL_NVIC_EnableIRQ(USART1_IRQn); //使能USART1中断通道
HAL_NVIC_SetPrioority(USART1_IRQn,3,3); //抢占优先级3,子优先级3.

编写中断服务函数

void USART1_IRQHandler(void) ;

串口数据接收和发送

STM32F1 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存在该寄存器内。

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

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

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

相关文章

Linux搭建实验环境搭建(nginx,mysql,java.tomcat)

♥️作者:小刘在C站 ♥️个人主页: 小刘主页 ♥️努力不一定有回报,但一定会有收获加油!一起努力,共赴美好人生! ♥️学习两年总结出的运维经验,以及思科模拟器全套网络实验教程。专栏&#xf…

KMP算法的及其原理

KMP算法 首先 我们先了解一下 KMP算法的作用 str1 和str2 字符串 如果str1中包含str2 那么返回头位置 如果不包含返回-1 首先 我们先加入一个概念: 有一个next数组 next[i]的值为 str2 中 以i-1位置为结尾的字符串中 最长相同前缀后缀为多长(相同前缀后缀 不是对称 aba 中相…

uniapp 小程序如何从主包页面跳转到分包页面

在uniapp开发小程序的时候,“分包”概念一定要提前了解下,具体我就不多说了,自己看下关网的相关配置。 那么,如果从主包页面,跳转至分包的页面呢?如图所示 我的页面->详情页 在我的页面创建好自己的链…

测牛学堂:车载测试面试总结之语音助手相关

车载语音助手的工作原理? 语音助手的工作原理总结下来可以分为4个步骤: 1 通过麦克风采集驾驶员的语音指令 2将语音信号转换为数字信号 3过语音识别技术将语音指令转换为计算机可以理解的指令 4 通过语音合成技术将计算机的回应转换为语音输出 车载…

ARM--LED灯点亮

LED1,LED2,LED3亮灯 .text .global _start_start: /**********LED1点灯--->PE10**************//*初始化RCC章节*/通过RCC_MP_AHB4ENSETR寄存器,使能GPIOs组控制器 0x500000A28[4] 1RCC_INIT: E组和F组一起使能ldr r0,0x50000A28 ldr r1,[r0]orr r1,r1,#(0x3 << 4)s…

vuex和redus的异同

生态系统和语言&#xff1a;Vuex是为Vue.js框架设计的状态管理库&#xff0c;而Redux是一个独立的JavaScript状态管理库&#xff0c;可以与多种框架&#xff08;如React、Angular等&#xff09;一起使用。 架构&#xff1a;Vuex是基于Flux架构的一种实现&#xff0c;而Redux是…

QT 脚本QScriptValue返回QList<QString>

在 QT 脚本中&#xff0c;可以使用 QScriptValue 类来返回 QList<QString> 类型的值。首先&#xff0c;你需要创建一个 QList<QString> 对象&#xff0c;然后将其转换为 QScriptValue 类型。 下面是一个示例代码&#xff1a; // 创建 QList<QString> 对象 …

vue3+ts+elementui-plus二次封装树形表格实现不同层级展开收起的功能

一、TableTreeLevel组件 <template><div classmain><div class"btns"><el-button type"primary" click"expandLevel(1)">展开一级</el-button><el-button type"primary" click"expandLevel(2…

13年测试老鸟,接口性能测试总结整理,据说这是全网最全的...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试按照不同…

【云原生系列】openstack搭建过程及使用

目录 搭建步骤 准备工作 正式部署OpenStack 安装的过程 安装组件如下 登录页面 进入首页 创建实例步骤 上传镜像 配置网络 服务器配置 dashboard配置 密钥配置免密登录 创建实例 绑定浮动ip 免密登录实例 搭建步骤 准备工作 1.关闭防火墙和网关 systemctl dis…

运维高级学习---MySQL备份恢复

数据库备份&#xff0c;数据库为school&#xff0c;素材如下 1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) );创建sco…

【周赛第66期】题目、解答与疑义

目录 感想 判断题1.单选题1.2.&#xff08;有疑义&#xff09; 填空题1. 编程题1.路灯亮度题目题解答案 2.题目题解答案 感想 &#xff08;吐槽&#xff09; 在线IDE真不好用&#xff0c;不说不如CLion&#xff0c;抄一下leetcode的也好啊…… 希望支持比赛时实时看别人通过了…

MATLAB 创建神经网络模型的patternnet和newff函数区别

patternnet和newff都是在MATLAB中用于创建人工神经网络的函数&#xff0c;但它们有一些区别和适用场景。 网络类型&#xff1a; patternnet&#xff1a;用于创建多层感知器&#xff08;MLP&#xff09;类型的神经网络&#xff0c;MLP是一种前馈神经网络&#xff0c;由输入层、若…

Jupyter(CPP内核) || 如何在使用xeus-cling时添加第三方库

国内的搬运真是管杀不管埋。在CSDN上找了半天没有找到在xeus-cling添加第三方库的&#xff0c;最后还是只能自己到处去看英文文档。 先贴上英文文档的链接&#xff1a;Introduction — xeus-cling documentation 构建二进制文件时&#xff0c;通常在构建工具中指定包含目录和第…

抖音SEO源码开发指南:介绍如何开发抖音SEO源码的基本步骤和要点。

一、 抖音SEO源码开发指南&#xff1a; 确定目标&#xff1a;首先要明确开发抖音SEO源码的目标是什么&#xff0c;是提高搜索排名还是增加用户量等。根据不同的目标来制定开发策略和思路。 分析竞争&#xff1a;对于同类产品&#xff0c;要进行竞争分析&#xff0c;了解对手的…

threadLocal如何支持线程池获取

问题: ThreadLocal默认不支持子线程获取&#xff0c;而InheritableThreadLocal支持子线程获取threadLocal值&#xff0c;但是如果使用线程池&#xff0c;核心个数为1则子线程会获取到上一个threadLocal的值。 解决&#xff1a; 1.引入transmittable-thread-local jar <d…

k8s集群部署(使用kubeadm部署工具进行快速部署,相关对应版本为docker20.10.0+k8s1.23.0)

1. 安装要求 在开始之前&#xff0c;部署Kubernetes集群机器需要满足以下几个条件&#xff1a; 一台或多台机器&#xff0c;操作系统 CentOS7.x-86_x64硬件配置&#xff1a;2GB或更多RAM&#xff0c;2个CPU或更多CPU&#xff0c;硬盘20GB或更多可以访问外网&#xff0c;需要拉…

在Mac系统下搭建Selenium环境并驱动Chrome浏览器

本文带领那些使用Mac的童鞋们实现Selenium驱动Chrome浏览器&#xff0c;虽然会有坑&#xff0c;但是我们可以凭借敏捷的身手躲过。下面就开始吧&#xff1a; 安装selenium 打开终端 ->pip安装&#xff08;安装命令&#xff1a;pip3 install selenium&#xff09; 安装浏览…

如何在 SwiftUI 中使用 Touch ID 和 Face ID?

1. 需要通过指纹&#xff0c;面容认证后才能打开 App 2. 添加配置 需要向 Info.plist 文件中添加一个配置&#xff0c;向用户说明为什么要访问 添加 Privacy - Face ID Usage Description 并为其赋予值 $(PRODUCT_NAME) need Touch Id or Face ID permission for app lock 3. …

LeetCode-0727

SQL50 基础 1633 select contest_id,Round(count(*) * 100/(select count(*) from Users),2) as percentage from Users cross join Registerusing(user_id)group by contest_idorder by count(*) desc,contest_id1211 select query_name , Round(avg(rating/position),2) as…