AFIO是指GPIO端口的复用功能,GPIO除了可以用作普通的输入输出,还可以用作片上外设的复用输入输出口(如串口,ADC等)。大多数GPIO有一个默认复用功能,有的还有重映射功能。重映射功能是指把原来属于A引脚的默认复用功能,转移到B引脚进行试验,前提是B引脚有这个重映射功能。使用GPIO_PinRemapConfig()函数进行重映射。
当把GPIO用作EXTI外部中断或使用重映射功能的时候,必须开启AFIO时钟,而在使用默认复用功能的时候不用开启AFIO时钟。
/*配置GPIO##group的##pin为EXTI中断,并设置优先级*/
#define DEFINE_PIN_EXTI(group, pin, IRQn, SubPriority) \
void init_P##group##pin##_as_EXTI(void) \
{ \
GPIO_InitTypeDef GPIO_InitStructure; \
EXTI_InitTypeDef EXTI_InitStructure; \
NVIC_InitTypeDef NVIC_InitStructure; \
\
/*使能EXTIx线的时钟和第二功能AFIO时钟*/ \
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO##group|RCC_APB2Periph_AFIO, ENABLE); \
\
/*配置EXTI中断线I/O*/ \
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_##pin; \
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /*上拉输入*/\
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; \
GPIO_Init(GPIO##group, &GPIO_InitStructure); \
\
/*选择GPIO##group##pin管脚为外部中断源和配置IO口的工作模式*/ \
GPIO_EXTILineConfig(GPIO_PortSourceGPIO##group, GPIO_PinSource##pin); \
EXTI_InitStructure.EXTI_Line = EXTI_Line##pin; \
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; \
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; /*设置为下降沿触发*/\
EXTI_InitStructure.EXTI_LineCmd = ENABLE; \
EXTI_Init(&EXTI_InitStructure); \
\
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /*设置NVIC优先级组为第一组*/ \
NVIC_InitStructure.NVIC_IRQChannel = IRQn; /*该参数的设置参考<STM32固件库>中NVIC_Init()函数的用法和<STM32参考手册>中8.1.2中断和异常向量*/ \
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; \
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; \
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; \
NVIC_Init(&NVIC_InitStructure); \
}
/*这里配置PC5为EXTI为外部中断源,NVIC结构体中.NVIC_IRQChannel=EXTI9_5_IRQn表示要配置的是EXTI第5-9线的中断向量,EXTI5-EXTI9使用同一个中断向量,所以只能写入EXTI5_9_IRQn.这些参数可在stm32f10x.h中的IRQn类型定义中找到.*/
DEFINE_PIN_EXTI(C, 5, EXTI9_5_IRQn, 1)
/*中断服务函数的编写*/
/*stm32f10x_it.c文件是专门用来存放中断服务函数的.中断服务函数的名字必须要与启动文件startup_stm32f10x_hd.s中的中断向量表一致.*/
/* PC5 Key1 interrupt handler */
void EXTI9_5_IRQHandler(void)
{
static uint8_t led1_status = OFF;
if(EXTI_GetITStatus(EXTI_Line5) != RESET) //确保是否产生了EXTI LINE中断
{
led1_status ^= 1;
turn_led(LED1, led1_status);
// EXTI_ClearITPendingBit(EXTI_Line5); //清除中断标志
}
}
|