基于STM32A7核按键点亮LED灯的示例程序

//main.c
#include "led.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++);
}

int main()
{

	hal_exit_init(EXTI9,PF9,FTSR);
	hal_gic_init(99,0x1d);
	hal_exit_init(EXTI7,PF8,FTSR);
	hal_gic_init(97,0x1e);
	hal_exit_init(EXTI8,PF7,FTSR);
	hal_gic_init(98,0x1f);
	led_init();

	while(1)
	{
	
	}
	return 0;
}

//led.h
#ifndef __LED_H__
#define __LED_H__
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"

//引脚封装
#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

#define PF7 0x05
#define PF8 0x05
#define PF9 0x05

#define EXTI7 7
#define EXTI8 8
#define EXTI9 9

#define RTSR 0 //上升沿
#define FTSR 1 //下降沿


typedef unsigned int status_t;

typedef struct{
	char *cmd_arr; 	//命令符字符串
	gpio_t *gpio; 	//gpio组号
	unsigned int pin; //对应的引脚编号
	status_t status; 	//LED灯状态
	void (*gpio_write_p)(gpio_t * gpio,unsigned int pin, status_t status);

}cmd_t;

//模式寄存器封装
typedef enum{
	INPUT, 		//0 0b00
	OUTPUT, 	//1 0b01
	ALT, 		//2 0b10
	ANALOG, 	//3 0b11
}gpio_moder_t; 	//4

//输出类型寄存器封装
typedef enum{
	PP, 	//推挽 0 0b0
	OD, 	//开漏 1 0b1
}gpio_otyper_t;

//输出速度寄存器封装
typedef enum{
	LOW, 		//低速 0 0b00
	MED, 		//中速 1 0b01
	HIGH, 		//高速 2 0b10
	VERT_HIGH, 	//超高速 3 0b11
}gpio_ospeedr_t;

//是否需要上下拉电阻寄存器封装
typedef enum{
	NO_PUPDR, 	//禁止 0 0b00
	PU, 		//上拉 1 0b01
	PD, 		//下拉 2 0b10
}gpio_pupdr_t;

//输出高低电平寄存器封装
typedef enum{
	GPIO_RESET_T, 	//输出低电平 0 0b0
	GPIO_SET_T, 	//输出高电平 1 0b1
}gpio_odr_t;

//寄存器初始化封装
typedef struct{
	gpio_moder_t 	moder; 			//模式
	gpio_otyper_t 	otyper; 		//输出类型
	gpio_ospeedr_t 	ospeedr; 		//输出速率
	gpio_pupdr_t 	pupdr; 			//是否需要上下拉电阻

}gpio_init_t;

//EXIT章节初始化
void hal_exit_init(volatile unsigned int my_EXTI,unsigned int gpio, unsigned int RF);
//GIC章节初始化
void hal_gic_init(unsigned int interNum,unsigned int priority);

//PE10 PF10 PE8
//函数: 1)GPIO组号 2)引脚编号 3)初始化相关的值
//无返回值
void hal_gpio_init(gpio_t* gpiox,unsigned int pin, gpio_init_t* init);

//函数2功能:对GPIO引脚操作,写0输出低电平 写1输出高电平
//参数:1)GPIO组号 2)引脚编号 3)写入的值
//无返回值
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,unsigned int gpio_status);

void led_init();

#endif

//led.c
#include "led.h"

void hal_exit_init(volatile unsigned int my_EXTI, unsigned int gpio, unsigned int RF)
{
	RCC->MP_AHB4ENSETR |= (0x1 << 5);
	
	//计算EXTICRn的偏移量 9/4=2 8/4=2 7/4=1
	int exticrn = my_EXTI/4;
	int bExticrn = my_EXTI%4;
	GPIOF->MODER &=(~(0x3 << my_EXTI *2));//led1 pf9
	//key和exit做连接
	*(&(EXTI->EXTICR1)+exticrn) &= (~(0xff << bExticrn*8));
	*(&(EXTI->EXTICR1)+exticrn) |= (gpio << bExticrn*8);

	//设置下降沿触发
	if(RF == 1) //=1上升沿触发
		EXTI->FTSR1 |= (0x1 << my_EXTI);
	else
		EXTI->RTSR1 |= (0x1 << my_EXTI);
	//设置中断不屏蔽
		EXTI->C1IMR1 |= (0x1 << my_EXTI);
}

