STM32 HAL库编程(2)—— 外部中断、ADC

STM32 HAL库编程(2)—— 外部中断、ADC

学习外部中断和ADC,使用战舰mini开发板


前言

  • 外部中断:指的是某一个引脚从低电平变高电平,或高电平变低电平而产生的中断,区别于定时器内部中断。这个常用于按键读取,按键按下去之后,比如从高电平变成低电平,自动就跳到了中断函数。如果没有中断函数,就需要一直在while中读取按键的高低电平,这种轮询方式效率太低。
  • ADC:模数转换,将模拟信号转换位数字信号。STM32可以读取的模拟电压位0-3.3V,12位精度(即模拟信号的0-3.3 转换为 数字信号的0-4095)。

一、新建工程

1. 查看手册,看芯片型号和LED、按键引脚

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 使用CUBEMX新建工程

依照步骤选择CPU、选择debug方式、配置时钟、配置LED引脚、最后工作来进行。并且在生成的代码上测试LED闪烁代码,观察是否正常运行。

二、配置按键引脚为外部中断

1. 配置引脚为外部中断

  • 根据上方的原理图,设置三个按键为外部中断方式,外部中断的英文名为EXTI。在配置中断时,会发现EXTI后有一个中断号,这是与引脚号对应的,例如PA0就是EXTI0,PC5就是EXTI5,有中断号才能判断是哪一个引脚产生的中断
  • 实际上,PA0,PB0,PC0等都是共用中断EXTI0的,其他EXTI1、EXTI2等也都是这样。这样做的目的是减少外部中断数量,单片机速度本来就不高,太多的中断会降低运行效率。
  • 那如果PA0、PB0都用到了中断EXTI0,如何判断出中断是由哪一个引脚产生的呢?一个办法就是在产生中断后,在中断函数中读取PA0和PB0的引脚高低电平,从而判断出哪一个引脚发生了中断。
  • 产生了中断,代码会自动跳到中断函数中,需要运行的代码就放在中断函数中,比如转变LED灯的亮灭。在以前的库函数中,中断0-4由单独的中断函数,中断5-9共用一个中断函数,中断10-15也共用一个中断函数,但HAL库中,所有的外部中断共用一个中断函数。进入中断函数后,首先需要通过**中断句柄(中断号)**判断是哪一个中断。
    在这里插入图片描述

2. 配置中断方式

  • 中断方式:上升沿中断下降沿中断,最常用的两种中断方式。上升沿中断就是当引脚从低电平变成高电平时,会产生一个中断,下降沿中断反之。比如一个按键,没按的时候时低电平,按下去的时候是高电平,那我就配置这个引脚的中断方式为上升沿中断。
  • 引脚上拉下拉:一个引脚默认既不是高电平也不是低电平,这样就可能导致中断异常。为稳定中断,我们需要通过上拉或下拉的方式,让引脚在平时的状态下,保持高电平或低电平。原理图中按键都没有设置外部上拉或者下拉,我们需要配置KEY0和KEY1为上拉,WK_UP为下拉
  • 三个按键的中断配置为:PA0:标签WK_UP,上升沿中断,引脚下拉;PC5:标签KEY0,下降沿中断,引脚上拉;PA15:标签KEY1,下降沿中断,引脚上拉。

在这里插入图片描述
配置完成后的图如下图:可以顺带设置LED的标签为LED0和LED1
在这里插入图片描述

3. 配置中断优先级

在这里插入图片描述

三、代码介绍

在这里插入图片描述
在这里插入图片描述

  • 右击上方的中断提交函数,点击查看该函数的定义:
    在这里插入图片描述
    在这里插入图片描述

四、编写代码

1. 中断回调函数

代码为不同引脚让LED灯发生变化,代码如下。只需要将中断回调函数复制到放在合适的位置,每次中断就会自动调用这个函数。
在这里插入图片描述

2. 烧录测试

五、代码优化

问题:对于按键而言,会有按键抖动,即在按下去的时候,会产生多个上升沿和下降沿,导致多次产生中断。
解决:一个是通过添加滤波电容的方式,硬件方式消去按键的抖动信号;另一个办法是添加延时并判断,软件方式消去抖动。由于电路已经设计,这里使用软件方式。
在这里插入图片描述

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    
    
	if(GPIO_Pin == WK_UP_Pin)		// 按键WK_UP中断
	{
    
    
		HAL_Delay(20);
		if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port, WK_UP_Pin) == 1)
		{
    
    
			HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);		// 更改LED0亮灭
		}
	}
	else if(GPIO_Pin == KEY0_Pin)		// KEY0中断
	{
    
    
		HAL_Delay(20);
		if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == 0)
		{
    
    
			HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);		// 更改LED1亮灭
		}
	}
	else if(GPIO_Pin == KEY1_Pin)		// KEY1中断
	{
    
    
		HAL_Delay(20);
		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
		{
    
    
			HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);		// 更改LED0亮灭
			HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);		// 更改LED1亮灭
		}
	}
	
}

六、串口配置

1. 串口介绍

  • 串口是单片机中很常见的一种通信方式,可以与电脑通信、与传感器通信、与其他单片机通信等。
  • 异步串口(UART)是用的最多的一种串口,仅包含TX和RX两条通信线。

2. 串口配置

  • 可以看到,对于这个stm32而言,有很多个串口。这里我们选择串口1,并配置为异步串口,波特率为115200。
  • 对于一个串口,它可以映射到不同的引脚上,除了这里使用的PA9和PA10,串口1还可以使用PB6和PB7,
    在这里插入图片描述
    在这里插入图片描述

3. 串口代码介绍

在这里插入图片描述

4. 编写串口代码1——发送数据

发送数据使用以下函数进行:
在这里插入图片描述
在main中编写以下代码,每隔1s发送hello给电脑:
在这里插入图片描述

uint8_t buff[10] = {
    
    "hello\r\n"};

	HAL_UART_Transmit(&huart1, buff, 10, 1000);
	HAL_Delay(1000);

连接USB到电脑,发开串口助手,注意选择对应的波特率115200。

5. 使用printf发送数据

在C语言学习中,printf可以很方便的输出内容,例如printf(“a is %d”, a)可以输出a的值。为使用printf,需要在代码中添加stdio.h库和重定向函数,如下图。
在这里插入图片描述

#include "stdio.h"

// 重定向函数,可以使用printf
int fputc(int ch,FILE *f)
{
    
    
    uint8_t temp[1]={
    
    ch};
    HAL_UART_Transmit(&huart1,temp,1,2);       
}

在while中测试printf,输出一些内容测试一下。

猜你喜欢

转载自blog.csdn.net/Hot_Ant/article/details/113776708