实验要求
1、按下KEY1,LED1亮,再次按下KEY1,LED1灭;
2、按下KEY2,LED2亮,再次按下KEY2,LED2灭;
3、按下KEY3,LED3亮,再次按下KEY3,LED3灭;
实验代码实现
一、头文件
1、gpio.h
#ifndef __GPIO_H__
#define __GPIO_H__
#define RCC_AHB4_ENSETR (*(volatile unsigned int*)0x50000A28)
typedef struct{
volatile unsigned int MODER; //00
volatile unsigned int OTYPER; //04
volatile unsigned int OSPEEDR; //08
volatile unsigned int PUPDR; //0C
volatile unsigned int IDR; //10
volatile unsigned int ODR; //14
}gpio_t;
#define GPIOE ((gpio_t*)0x50006000)
#define GPIOF ((gpio_t*)0x50007000)
//引脚封装
#define GPIO_PIN_0 0
#define GPIO_PIN_1 1
#define GPIO_PIN_2 2
#define GPIO_PIN_3 3
#define GPIO_PIN_4 4
#define GPIO_PIN_5 5
#define GPIO_PIN_6 6
#define GPIO_PIN_7 7
#define GPIO_PIN_8 8
#define GPIO_PIN_9 9
#define GPIO_PIN_10 10
#define GPIO_PIN_11 11
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_14 14
#define GPIO_PIN_15 15
//封装模式寄存器
typedef enum{
INPUT,
OUTPUT,
ALT,
ANALOG,
}gpio_mode_t;
//封装输出类型寄存器
typedef enum{
PP,
OD,
}gpio_otyper_t;
//封装输出速度寄存器
typedef enum{
LOW,
MED,
HIGH,
VERY_HIGH,
}gpio_ospeedr_t;
//封装是否需要上下拉电阻
typedef enum{
NO_PUPD,
PU,
PD,
}gpio_pupdr_t;
//封装输出高低电平
typedef enum{
GPIO_RESET,
GPIO_SET,
}gpio_status_t;
//封装初始化结构体
typedef struct{
gpio_mode_t moder; //模式
gpio_otyper_t otyper; //输出类型
gpio_ospeedr_t speed; //速率
gpio_pupdr_t pupdr; //是否需要上下拉电阻
}gpio_init_t;
//函数功能:初始化GPIO
void hal_gpio_init(gpio_t* gpiox,gpio_init_t* init,unsigned int pin);
//函数功能:操作GPIO引脚,实现亮灭
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status);
void hal_gpio_turn(gpio_t* gpiox,unsigned int pin);
#endif
2、key.h
#ifndef __KEY_H__
#define __KEY_H__
//#include "stm32mp1xx_gpio.h"
#include "gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
//PF9 key1初始化
void key1_gpio_init(); //GPIO章节初始化
void key1_exti_init(); //EXIT章节初始化
void key1_gicd_init(); //GICD层章节初始化
void key1_gicc_init(); //GICC层章节初始化
//PF7 key2初始化
void key2_gpio_init(); //GPIO章节初始化
void key2_exti_init(); //EXIT章节初始化
void key2_gicd_init(); //GICD层章节初始化
void key2_gicc_init(); //GICC层章节初始化
//PF8 key3初始化
void key3_gpio_init(); //GPIO章节初始化
void key3_exti_init(); //EXIT章节初始化
void key3_gicd_init(); //GICD层章节初始化
void key3_gicc_init(); //GICC层章节初始化
#endif
二、初始化函数及功能函数
1、gpio.c
#include "gpio.h"
//初始化GPIO
void hal_gpio_init(gpio_t* gpiox,gpio_init_t* init,unsigned int pin)
{
//设置输出模式
gpiox->MODER &=(~(0x3<<(pin*2)));
gpiox->MODER |=(init->moder<<(pin*2));
//设置输出类型
gpiox->OTYPER &=(~(0x1<<pin));
gpiox->OTYPER |=(init->otyper<<pin);
//设置输出速率
gpiox->OSPEEDR &=(~(0x3<<(pin*2)));
gpiox->OSPEEDR |=(init->speed<<(pin*2));
//是否上下拉电阻
gpiox->PUPDR &=(~(0x3<<(pin*2)));
gpiox->PUPDR |=(init->pupdr<<(pin*2));
}
//函数功能:操作GPIO引脚,实现亮灭
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status)
{
if(status==GPIO_SET)
{
gpiox->ODR |=(0x1<<pin);
}
else
{
gpiox->ODR &=(~(0x1<<pin));
}
}
//按键交替亮灭
void hal_gpio_turn(gpio_t* gpiox,unsigned int pin)
{
if((gpiox->ODR & (0x1<<pin))==0)
{
gpiox->ODR |=(0x1<<pin);
}
else
{
gpiox->ODR &=(~(0x1<<pin));
}
}
2、key.c
#include "key.h"
/************key1初始化*************/
void key1_gpio_init()
{
/****RCC章节初始化*******/
//1.设置GPIOF组时钟使能
RCC->MP_AHB4ENSETR |= (0x1 << 5);
/****GPIO章节初始化*******/
//1.设置PF9引脚为输入模式
GPIOF->MODER &= (~(0x3 << 18));
}
void key1_exti_init()
{
//设置PF9引脚与EXTI9控制器连接
EXTI->EXTICR3 &=(~(0xff)<<8);
EXTI->EXTICR3 |=(0x5<<8);
//设置PF9引脚下降沿触发
EXTI->FTSR1 |=(0x1<<9);
//设置PF9引脚中断不屏蔽
EXTI->C1IMR1 |=(0x1<<9);
}
void key1_gicd_init()
{
//设置全局使能寄存器
GICD->CTRL |=(0x1<<0);
//设置中断使能寄存器
GICD->ISENABLER[3] |=(0x1<<3);
//设置GICD层中断优先级寄存器
GICD->IPRIORITYR[24] &=(0x1f<<27);
GICD->IPRIORITYR[24] |=(0x1<<27);
//设置中断目标分配寄存器
GICD->ITARGETSR[24] |=(0x3<<24);
}
void key1_gicc_init()
{
//设置全局使能寄存器
GICC->CTRL |=(0x1<<0);
//设置GICC层中断优先级值
GICC->PMR &=(~(0x1f)<<3);
GICC->PMR |=(0x4<<3);
}
/************key2初始化*************/
void key2_gpio_init()
{
//1.设置PF7引脚为输入模式
GPIOF->MODER &= (~(0x3 << 14));
}
void key2_exti_init()
{
//设置PF7引脚与EXTI7控制器连接
EXTI->EXTICR2 &=(~(0xff<<24));
EXTI->EXTICR2 |=(0x5<<24);
//设置PF7引脚下降沿触发
EXTI->FTSR1 |=(0x1<<7);
//设置PF7引脚中断不屏蔽
EXTI->C1IMR1 |=(0x1<<7);
}
void key2_gicd_init()
{
//设置全局使能寄存器
GICD->CTRL |=(0x1<<0);
//设置中断使能寄存器
GICD->ISENABLER[3] |=(0x1<<1);
//设置GICD层中断优先级寄存器
GICD->IPRIORITYR[24] &=(0x1f<<11);
GICD->IPRIORITYR[24] |=(0x2<<11);
//设置中断目标分配寄存器
GICD->ITARGETSR[24] |=(0x3<<8);
}
void key2_gicc_init()
{
//设置全局使能寄存器
GICC->CTRL |=(0x1<<0);
//设置GICC层中断优先级值
GICC->PMR &=(~(0x1f)<<3);
GICC->PMR |=(0x5<<3);
}
/************key3初始化*************/
void key3_gpio_init()
{
//1.设置PF8引脚为输入模式
GPIOF->MODER &= (~(0x3 << 16));
}
void key3_exti_init()
{
//设置PF8引脚与EXTI9控制器连接
EXTI->EXTICR3 &=(~(0xff)<<0);
EXTI->EXTICR3 |=(0x5<<0);
//设置PF8引脚下降沿触发
EXTI->FTSR1 |=(0x1<<8);
//设置PF8引脚中断不屏蔽
EXTI->C1IMR1 |=(0x1<<8);
}
void key3_gicd_init()
{
//设置全局使能寄存器
GICD->CTRL |=(0x1<<0);
//设置中断使能寄存器
GICD->ISENABLER[3] |=(0x1<<2);
//设置GICD层中断优先级寄存器
GICD->IPRIORITYR[24] &=(0x1f<<19);
GICD->IPRIORITYR[24] |=(0x3<<19);
//设置中断目标分配寄存器
GICD->ITARGETSR[24] |=(0x3<<16);
}
void key3_gicc_init()
{
//设置全局使能寄存器
GICC->CTRL |=(0x1<<0);
//设置GICC层中断优先级值
GICC->PMR &=(~(0x1f)<<3);
GICC->PMR |=(0x6<<3);
}
三、中断处理函数
do_irq.c
#include "key.h"
extern void printf(const char *fmt, ...);
extern void delay_ms(int ms);
unsigned int i = 0;
void do_irq(void)
{
unsigned int num = 0;
// 获取中断号
num = GICC->IAR;
switch (num)
{
case 97:
delay_ms(500);
printf("key2 is pressed \n");
hal_gpio_turn(GPIOF, GPIO_PIN_10);
// 清除EXTI层中断挂起标志位
EXTI->FPR1 |= (0x1 << 7);
// 清除GICD层中断挂起标志位
GICD->ICPENDR[3] |= (0x1 << 1);
break;
case 98:
delay_ms(500);
printf("key3 is pressed \n");
hal_gpio_turn(GPIOE, GPIO_PIN_8);
// 清除EXTI层中断挂起标志位
EXTI->FPR1 |= (0x1 << 8);
// 清除GICD层中断挂起标志位
GICD->ICPENDR[3] |= (0x1 << 2);
break;
case 99:
delay_ms(500);
printf("key1 is pressed \n");
hal_gpio_turn(GPIOE, GPIO_PIN_10);
// 清除EXTI层中断挂起标志位
EXTI->FPR1 |= (0x1 << 9);
// 清除GICD层中断挂起标志位
GICD->ICPENDR[3] |= (0x1 << 3);
break;
}
// 清除中断号
GICC->EOIR &= (0x3ff << 0);
GICC->EOIR |= num;
}
四、主函数
main.c文章来源:https://www.toymoban.com/news/detail-767232.html
#include "key.h"
extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
int i,j;
for(i = 0; i < ms;i++)
for (j = 0; j < 1800; j++);
}
void LED_init()
{
//时钟使能
RCC_AHB4_ENSETR |=(0x3<<4);
//RCC_AHB4_ENSETR |=(0x1<<5);
//初始化结构体
gpio_init_t init={OUTPUT,PP,LOW,NO_PUPD};
//LED初始化
hal_gpio_init(GPIOE,&init,GPIO_PIN_10); //LED1
hal_gpio_init(GPIOF,&init,GPIO_PIN_10); //LED2
hal_gpio_init(GPIOE,&init,GPIO_PIN_8); //LED3
}
int main()
{
LED_init();
/**********key1初始化************/
key1_exti_init();
key1_gicc_init();
key1_gicd_init();
key1_gpio_init();
/**********key2初始化************/
key2_exti_init();
key2_gicc_init();
key2_gicd_init();
key2_gpio_init();
/**********key3初始化************/
key3_exti_init();
key3_gicc_init();
key3_gicd_init();
key3_gpio_init();
while(1)
{
}
return 0;
}
实验结果
依次按下key3、key2、key1、key2
结果应该为LED3、LED1亮,LED2灭;
文章来源地址https://www.toymoban.com/news/detail-767232.html
到了这里,关于【stm32----按键中断实验,按键控制LED灯】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!