MPU中断处理

key_init.h

cpp 复制代码
#ifndef __KEY_INIT_H_

#define __KEY_INIT_H_

#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"

void key_init();

#endif

key_init.c

cpp 复制代码
#include "key_init.h"

void key_init(){
    
    /**
     * key1 引脚 PF9
     * key2 引脚 PF7
     * kry3 引脚 PF8
    */

    //使能PF时钟
    RCC->MP_AHB4ENSETR |= (0X1 << 5);
    //设置引脚模式位输入,00为输入
    GPIOF->MODER &= (~(0X3 << 18)); //key1
    GPIOF->MODER &= (~(0X3 << 14)); //key2
    GPIOF->MODER &= (~(0X3 << 16)); //key3
    
    /**
     * GPIO的外设的组别有A-K组,每一个GPIO组有16个引脚
     * 这16个引脚都有对应的EXIT管理:EXIT0-15
     * EXIT又是由 4 个 EXITCR管理(EXTICR 0-3)
     * EXTICR 0 : EXTI 0-3
     * EXTICR 1 : EXTI 4-7
     * EXTICR 2 : EXTI 8-11
     * EXTICR 3 : EXTI 12-15
     * key1 PE9->EXTI9->EXTICR3
     * key2 PE7->EXTI7->EXTICR2
     * key3 PE8->EXTI8->EXTICR3
     */
    //设置对应引脚得EXTI事件
    //清空
    EXTI->EXTICR3 &= (~(0XFF << 8)); //key1
    EXTI->EXTICR2 &= (~(0XFF << 24));//key2
    EXTI->EXTICR3 &= (~(0XFF << 0)); //key3
    //设置为PF外设触发
    EXTI->EXTICR3 |= (0X5 << 8); //key1
    EXTI->EXTICR2 |= (0X5 << 24);//key2
    EXTI->EXTICR3 |= (0X5 << 0); //key3

    //设置下降沿检测,也就是引脚电平下降时触发
    EXTI->FTSR1 |= (0X1 << 9); //key1
    EXTI->FTSR1 |= (0X1 << 7); //key2
    EXTI->FTSR1 |= (0X1 << 8); //key3

    //取消事件屏蔽
    EXTI->C1IMR1 |= (0X1 << 9); //key1
    EXTI->C1IMR1 |= (0X1 << 7); //key2
    EXTI->C1IMR1 |= (0X1 << 8); //key3

    /**
     * 一共有287个中断事件
     * 每个寄存器有32位,也就是有9个寄存器去管理
     * key1->EXTI9-> 99 -> 99/32=3余3 -> 第 3 个寄存器的第3位
     * key2->EXTI7-> 97 -> 99/32=3余1 -> 第 3 个寄存器的第1位
     * key3->EXTI8-> 98 -> 99/32=3余2 -> 第 3 个寄存器的第2位
     * 
    */
    //全局使能对应中断号
    GICD->ISENABLER[3] |= (0X1 << 3); //key1
    GICD->ISENABLER[3] |= (0X1 << 1); //key2
    GICD->ISENABLER[3] |= (0X1 << 2); //key3

    /** 
     * 一共有287个中断事件
     * 每个中断事件的优先级容量为5位,也就是说只有32个优先级
     * 但是每个寄存器只有32位,还要字节对齐,所以无法容纳足够 5个 中断事件,只能容纳 4个
     * 而且设置的字节偏移了 3 位,所以
     * key1->99-> 99/4=24余3 -> IPRIORITYR 24 的第 3 个
     * key1->97-> 97/4=24余1 -> IPRIORITYR 24 的第 1 个
     * key1->98-> 98/4=24余2 -> IPRIORITYR 24 的第 2 个
     * 将其设置为 0 就是最高优先级
     */
    //设置中断优先级
    GICD->IPRIORITYR[24] &= (~(0X1F << 27)); //key1
    GICD->IPRIORITYR[24] &= (~(0X1F << 11)); //key2
    GICD->IPRIORITYR[24] &= (~(0X1F << 19)); //key3

    /**
     * 一共287个中断事件
     * 每个寄存器只存放了4个事件,每 2 位对应一个事件,字节对齐,其偏移量位0
     * 01:处理器1处理事件
     * 10:处理器2处理事件
     * key1->99-> 99/4=24余3 -> IPRIORITYR 24 的第 3 个
     * key1->97-> 97/4=24余1 -> IPRIORITYR 24 的第 1 个
     * key1->98-> 98/4=24余2 -> IPRIORITYR 24 的第 2 个
     */
    //设置处理中断的处理器
    GICD->ITARGETSR[24] |= (0X1 << 24); //key1
    GICD->ITARGETSR[24] |= (0X1 << 8);  //key2
    GICD->ITARGETSR[24] |= (0X1 << 16); //key3

    //允许中断可以被转发到核0中
    GICD->CTRL |= (0X1 << 0);

    //设置中断的优先级掩码为最低优先级
    //当优先级掩码比中断优先级底时,中断才能转发
    GICC->PMR |= (0X1F << 3);

    //允许优先级掩码中断转发到核0中
    GICC->CTRL |= (0X1 << 0);
}

