芯片为STM32F103ZET6,STM32FXX手册
1.按键控制小灯泡(外部中断)
RCC_APB2ENR:位0是启用AFIO,不启用不能开启中断!,RCC的寄存器地址是 0x4002 1000 - 0x4002 13FF,APB2的偏移值为0x18,所以配置的地址就是0x4002 1018。
AFIO:事件寄存器没在用,跳过不管,外部中断配置寄存器有四个,分别是AFIO_EXTICR1,2,3,4,他们分别对应着GPIOABCDEFG的四个引脚,比如EXTICR1就是对应着0-4脚的GPIOABCDEFG,四个寄存器加起来刚好是16个脚的中断,每个位数的引脚同时只能有一个启用中断,如GPIOA的1脚启用了外部中断,GPIOBCDEFG的1脚就不能启用外部中断,当前使用的是PE4,所以用的是AFIO_EXTICR2,AFIO的地址是0x4001 0000,EXTICR2的偏移值是0x0C,所以配置地址就是0x4001 000C。
EXTI:目前用到的有 中断屏蔽寄存器(EXTI_IMR),上升沿触发选择寄存器(EXTI_RTSR),下降沿触发选择寄存器(EXTI_FTSR),挂起寄存器(EXTI_PR) ,EXTI的地址是0x4001 0400,偏移地址分别是0x00,0x08,0x0C,0x14,。没用到的寄存器分别是事件屏蔽寄存器(EXTI_EMR),软件中断事件寄存器(EXTI_SWIER) ,偏移地址分别是0x04,0x10。
//.h文件
typedef unsigned int uint32_t;
#define PERIPH_BASE ((uint32_t)0x40000000)
#define GPIOB_CRL *(unsigned int*)(0x40010C00)
#define GPIOB_ODR *(unsigned int*)(0x40010C0C)
#define GPIOE_CRL *(unsigned int*)(0x40011800)
#define GPIOE_ODR *(unsigned int*)(0x4001180c)
#define APB2PERIPH_BASE ((uint32_t)PERIPH_BASE+0x10000)
#define RCC_APB2ENR *(unsigned int*)(0x40021018)
#define AFIO_EXTICR2 *(unsigned int*)(0x4001000C)
#define EXTI_BASE ((uint32_t)APB2PERIPH_BASE+0x0400)
#define EXTI_IMR *(unsigned int*)(EXTI_BASE)
#define EXTI_EMR *(unsigned int*)(EXTI_BASE+0x04)
#define EXTI_RTSR *(unsigned int*)(EXTI_BASE+0x08)
#define EXTI_FTSR *(unsigned int*)(EXTI_BASE+0x0C)
#define EXTI_SWIER *(unsigned int*)(EXTI_BASE+0x10)
#define EXTI_PR *(unsigned int*)(EXTI_BASE+0x14)
//main.c
#include "GPIO.h"
#include "stm32f10x.h"
void SystemInit(void)
{
}
unsigned char a =2;
typedef unsigned int u32;
void delay(u32 i)
{
while(i--);
}
int main()
{
RCC_APB2ENR |= 1; //启用AFIO,之前就是没启用网上找了半天,笑死了
AFIO_EXTICR2 |= 0x04; //选择将GPIOE4脚选为EXTI的外部中断输入源。
EXTI_IMR = 1<<4; //开放4脚上的中断请求
EXTI_FTSR = 1<<4;
//设置4脚为下降沿触发(因为原理图上按钮另一端是接地)
//EXTI_RTSR = 1<<4; //设置4脚为上升沿触发中断可以和下降沿触发一起配置,这样子就是按下去一个变化抬起来一个变化。
RCC_APB2ENR |= (1<<3); //初始化GPIOB的时钟
RCC_APB2ENR |= (1<<6); //初始化GPIOE的时钟
GPIOB_CRL &= ~(0xf<<4*5); //清空PB5的端口配置
GPIOB_CRL |= (1<<4*5); //设置PB5为通用推挽输出模式,输出速率为10MHZ
GPIOB_ODR |= (1<<5); //因为LED是共阳,所以要将PB5设置为低电平
GPIOE_CRL &= ~(0xf<<4*4); //清空PE4的端口配置
GPIOE_CRL |= 0x1<<(4*4+3); //设置PE4为上拉输入模式
GPIOE_ODR |= (1<<4); //因为是上拉输入模式,所以要将PE4设置为高电平(这个一定要配哦(应该吧),不然的话好像不能触发中断,因为一直是下降沿)
delay(1000);
while(1)
{
if(EXTI_PR & 1<<4) //判断是否触发中断
{
GPIOB_ODR = ~(GPIOB_ODR&1<<5); //触发了中断就将LED置反
EXTI_PR |= 1<<4; //将中断位重置
}
}
}