void hal_gic_init(unsigned int interNum, unsigned int priority)
{
	GICD->CTRL |=(0x1<<0);
	//GICD层中断使能寄存器
	int consult = 0;
	int remain =0;
	consult = interNum/32;
	remain = interNum%32;
	GICD->ISENABLER[consult] |=(0x1 << remain);
	//GICD层中断优先级寄存器
	consult = interNum / 4;
	remain = interNum % 4;
	GICD->IPRIORITYR[consult] &=(~(priority << (remain*8+3)));
	//GICD层中断目标分配寄存器
	consult = interNum / 4;
	remain = interNum % 4;
	GICD->ITARGETSR[consult] &= (~(0x03 << remain*8));
	GICD->ITARGETSR[consult] |= (0x01 << remain*8);

	//使能GICC层控制器
	GICC->CTRL |= (0x1 << 0);
	//设置GICC层中断优先级
	GICC->PMR |= (0x2 << 3);
}


//led 初始化函数
void hal_gpio_init(gpio_t* gpiox, unsigned int pin, gpio_init_t* init)
{
	//设置GPIO引脚模式
	gpiox->MODER &= (~(0x3<<(pin*2))); 			//对21:20(以PE10为例)清0
	gpiox->MODER |= (init->moder << (pin*2)); 	//将21:20设置为moder代表的模式

	//设置GPIO引脚类型
	gpiox->OTYPER &= (~(0x1 << pin));
	gpiox->OTYPER |= (init->otyper << pin);

	//设置GPIO引脚速率
	gpiox->OSPEEDR &= (~(0x1 << (pin *2)));
	gpiox->OSPEEDR |= (init->ospeedr << (pin * 2));

	//设置GPIO引脚上下拉电阻
	gpiox->PUPDR &= (~(0x1 << (pin * 2)));
	gpiox->PUPDR |= (init->pupdr << (pin *2));

}
//控制led打开或关闭
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,unsigned int gpio_status)
{
	//判断输入的值是否为低电平
	if(gpio_status == GPIO_RESET_T)
	{
		gpiox->ODR &= (~(0x1 << pin)); 	//将LEDn关闭
	}
	else
	{
		gpiox->ODR |= (0x1<< pin); 		//将LEDn打开
	}
}

//led初始化函数
void led_init()
{

	//结构体初始化 设置输出模式,类型,速率,上下拉电阻
	gpio_init_t init = {OUTPUT,PP,LOW,NO_PUPDR};
	//调用gpio初始化函数
	//LED1
	hal_gpio_init(GPIOE, GPIO_PIN_10, &init);
	//LED2
	hal_gpio_init(GPIOF, GPIO_PIN_10, &init);
	//LED3
	hal_gpio_init(GPIOE, GPIO_PIN_8, &init);
}

//do_irq.c
#include "led.h"
extern void printf(const char *fmt, ...);
unsigned int i = 0;
//标记led开启/关闭状态
int ledState[3]={0,0,0};

void do_irq(void) 
{
	unsigned int num;
	//获取中断号
	num = GICC->IAR & (0x3ff);
	switch(num)
	{
		
		case 97:
			printf("key2 press!\n");
			//对led2的状态取反
			ledState[1] ^=0x01;	
			hal_gpio_write(GPIOF,GPIO_PIN_10,ledState[1]);
			EXTI->FPR1 |=(0x1<<7);
			GICD->ICPENDR[3] |=(0x1 << 1);
			break;
		case 98:
			printf("key3 press!\n");
			//对led3的状态取反
			ledState[2] ^=0x01;	
			hal_gpio_write(GPIOE,GPIO_PIN_8,ledState[2]);
			EXTI->FPR1 |=(0x1<<8);
			GICD->ICPENDR[3] |=(0x1 << 2);
			break;
		case 99:
			printf("key1 pres!\n");
			//对led3的状态取反
			ledState[0] ^=0x01;	
			hal_gpio_write(GPIOE,GPIO_PIN_10,ledState[0]);
			//1.清除EXIT层中断挂起标志位
			EXTI->FPR1 |=(0x1<<9);
			//2.清除GICD中断挂起标志位
			GICD->ICPENDR[3] |=(0x1 << 3);
			break;
	}
	//3.清除获取到的中断号
	GICC->EOIR = num;
}


你可能感兴趣的:(嵌入式)