module.h

cpp 复制代码
#ifndef __MODULE_H_

#define __MODULE_H_

#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"

typedef enum{
    LED_1,
    LED_2,
    LED_3
}Led_t;

typedef enum{
    CMD_ON,
    CMD_OFF
}Cmd_t;

void module_init();
void module_led_ctrl(Led_t led, Cmd_t cmd);
void module_fan_ctrl(Cmd_t cmd);
void module_motor_ctrl(Cmd_t cmd);
void module_buzzer_ctrl(Cmd_t cmd);


#endif

module.c

cpp 复制代码
#include "module.h"


void module_init(){
    //时钟使能
    RCC->MP_AHB4ENSETR |= (0X1 << 1); //PB
    RCC->MP_AHB4ENSETR |= (0X1 << 4); //PE
    RCC->MP_AHB4ENSETR |= (0X1 << 5); //PF
    //模式选择
    //模式位复位
    GPIOE->MODER &= (~(0X3 << 20)); //LED1
    GPIOF->MODER &= (~(0X3 << 20)); //LED2
    GPIOE->MODER &= (~(0X3 << 16)); //LED3
    GPIOE->MODER &= (~(0X3 << 18)); //FAN
    GPIOF->MODER &= (~(0X3 << 12)); //MOTOR
    GPIOB->MODER &= (~(0X3 << 12)); //BUZZER
    //模式位置位
    GPIOE->MODER |= (0X1 << 20); //LED1
    GPIOF->MODER |= (0X1 << 20); //LED2
    GPIOE->MODER |= (0X1 << 16); //LED3
    GPIOE->MODER |= (0X1 << 18); //FAN
    GPIOF->MODER |= (0X1 << 12); //MOTOR
    GPIOB->MODER |= (0X1 << 12); //BUZZER
    
    //推挽输出设置
    GPIOE->OTYPER &= (~(0X3 << 10)); //LED1
    GPIOF->OTYPER &= (~(0X3 << 10)); //LED2
    GPIOE->OTYPER &= (~(0X3 << 8));  //LED3
    GPIOE->OTYPER &= (~(0X3 << 9));  //FAN
    GPIOF->OTYPER &= (~(0X3 << 6));  //MOTOR
    GPIOB->OTYPER &= (~(0X3 << 6));  //BUZZER

    //低速输出设置    
    GPIOE->OSPEEDR &= (~(0X3 << 20)); //LED1
    GPIOF->OSPEEDR &= (~(0X3 << 20)); //LED2
    GPIOE->OSPEEDR &= (~(0X3 << 16)); //LED3
    GPIOE->OSPEEDR &= (~(0X3 << 18)); //FAN
    GPIOF->OSPEEDR &= (~(0X3 << 12)); //MOTOR
    GPIOB->OSPEEDR &= (~(0X3 << 12)); //BUZZER
    
    //无上下拉电阻设置
    GPIOE->PUPDR &= (~(0X3 << 20)); //LED1
    GPIOF->PUPDR &= (~(0X3 << 20)); //LED2
    GPIOE->PUPDR &= (~(0X3 << 16)); //LED3
    GPIOE->PUPDR &= (~(0X3 << 18)); //FAN
    GPIOF->PUPDR &= (~(0X3 << 12)); //MOTOR
    GPIOB->PUPDR &= (~(0X3 << 12)); //BUZZER
}
//LED灯模组
void module_led_ctrl(Led_t led, Cmd_t cmd){
    switch(led){
        case LED_1:
        if(cmd == CMD_ON){
            GPIOE->ODR |= (0X1 << 10);
        }else if(cmd == CMD_OFF){
            GPIOE->ODR &= (~(0X1 << 10));
        }
        break;
        case LED_2:
        if(cmd == CMD_ON){
            GPIOF->ODR |= (0X1 << 10);
        }else if(cmd == CMD_OFF){
            GPIOF->ODR &= (~(0X1 << 10));
        }
        break;
        case LED_3:
        if(cmd == CMD_ON){
            GPIOE->ODR |= (0X1 << 8);
        }else if(cmd == CMD_OFF){
            GPIOE->ODR &= (~(0X1 << 8));
        }
        break;
    }
}
//风扇模组
void module_fan_ctrl(Cmd_t cmd){
    if(cmd == CMD_ON){
        GPIOE->ODR |= (0X1 << 9);
    }else if(cmd == CMD_OFF){
        GPIOE->ODR &= (~(0X1 << 9));
    }
}
//马达模组
void module_motor_ctrl(Cmd_t cmd){
    if(cmd == CMD_ON){
        GPIOF->ODR |= (0X1 << 6);
    }else if(cmd == CMD_OFF){
        GPIOF->ODR &= (~(0X1 << 6));
    }
}
//蜂鸣器模组
void module_buzzer_ctrl(Cmd_t cmd){
    if(cmd == CMD_ON){
        GPIOB->ODR |= (0X1 << 6);
    }else if(cmd == CMD_OFF){
        GPIOB->ODR &= (~(0X1 << 6));
    }
}

