stm32 HAL库笔记(一)——串口的操作
昨天分析了普通io口的使用,和初始化代码流程,回顾一下,首先定义一个配置io口功能的结构体,然后开启时钟,再去配置这个结构体里面的各个成员变量,每个成员变量都有很多种选择,可以看各个成员变量 后面的注释,找到可选的配置即可,把这个结构体配置完了之后,把它扔到hal库提供的io口初始化函数中,另一个参数是ABC。。。中的一个,指定端口。
同理,操作串口的流程大致和上面叙述的过程差不多,但是串口多了收发数据,中断等等功能。在Cubemx里面配置串口,然后打开工程,跟踪代码,了解详细的过程。首先,串口的初始化代码部分:
UART_HandleTypeDef UART1_Handler; //UART句柄
UART1_Handler.Instance=USART1; // 指定串口
UART1_Handler.Init.BaudRate=bound; // 波特率
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); // 初始化这个串口
大概过程和配置io口类似,不再细说。但是要进到串口初始化函数中去看一下,发现会调用这个函数,但是这个函数的weak虚函数,虚函数的概念百度一下即可,大概就是用户需要自己重新写他的功能:
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
{
...
HAL_UART_MspInit(huart);
...
}
...
__weak void HAL_UART_MspInit(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_MspInit could be implemented in the user file
*/
}
看一下注释,大意就是与回调有关系,cubemx给做了,看一下:
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct; /**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_NVIC_SetPriority(USART1_IRQn, , );
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
从代码可以功能:配置io口,刚才的初始化串口函数,只是配置了串口的波特率、数据位等等,但是还没有配置串口所在的引脚,在这里配置,注释很清楚,A9 A10是这个川口的T和R,然后配置速度、复用模式,复用为什么,这个复用说一下。举个例子,如果有的用户想用很多普通io口,不用串口啊、SPI接口啊。有的呢,就用串口和spi接口,那厂家要是想满足这些用户,就要给片上,多加io口,加串口,等等其他的引脚,那么就可能会使脚很多,芯片大或者制造成本高,于是厂家就用100根引脚(407某型号)然后让一些脚有多个功能,既可以干这个也可以做那个,至于到底做什么,用户决定,这样就是脚会少,同时满足大多数用户的需求。片上除了电源等口,剩下的,基本都可以当作普通的io口用,同时也可以做串口、SPI等等功能,这叫复用。刚才说到,我们只配置了串口功能,还没配置这个串口所在的io口为复用,复用为串口。在这个回调初始化中定义了。同时,也配置了,中断优先号,中断使能。
那么中断怎么用呢?这里我直接参考了正点原子的教程:
// 串口号 接受缓冲数组 接收量:自己宏定义或者直接写数就行
HAL_UART_Receive_IT(&huart1, (u8 *)aRxBuffer1, RXBUFFERSIZE1);
//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
这个函数放在串口初始化中,就使能了串口接收中断,串口接收到数据,这个函数就把数据放在我们定义的接受缓冲数组中,可能一次过来很多,但是我们只接收RXBUFFERSIZ1个,这个还要配合回中断调用函数,在利用JY901模块收再说,下面再说。如果想深入了解的话,还得进入这个函数去看看,发现他会调用函数:__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);,其实这是一个宏定义,如下:
#define UART_IT_MASK ((uint32_t)0x0000FFFFU)
#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == 1U)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
(((__INTERRUPT__) >> 28U) == 2U)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))
很复杂,如果带参数宏定义,把参数带入进来,然后对比寄存器,配置中断的,这个就不详细写了,其实如果不了解寄存器的话也可用起来的。(刚才分析了一下,感觉这块还是要一步一步的写出来,以后自己看还是很省事的,但是时间紧迫,以后在回过头来补充)。
那如果发生了中断呢,刚才配置的是USART1_IRQn,我们去查一下他,发现:
DCD USART1_IRQHandler ; USART1 void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
串口1的中断处理函数是USART1_IRQHandler,他又调用了HAL_UART_IRQHandler(&huart1):
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
...
UART_Receive_IT(huart); //读数据寄存器,并且调用回调函数
....
} static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
HAL_UART_RxCpltCallback(huart); // 回调函数,虚函数自己定义
} __weak 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
*/
}
那么我们接收到了传到串口的数据后我们利用hal库函数也得到了,然后我们想利用一下这些数据做点什么怎么办呢?这个接收中断回调函数就来了,接收到数据后,执行中断函数,中断函数的功能是读取数据寄存器,把数据放在我们指定的数组中,然后调用这个回调函数,我们在这各回调函数中就可以操作这些数据了(读取到了),(但是根据正点院子教程所说,这么做效率不高,入门的话,就这么做就行,毕竟官方的)。
if(huart->Instance == USART1)//如果是串口1
{
a = aRxBuffer1[];
HAL_UART_Receive_IT(&huart1, (u8 *)aRxBuffer1, RXBUFFERSIZE1);
}
这里要仔细说一下,我这么写是来一个中断,读取一个字节(之前宏的),但是我用的JY901模块是一次发送11个数据,每条11个字节,我就要中断11次,想来效率不高,该进:把RXBUFFERSIZE1定义为11,一条指令包过来11个字节全部存储在aRxBuffer1中,就行了,然后继续接收使能。
概过程就是这样,这里面并没有发送中断,目前我还没用,只接受就行了,抓紧调四轴。
stm32 HAL库笔记(一)——串口的操作的更多相关文章
- stm32 HAL库笔记(零)
最近在设计四旋翼飞行器,用stm32f407,有三种开发方式可以选择:一.寄存器开发.二:库函数开发.三:HAL库开发,考虑了一下,选择了HAL库,原因如下: 1. 寄存器开发相对较慢,寄存器很多,配 ...
- stm32 HAL库笔记(一)——普通IO口
今天介HAL库操作普通IO口,就是输入/输出. 如果用CubeMX配置io工程,打开以后可以看到如下代码: GPIO_InitTypeDef GPIO_Initure; __HAL_RCC_GPIOB ...
- 【情人节选帽子】TCS34725颜色传感器和Python图形界面编程(STM32 HAL库)
截图 描述: l STM32 HAL库编程 l 使用模拟IIC通信,方便程序移植 l Python界面编写,蘑菇头的帽子是什么颜色 l STM32 HAL库串口通信 l Python界面使用 ...
- STM32 HAL库与标准库的区别_浅谈句柄、MSP函数、Callback函数
最近笔者开始学习STM32的HAL库,由于以前一直用标准库进行开发,于是发现了HAL库几点好玩的地方,在此分享. 1.句柄在STM32的标准库中,假设我们要初始化一个外设(这里以USART为例)我们首 ...
- 【有趣的全彩LED | 编程】用STM32 HAL库让WS2812B为你所动
一.效果展示 观看演示效果:https://www.bilibili.com/video/BV1dv411Y7x3 使用STM32 HAL库编程 PWM+DMA控制输出,CubeMX生成初始工程 实现 ...
- 【春节歌曲回味 | STM32小音乐盒 】PWM+定时器驱动无源蜂鸣器(STM32 HAL库)
l STM32通过PWM与定时器方式控制无源蜂鸣器鸣响 l STM32小音乐盒,歌曲进度条图形显示与百分比显示,歌曲切换 l 编程使用STM32 HAL库 l IIC OLED界面编程,动画实 ...
- STM32 HAL库详解 及 手动移植
源: STM32 HAL库详解 及 手动移植
- 【书籍连载】《STM32 HAL 库开发实战指南—基于F7》-第一章
从今天起,每天开始连载一章<STM32 HAL 库开发实战指南—基于F7>.欢迎各位阅读.点评.学习. 第1章 如何使用本书 1.1 本书的参考资料 本书参考资料为:<STM32 ...
- STM32 HAL库 UART 串口读写功能笔记
https://www.cnblogs.com/Mysterious/p/4804188.html STM32L0 HAL库 UART 串口读写功能 串口发送功能: uint8_t TxData[10 ...
随机推荐
- 入学java的第一天
登录http://www.oracle.com,下载JDK(J2SE) JDK 1.0,1.1,1.2,1.3,1.4 1.5(JDK5.0) 支持注解.支持泛型 1.6(JDK6.0)Server2 ...
- 5. Web vulnerability scanners (网页漏洞扫描器 20个)
5. Web vulnerability scanners (网页漏洞扫描器 20个) Burp Suite是攻击Web应用程序的集成平台. 它包含各种工具,它们之间有许多接口,旨在方便和加快攻击应用 ...
- 改变一下主要发博的方向吧...转scratch!
因为expression2实在是没什么好说的,BUI,水滴鱼大佬还有其他贴吧上的大佬,实在是多得不行,我一个小人物也说不了什么,然而scratch我却可以多发发脚本,思路,美工啊等等.所以以后我就主要 ...
- 货币转换 I
描述 人民币和美元是世界上通用的两种货币之一,写一个程序进行货币间币值转换,其中: 人民币和美元间汇率固定为:1美元 = 6.78人民币. 程序可以接受人民币或美元输入,转换为美元或人民币输出.人民币 ...
- [随笔][Java][something]
import 只能导入包中的类,不能导入某个包.为了方便,一般不导入单独的类,而是导入包下的所有类.import java.util.*; 包java.lang中的所有类默认由编译器全部导入了,不必手 ...
- map集合实现缓存
package com.linmingliang.myblog.utils; import java.util.Map;import java.util.concurrent.ConcurrentHa ...
- Python(三)——文件操作
在我们用语言的过程中,比如要往文件内进行读写,那么势必要进行文件操作,那么咋操作呢?用眼睛直接看么?今天就定个小目标,把文件读写那些事扯一扯 文件操作 把大象放进冰箱分几步? 第一步:打开冰箱 第二步 ...
- python selenium 处理时间日期控件(十六)
测试过程中经常遇到时间控件,需要我们来选择日期,一般处理时间控件通过层级定位来操作或者通过调用js来实现. 1.首先我们看一下如何通过层级定位来操作时间控件. 通过示例图可以看到,日期控件是无法输入日 ...
- Windows 10 RS4 无法完全关闭Hyper-V导致Virtual Box 虚拟机无法启动
https://www.jianshu.com/p/2e3429d45aea 起因 因为需要使用Virtual Box做一些工作,卸载了Windows Docker.按照经验,关闭了Hyper-V. ...
- 《重构-改善既有代码的设计》学习笔记---Replace Temp with Query(以查询取代临时变量)
临时变量的问题在于: 它们是暂时的,而且只能在所属函数内使用.由于临时变量只在所属函数内可见,所以,如果很多地方都在用这个临时变量,就会驱使你写出更长的函数.如果把临时变量替换为一个查询,那么其他函数 ...