用外部中断实现四个按键控制分别一个七段数码管的四个位选并按一次按键数字递增,基于STM32F103R6
时间: 2024-05-23 16:14:44 浏览: 16
本文介绍如何使用STM32F103R6单片机的外部中断功能,实现四个按键控制分别一个七段数码管的四个位选,并按一次按键数字递增的功能。
硬件准备:
- STM32F103R6单片机开发板
- 4个按键
- 4个共阳七段数码管
- 杜邦线若干
将4个按键和4个共阳七段数码管按照如下图连接:
![image-20211020102454857](https://i.loli.net/2021/10/20/4ga8MwWz6UJ7Yf2.png)
其中,按键连接到开发板的GPIO口,数码管连接到开发板的GPIO口和定时器TIM2的输出比较通道1(OC1)。
软件准备:
- Keil C51编译器
- STM32F10x标准外设库
编写程序:
首先需要在Keil C51编译器中创建一个新的工程,并将STM32F10x标准外设库添加到工程中。
在代码中需要定义四个宏,分别代表四个按键所连接的GPIO口和四个七段数码管的位选GPIO口。同时需要定义一个变量代表当前显示的数字。
```c
// 定义GPIO口
#define KEY1 GPIO_Pin_0
#define KEY2 GPIO_Pin_1
#define KEY3 GPIO_Pin_2
#define KEY4 GPIO_Pin_3
#define DIG1 GPIO_Pin_4
#define DIG2 GPIO_Pin_5
#define DIG3 GPIO_Pin_6
#define DIG4 GPIO_Pin_7
// 当前显示的数字
unsigned char num = 0;
```
在主函数中需要初始化所有的GPIO口和外部中断。
```c
int main(void)
{
// 初始化所有GPIO口
GPIO_Configuration();
// 初始化外部中断
EXTI_Configuration();
while (1)
{
}
}
```
初始化函数中需要对GPIO口进行初始化,使其能够输入或输出,并设置外部中断。
```c
// GPIO初始化函数
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIOA和GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
// 配置KEY1、KEY2、KEY3、KEY4为输入模式
GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2 | KEY3 | KEY4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置数码管位选为输出模式
GPIO_InitStructure.GPIO_Pin = DIG1 | DIG2 | DIG3 | DIG4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
// 外部中断初始化函数
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// 配置KEY1、KEY2、KEY3、KEY4为中断源
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);
// 配置外部中断线
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 配置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
```
在中断服务函数中需要根据按键编号更新当前显示的数字,并将数字通过四个位选GPIO口显示在四个七段数码管上。
```c
// KEY1中断服务函数
void EXTI0_IRQHandler(void)
{
if (GPIO_ReadInputDataBit(GPIOA, KEY1) == 0) // 按键按下
{
num++;
if (num > 9) num = 0;
}
GPIO_SetBits(GPIOB, DIG1); // 关闭所有数码管
GPIO_ResetBits(GPIOB, DIG2 | DIG3 | DIG4); // 打开第1个数码管
GPIO_Write(GPIOB, num_table[num]); // 显示数字
EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志
}
// KEY2中断服务函数
void EXTI1_IRQHandler(void)
{
if (GPIO_ReadInputDataBit(GPIOA, KEY2) == 0) // 按键按下
{
num++;
if (num > 9) num = 0;
}
GPIO_SetBits(GPIOB, DIG2); // 关闭所有数码管
GPIO_ResetBits(GPIOB, DIG1 | DIG3 | DIG4); // 打开第2个数码管
GPIO_Write(GPIOB, num_table[num]); // 显示数字
EXTI_ClearITPendingBit(EXTI_Line1); // 清除中断标志
}
// KEY3中断服务函数
void EXTI2_IRQHandler(void)
{
if (GPIO_ReadInputDataBit(GPIOA, KEY3) == 0) // 按键按下
{
num++;
if (num > 9) num = 0;
}
GPIO_SetBits(GPIOB, DIG3); // 关闭所有数码管
GPIO_ResetBits(GPIOB, DIG1 | DIG2 | DIG4); // 打开第3个数码管
GPIO_Write(GPIOB, num_table[num]); // 显示数字
EXTI_ClearITPendingBit(EXTI_Line2); // 清除中断标志
}
// KEY4中断服务函数
void EXTI3_IRQHandler(void)
{
if (GPIO_ReadInputDataBit(GPIOA, KEY4) == 0) // 按键按下
{
num++;
if (num > 9) num = 0;
}
GPIO_SetBits(GPIOB, DIG4); // 关闭所有数码管
GPIO_ResetBits(GPIOB, DIG1 | DIG2 | DIG3); // 打开第4个数码管
GPIO_Write(GPIOB, num_table[num]); // 显示数字
EXTI_ClearITPendingBit(EXTI_Line3); // 清除中断标志
}
```
在主函数中需要定义一个数字表,用于将数字转换成七段数码管的显示码。
```c
// 数字表
unsigned char num_table[10] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F // 9
};
```
编译程序,并下载到STM32F103R6开发板中运行。按下四个按键中的任意一个,数码管上的数字会递增,直到达到9后又从0开始。
完整代码如下:
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)