保存现场
异常的处理流程,保存现场会做哪些事情(四大步三小步) ---->CPU自动完成
1.保存CPSR寄存器中的值,到SPSR_<mode>寄存器中
2.修改CPSR寄存器对应的位
1>修改CPSR寄存器对应的状态位(T位)
2>根据需要,禁止相应中断位(I位 / F位)
3>修改CPSR寄存器的模式位,修改为对应的异常模式
3.保存函数的返回地址到LR寄存器中
4.修改PC指针指向对应的异常向量表
恢复现场
1.恢复SPSR_<mode>寄存器中的值给到CPSR寄存器中
2.恢复LR寄存器中的值给到PC
key.h
#ifndef __KEY_H__
#define __KEY_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_uart.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
//事件号
#define EXTI_7 7
#define EXTI_8 8
#define EXTI_9 9
//中断号
#define EXTI7 97
#define EXTI8 98
#define EXTI9 99
//key_exit初始化
void hal_key_exti_init(volatile unsigned int exti,gpio_t* gpiox,volatile unsigned int* style);
//key_gic初始化
void hal_key_gic_init(unsigned int extid);
/********LED*章节*********/
//寄存器的模型
typedef enum{
INPUT, //输入 0
OUTPUT, //输出 1
ALT, //2
ANALOG, //3
}gpio_moder_t;
//寄存器输出类型
typedef enum{
PP, //推挽 0
OD, //开漏 1
}gpio_otyper_t;
//寄存器数据输出速率
typedef enum{
LOW, //低速 00
MED, //中速 01
HIGH, //高速 10
HIGHEST,//超高速 11
}gpio_ospeedr_t;
//上下拉电阻寄存器
typedef enum{
NO_PUPDR, //禁止 0
PU, //上拉 1
PD, //下拉 2
}gpio_pupdr_t;
//高低电平
typedef enum{
GPIO_RESET_T, //低电平 0
GPIO_SET_T, //高电平 1
}gpio_odr_t;
typedef struct{
gpio_moder_t moder; //引脚模式
gpio_otyper_t otyper; //输出类型
gpio_ospeedr_t ospeedr; //输出速度
gpio_pupdr_t pupdr; //是否上下拉
}gpio_init_t;
//LED_GPIO初始化
void hal_led_gpio_init(gpio_t* gpiox,unsigned int pin,gpio_init_t* init);
//LED_操作
void operate_led(gpio_t* gpiox,unsigned int pin);
//LED_ON
void turn_on(gpio_t* gpiox,unsigned int pin);
//LED_OFF
void turn_off(gpio_t* gpiox,unsigned int pin);
#endif
key.c
#include "key.h"
extern void delay_ms(int ms);
//key_exit初始化
void hal_key_exti_init(unsigned int exti,gpio_t* gpiox,volatile unsigned int* style)
{
// RCC章节初始化
// 1.GPIO使能
//
//unsigned int a = (unsigned int)(gpiox - GPIOA)/256;
RCC->MP_AHB4ENSETR |= (0x1 << 5);
// GPIO章节初始化GPIOF_MODER
gpiox->MODER &= (~(0x3 << exti*2));
// EXTI章节初始化
//2.设置EXTI选择寄存器 EXTI_EXITCRx
*(&(EXTI->EXTICR1) + (exti/4)) &= (~(0xff << (exti%4)*8));
*(&(EXTI->EXTICR1) + (exti/4)) |= (5 << (exti%4)*8);
/*
switch(exti/4)
{
case 1:
EXTI->EXTICR2 &= (~(0xff << (exti%4)*8));
EXTI->EXTICR2 |= (0x5 << (exti%4)*8);
break;
case 2:
EXTI->EXTICR3 &= (~(0xff << (exti%4)*8));
EXTI->EXTICR3 |= (0x5 << (exti%4)*8);
break;
case 3:
EXTI->EXTICR4 &= (~(0xff << (exti%4)*8));
EXTI->EXTICR4 |= (0x5 << (exti%4)*8);
break;
}
*/
//2.设置中断通信为下降沿触发EXTI_FTSR1
*style |= (0x1 << exti);
//3.设置中断不屏蔽EXTI_C1IMR1
EXTI->C1IMR1 |= (0x1 << exti);
}
//key_gic初始化
void hal_key_gic_init(unsigned int extid)
{
// GICD章节初始化
//1.设置GICD层组控制器使能
GICD->CTRL |= 0x1;
//2.设置GICD层中断设置使能寄存器
GICD->ISENABLER[extid/32] |= (0x1 << extid%32);
//3.设置GICD层中断优先级寄存器
GICD->IPRIORITYR[extid/4] &= (~(0x1f << ((extid%4)*8+3)));
//4.设置GICD层中断目标分配寄存器
GICD->ITARGETSR[extid/4] &= (~(0x3 << (extid%4)*8));
GICD->ITARGETSR[extid/4] |= (0x1 << (extid%4)*8);
// GICC章节初始化
//1.设置GICC层控制使能寄存器
GICC->CTRL |= (0x1 << 0);
//2.设置GICC层中断优先级寄存器
GICC->PMR |= (0x1f << 3);
}
/********LED*章节*********/
//LED_GPIO初始化
void hal_led_gpio_init(gpio_t* gpiox,unsigned int pin,gpio_init_t* init)
{
// moder; //引脚模式
gpiox->MODER &= (~(0x3 << pin*2));
gpiox->MODER |= (init->moder << pin*2);
// otyper; //输出类型
gpiox->OTYPER &= (~(0x1 << pin));
gpiox->OTYPER |= (init->otyper << pin);
// ospeedr; //输出速度
gpiox->OSPEEDR &= (~(0x3 << pin));
gpiox->OSPEEDR |= (init->ospeedr << pin*2 );
// pupdr; //是否上下拉
gpiox->PUPDR &= (~(0x3 << pin*2));
gpiox->PUPDR |= (init->pupdr << pin*2);
}
//LED_操作
void operate_led(gpio_t* gpiox,unsigned int pin)
{
if((gpiox->ODR & (0x1 << pin)) == 0)
{
turn_on(gpiox,pin);
}
else
{
turn_off(gpiox,pin);
}
}
//LED_ON
void turn_on(gpio_t* gpiox,unsigned int pin)
{
gpiox->ODR |= (0x1 << pin);
}
//LED_OFF
void turn_off(gpio_t* gpiox,unsigned int pin)
{
gpiox->ODR &= (~(0x1 << pin));
}
do_irq.c
#include "key.h"
extern void printf(const char *fmt, ...);
void do_irq(void)
{
unsigned int num;
//获取中断号 IAR[9:0]
num = GICC->IAR & (0x3ff);
//判断中断号
//99--->KEY1
//98--->KEY3
//97--->KEY2
switch(num)
{
case 97:
printf("key2 pressed!!!!!!\n");
//LED2
operate_led(GPIOF,10);
//1.消除EXTI层中断挂起标志位 FPR1 [9] = 1
EXTI->FPR1 |= (0x1 << 7);
//2.消除GICD层中断挂起标志位 ICPENDR[3] |= (0x1 << 3)
GICD->ICPENDR[num/32] |= (0x1 << (num%32));
break;
case 98:
printf("key3 pressed!!!!!!\n");
//LED1
operate_led(GPIOE,10);
//1.消除EXTI层中断挂起标志位 FPR1 [9] = 1
EXTI->FPR1 |= (0x1 << 8);
//2.消除GICD层中断挂起标志位 ICPENDR[3] |= (0x1 << 3)
GICD->ICPENDR[num/32] |= (0x1 << (num%32));
break;
case 99:
printf("key1 pressed!!!!!!\n");
//LED3
operate_led(GPIOE,8);
//1.消除EXTI层中断挂起标志位 FPR1 [9] = 1
EXTI->FPR1 |= (0x1 << 9);
//2.消除GICD层中断挂起标志位 ICPENDR[3] |= (0x1 << 3)
GICD->ICPENDR[num/32] |= (0x1 << (num%32));
break;
}
//3.消除GICC层挂起标志位
GICC->EOIR = num;
}
main.c
#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 hal_exti_init()
{
hal_key_exti_init(EXTI_7,GPIOF,&EXTI->FTSR1);
hal_key_exti_init(EXTI_8,GPIOF,&EXTI->FTSR1);
hal_key_exti_init(EXTI_9,GPIOF,&EXTI->FTSR1);
}
void hal_gic_init()
{
hal_key_gic_init(EXTI7);
hal_key_gic_init(EXTI8);
hal_key_gic_init(EXTI9);
}
void hal_led_init()
{
//RCC使能
RCC->MP_AHB4ENSETR |= (0x3 << 4);
//设定init
gpio_init_t init = {OUTPUT,PP,LOW,NO_PUPDR};
//LED1 PE10
hal_led_gpio_init(GPIOE,10,&init);
//LED2 PF10
hal_led_gpio_init(GPIOF,10,&init);
//LED3 PE8
hal_led_gpio_init(GPIOE,8,&init);
}
int main()
{
//exti初始化
hal_exti_init();
//gic初始化
hal_gic_init();
//led初始化
hal_led_init();
hal_put_string("KEY TEXT READY\n");
while(1){}
return 0;
}
文章来源:https://www.toymoban.com/news/detail-537159.html
文章来源地址https://www.toymoban.com/news/detail-537159.html
到了这里,关于ARM day9 (按键中断控制led亮灭)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!