方法步骤
在How to use this driver里就讲述了怎么运用,此处是设置exti(中断),像之前的gpio操作步骤亦是如此。点击相应的文档How to use this driver处就可以知道如何操作了
注意:有些函数需要往下寻找,比如清除中断标志位(下面的步骤6)
以下是exti的步骤:
- 使能SYSCFG时钟:RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE)
- IO口初始化为输入:GPIO_Init()
- 设置IO口与中断线的映射关系:SYSCFG_EXTILineConfig()
- 设置触发外部中断的条件:EXTI_Init()
- 配置中断分组(NVIC)并且使能中断:NVIC_Init()
- 清除中断标志位:EXTI_ClearITPendingBit()
- 编写中断服务函数(这个是在.s文件里):EXTIx_IRQHandler()
在设置函数的相关参数时双击对应参数,然后右击选择Go To Definition Of ‘XXX’,层层递进查阅相关操作
代码
main.c
#include "led.h"
#include "sys.h"
#include "exti.h"
#include "delay.h"
int main(void)
{
/*初始化*/
LED_init();
led_off();
Exti_Init(); //按一下灯亮,再按一下灯灭
return 0;
}
sys.h
#ifndef __SYS_H__
#define __SYS_H__
//位带操作
//IO口操作宏定义
#define BITBAND(addr, bitnum) (0x42000000 +((addr-0x40000000)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414
#define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814
#define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14
#define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014
#define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414 20 = 0x14
#define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814
#define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14
#define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014
#define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010
#define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410
#define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810
#define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10
#define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010
#define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410 16 = 0x10
#define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810
#define GPIOH_IDR_Addr (GPIOH_BASE+16) //0x40021C10
#define GPIOI_IDR_Addr (GPIOI_BASE+16) //0x40022010
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) //输出
#define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) //输入
#define PIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) //输出
#define PIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) //输入
#endif //此行后面留一行空不然会有警告,可能是代码规范问题吧
delay.h
#ifndef __DELAY_H__
#define __DELAY_H__
#include "stm32f4xx.h"
void delay_us(unsigned int nus);
void delay_ms(unsigned int nms);
void delay_s(unsigned int ns);
#endif //此行后面留一行空不然会有警告
led.h
#ifndef __LED_H__
#define __LED_H__
#include "stm32f4xx.h"
void LED_init(void);
void led_off(void);
#endif //此行后面留一行空不然会有警告
exti.h
#ifndef __EXTI_H__
#define __EXTI_H__
#include "stm32f4xx.h"
void Exti_Init(void);
#endif
delay.c
#include "delay.h"
void delay_us(unsigned int nus)
{
SysTick->LOAD = (168000000/8/1000000)*nus;//重装载值
SysTick->CTRL |= 1;//使能CTRL开始计数
SysTick->VAL = 0;
while((SysTick->CTRL & (1<<16))==0);
SysTick->CTRL &= ~1;//失能CTRL开始计数
SysTick->VAL = 0;
}
//最多能帮你延时 798.9 ms
void delay_ms(unsigned int nms)
{
SysTick->LOAD = (168000000/8/1000)*nms;//重装载值
SysTick->CTRL |= 1;//使能CTRL开始计数
SysTick->VAL = 0;
while((SysTick->CTRL & (1<<16))==0);
SysTick->CTRL &= ~1;//失能CTRL开始计数
SysTick->VAL = 0;
}
void delay_s(unsigned int ns)
{
while(ns--)
{
delay_ms(500);
delay_ms(500);
}
}
led.c
#include "led.h"
void LED_init(void)
{
GPIO_InitTypeDef A;
//必须先初始化时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOE, ENABLE);
A.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;//PF8 PF9 PF10
A.GPIO_Mode = GPIO_Mode_OUT;//输出模式
A.GPIO_OType = GPIO_OType_PP;//推挽输出
A.GPIO_PuPd = GPIO_PuPd_UP;//上拉
A.GPIO_Speed = GPIO_Fast_Speed;//高速 50MHz
GPIO_Init(GPIOF,&A);
A.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;//PE13 PE14
A.GPIO_Mode = GPIO_Mode_OUT;//输出模式
A.GPIO_OType = GPIO_OType_PP;//推挽输出
A.GPIO_PuPd = GPIO_PuPd_UP;//上拉
A.GPIO_Speed = GPIO_Fast_Speed;//高速 50MHz
GPIO_Init(GPIOE,&A);
}
void led_off()
{
GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);
GPIO_SetBits(GPIOE,GPIO_Pin_13 | GPIO_Pin_14);
}
exti.c
#include "exti.h"
#include "sys.h"
void Exti_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//必须先初始化时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;//PA0
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;//输入模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed;//高速 50MHz
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;//PE3 PE4 PE2
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;//输入模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed;//高速 50MHz
GPIO_Init(GPIOE,&GPIO_InitStruct);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);//PA0 ---》EXTI0
EXTI_InitStruct.EXTI_Line = EXTI_Line0;//PA0 ---》EXTI0
EXTI_InitStruct.EXTI_LineCmd = ENABLE;//使能
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//中断
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;//EXTI0
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x1;//抢占优先级 0-3
NVIC_InitStruct.NVIC_IRQChannelSubPriority =0x3;//响应优先级 0-3
NVIC_Init(&NVIC_InitStruct);
}
//中断服务函数 在startup_stm32f40_41xxx.s 里面找
void EXTI0_IRQHandler(void)
{
//判断确实进中断
if(EXTI_GetITStatus(EXTI_Line0)==SET)
{
delay_xd(5);
//立马清楚中断线
EXTI_ClearITPendingBit(EXTI_Line0);
PFout(9)=!PFout(9);
}
}