目录
1、框架了解
2.GPIO
(1)开漏输出与推挽输出
(2)基本知识了解
HAL库函数:
配置流程:
(3)按键实验:STM32的按键开发基础_哔哩哔哩_bilibili
3、时钟
时钟框图
分类
应用
4、中断(2020-12-22)
HAL库提供了5个函数设置NVIC:
(1)HAL_NVIC_SetPriorityGrouping 函数
(2)HAL_NVIC_SetPriority 函数
(3) HAL_NVIC_EnableIRQ 函数
(4) HAL_NVIC_DisableIRQ 函数
(5) HAL_NVIC_SystemReset 函数
中断配置实例--以串口通信(USART1)为实例
EXTI—外部中断/事件控制器:
五、定时器(2020-12-25)
1.概括
2.通用定时器的重要知识点-STM32的定时器开发基础_哔哩哔哩_bilibili
3.关于TIM的配置
六、串口数据收发基础
1.基础知识点
2、HAL库中串口发送和接受的重要函数
概念:
(1)发送函数
(2)接收函数
注:在使用仿真器调试的时候,遇到的一些问题总结(如下):
七、STM32的定时器与串口综合训练
八、ADC模数转化基本原理
案例:
1)一般情况下,我们选用推挽输出,IO口有驱动力;推挽输出的最大特点是可以真正能真正的输出高电平和低电平,在两种电平下都具有驱动能力;
2)开漏输出主要是应对与一些电流型的驱动;开漏输出最主要的特性就是高电平没有驱动能力,需要借助外部上拉电阻才能真正输出高电平;
7组端口,16个引脚,注意每个引脚需要32位字访问;每个IO口由7个寄存器控制
8种模式:输出:推挽、开漏、推挽式复用、开漏式复用;输入:模拟、浮空、下拉、上拉
GPIO电平输出HAL库函数:void HAL_GPIO_WritePin(GPIOx,GPIO_Pin_7,GPIO_PIN_SET/RESET);
电平翻转:HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_3);
延迟函数:HAL_Delay(1000); //延时1s
使能时钟;
配置初始电平
配置引脚属性配置
提前了解:
STM32使用引脚输入的时候,不需要接入电阻,内部有上拉电阻和下拉电阻;
通过反复读取按键输入引脚的信号,识别高低电平判断是否有按键触发;
为什么要去抖动?有时候读到的短暂的电平信号是干扰造成的,所以需要过滤掉,一般使用延迟时间去处理;
读取函数:
GPIO_PinState HAL_GPIO_ReadPin(); GPIO_PinState是引脚状态;
存在的问题:按键中断的消抖如何处理?
参考网址:SysTick、SYSCLK、HCLK、HSI,HSE,LSE_linxi8693的博客-CSDN博客_hse lse
中断优先级分组:抢占式优先级和响应式优先级,每个中断源都需要被指定这两种优先级,另外注意中断嵌套;
HAL_NVIC_SetPriorityGrouping 函数用于设置 NVIC 优先级组, 有一个形参,
可选参数为:
1) NVIC_PRIORITYGROUP_0: 0 位抢占式优先级, 4 位响应优先级;
2) NVIC_PRIORITYGROUP_1: 1 位抢占式优先级, 3 位响应优先级;
3) NVIC_PRIORITYGROUP_2: 2 位抢占式优先级, 2 位响应优先级;
4) NVIC_PRIORITYGROUP_3: 3 位抢占式优先级, 1 位响应优先级;
5) NVIC_PRIORITYGROUP_4: 4 位抢占式优先级, 0 位响应优先级;
HAL_NVIC_SetPriority 函数用于设置一个中断的优先级, 它有三个形参,
第一个为 IRQn_Type 类型参数, 指定中断源;
第二个和第三个形参分别设定中断的抢占式优先级和响应优先级,这个的设
置要与中断组配合使用。
HAL_NVIC_EnableIRQ 函数用于在 NVIC 控制器中使能指定中断, 它有一个形参, 是 IRQn_Type 类型参数
HAL_NVIC_DisableIRQ 函数是在 NVIC 控制器中禁用指定中断, 用法与HAL_NVIC_EnableIRQ 函数相同。 最终通过设置 NVIC_ICER 寄存器值实现功能。
串口通信一般最简单的有两个中断:串口接收中断、 串口发送中断。
配置中断的步骤:
1) 设置优先级组
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2); /* 设置优先级组 */(一般设置为 NVIC_PRIORITYGROUP_2, 即有 2 位抢占式优先级和 2 位响应优先级)
2) 设置 USART1 中断
HAL_NVIC_SetPriority(USART1_IRQn, 1, 0); /* 设置 USART1 中断优先级 */ (设置 USART1 的抢占式优先级为 1, 响应优先级为 0)
HAL_NVIC_EnableIRQ(USART1_IRQn); /* 使能 USART1 中断 */
3) 编写中断服务函数
/* USART1 中断服务函数 */
void USART1_IRQHANDLER(void)
{
HAL_UART_IRQHandler(&husartx); //只要产生 USART1 相关的中断都会“自动的” 运行一次该函数
}
/* 串口接收中断回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
HAL_UART_Transmit(&husart1,&aRxBuffer,1,0);
HAL_UART_Receive_IT(&husart1,&aRxBuffer,1);
}4) 启动接收中断
HAL_UART_Receive_IT(&husart1,&aRxBuffer,1); /*该函数有三个形参,第一个是 USART 句柄类型变量,第二个参数是接收区缓冲区,第三个是接收数目*/ /
EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件,这两个功能从硬件上就有所不同。
对上图解释:
首先我们来看中蓝色虚线指示的电路流程。它是一个产生中断的线路,最终信号流入到 NVIC 控制器内。
编号 1 是输入线, EXTI 控制器有 19 个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个 GPIO,也可以是一些外设的事件。输入线一般是存在电平变化的信号。
编号 2 是一个边沿检测电路,它会根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)对应位的设置来控制信号触发。边沿检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号 1 给编号 3电路,否则输出无效信号 0。而 EXTI_RTSR 和 EXTI_FTSR 两个寄存器可以由控制器设置实现需要检测哪些类型的电平跳变过程,可以是只有上升沿触发、只有下降沿触发或者上升沿和下降沿都触发。
编号 3 电路实际就是一个或门电路,它一个输入来自编号 2 电路,另外一输入来自软件中断事件寄存器(EXTI_SWIER)。 EXTI_SWIER 允许我们通过程序控制就可以启动中断/事件线,这在某些地方非常有用。我们知道或门的作用就是有“1”就为 1,所以这两个输入随便一个有有效信号 1 就可以输出 1 给挂起请求检测器(EXTI_PR)和编号 5 电路。
编号 3 电路输出信号在进入 EXTI_PR 之后,就会把状态值保存在 EXTI_PR 寄存器对应位上, EXTI_PR 实际上就是中断信号的缓冲区。 在编号 3 电路输出为 1时 EXTI_PR 寄存器对应位也自动置 1, 说明有中断发生。 我们在处理完中断事件后必须对该寄存器位写入“1”清除 EXTI_PR 寄存器, 使得对应位为 0, 不然总是会发生中断请求。EXTI_PR 寄存器数据始终会输入到编号 4 的电路。
编号 4 电路是一个与门电路,另外一个输入源是中断屏蔽寄存器(EXTI_IMR)。 因为是一个与门电路, 所以,如果 EXTI_IMR 对应位设置为 0 时,那不管 EXTI_PR 寄存器数据是 1 还是 0,最终编号 4 电路输出的信号都为 0;如果 EXTI_IMR 设置为 1 时,最终编号 4 电路输出输出的信号才由 EXTI_PR 寄存器数据决定,这样我们可以简单的控制EXTI_IMR 来实现是否产生中断的目的。编号 4 电路的输出接入到 NVIC 控制器内, 由 NVIC 控制器调配,进而进行中断事件处理。
现在来看看图中红色虚线指示的电路流程。 它是一个产生事件的线路,最终输出一个脉冲信号。产生事件线路是在编号 3 电路之后与中断线路有所不同,编号 3 之前电路都是共用的。编号 5 电路是一个与门,它一个输入编号 3 电路,另外一个输入来自事件屏蔽寄存器(EXTI_EMR)。如果 EXTI_EMR 设置为 0 时,那不管编号 3 电路的输出信号是 1 还是 0,最终编号 5 电路输出的信号都为 0;如果 EXTI_EMR 设置为 1 时,最终编号 5 电路输出的信号才由编号 3 电路的输出信号决定,这样我们可以简单的控制 EXTI_EMR 来实现是否产生事件的目的。
编号 6 是一个脉冲发生器电路,当它的输入端,即编号 5 电路的输出端,是一个有效信号 1 时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。脉冲信号,就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器 TIM、模拟数字转换器 ADC 等等。产生中断线路目的是把输入信号输入到 NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。
注意外部中断的每一条线同时只能选择一个,也就是说你选择PA0,那么就不要通知选择PB0,因为共用一条线;如下两张图所示:
补充:抢占优先级和响应优先级-网址 (如下三张图所示)
HAL库版本使用注意:
1、系统嘀嗒定时器Sys Tick
集成在内核的定时器,给RTOS提供时钟节拍做时间基准;
2、看门狗定时器
3、实时时钟RTC
4、基本定时器:TIM6\TIM7
5、通用定时器:TIM2\TIM3\TIM4\TIM5
6、高级定时器:TIM1\TIM8
具体引脚电平翻转的时候,是放入到HAL_TIM_PeriodElapsedCallback()函数中,进行定时回调,注意这个函数在main函数中;(参考下面的代码)
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
}
if(htim->Instance == TIM3)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
}
}
/* USER CODE END 0 */
并行通信与串行通信
单工、半双工、全双工 (如下图所示):
单工:一种为单向(或单工)配置,只允许数据向一个传送;
半双工:另一种是半双工配置,允许数据向两个方向中的任一方向传送,但每次只能有一个站发送;
全双工:第三种传送方式是全双工配置,允许同时双向传送数据,因此,全双工配置是一对单向配置,它要求两端的通信设备具有完整和独立的发送和接收能力。
异步串行通信:没有同步时钟的前提下,讲一个字符按照位进行传输的通信方式
波特率:每秒钟传输的二进制位数,如9600bps
TTL电平<----->RS232:MAX3232 SP3232
串口<----->USB接口:CH340 CP2012
USART1_TX与PA9复用,USART1_RX与PA10复用
USART2_TX与PA2复用,USART2_RX与PA3复用
阻塞式是等待接受完数据,才可以进行下一个程序执行,而非阻塞式是通过中断的方式进行,达到中断条件才执行,比如中断一次接受一个字节数据;
阻塞式指的是函数必须执行发送完,才进行下一步,所以一般不建议使用,主要是使用带有中断功能的非阻塞式
举例说明:一共给出了两种方式--阻塞式和非阻塞式
经过CubeMX初始化的STM32代码:
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
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();
}
}
注:在使用仿真器调试的时候,遇到的一些问题总结(如下):
可以看到ST-Link的驱动、连接等一切都正常,但是SW Device始终没有寻找到
最终在网上寻找别人方法的时候,寻找到了问题所在(参考:ST Link设备连接正常,但是keil中找不到已连接的设备_贼菜的菜菜哥的博客-CSDN博客_"if the target is in low power mode, please enable)
解决方法(参考:ST Link设备连接正常,但是keil中找不到已连接的设备_贼菜的菜菜哥的博客-CSDN博客_"if the target is in low power mode, please enable):也就是使用USB转TTL工具结合串口软件,对芯片里面的程序进行擦除。
关于sprintf()函数的用法:字符串格式化函数
注意需要引入 #include “stdio.h”
举例:
具体内容查看:
学习网址:ADC模数转换器的基本工作原理_哔哩哔哩_bilibili