main.c

cpp 复制代码
#include "key_init.h"
#include "module.h"
#include "delay.h"

extern void printf(const char *fmt, ...);
int main()
{

	key_init();
	// key1_init();
	// key2_init();
	// key3_init();

	module_init();
	module_led_ctrl(LED_1, CMD_ON);
	module_led_ctrl(LED_2, CMD_ON);
	module_led_ctrl(LED_3, CMD_ON);
	delay_ms(1000);
	module_led_ctrl(LED_1, CMD_OFF);
	module_led_ctrl(LED_2, CMD_OFF);
	module_led_ctrl(LED_3, CMD_OFF);


	printf("Init\n");

	while (1);
	

	return 0;
}
相关推荐
房开民5 小时前
使用海康机器人相机SDK实现基本参数配置(C语言示例)
c语言·数码相机·机器人
一川月白7096 小时前
51单片机---硬件学习(电子琴、主从应答模式、modbus模型、DS18B20传感器显示温度)
嵌入式硬件·51单片机·串口通信·异步通信·串行通信·同步通信·并行通信
逼子格6 小时前
【Proteus仿真】定时器控制系列仿真——秒表计数/数码管显示时间
数据库·单片机·嵌入式硬件·51单片机·proteus·定时器·硬件工程师
Tina表姐6 小时前
(C题|NIPT 的时点选择与胎儿的异常判定)2025年高教杯全国大学生数学建模国赛解题思路|完整代码论文集合
c语言·开发语言·数学建模
2401_888423097 小时前
51单片机-按键、蜂鸣器、定时器模块及中断
单片机·嵌入式硬件·51单片机
东亚_劲夫8 小时前
STM32—SPI协议
stm32·单片机·嵌入式硬件
高山有多高8 小时前
详解文件操作
c语言·开发语言·数据库·c++·算法
♞沉寂9 小时前
c51串口通信原理及实操
单片机·51单片机·c51
猫头虎10 小时前
2025最新超详细FreeRTOS入门教程:第一章 FreeRTOS移植到STM32
stm32·单片机·嵌入式硬件·机器人·硬件架构·freertos·嵌入式实时数据库
清风66666612 小时前
基于STM32单片机的酒驾检测设计
stm32·单片机·嵌入式硬件·毕业设计·课程设计