GPIO_EXTILineConfig分析,即AFIO配置

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14)。将GPIOB_14开启外部中断复用。先看下手册。

        可以看到,这是第四个外部中断配置寄存器,所以前面还有3个寄存器。因为,一共有16条中断线,对应16个GPIO_Pin。AFIO_EXTICR1配置Pin0-Pin3,AFIO_EXTICR2配置Pin4-Pin7,AFIO_EXTICR3配置Pin8-Pin11,AFIO_EXTICR4配置Pin12-15。每个寄存器的高16位都是保留的,而低16位分为4组,从低到高,每四位配置一个中断线,也就是对应Pin口,而这4位根据取不同的值就可以决定选择哪个端口,端口即ABCD等。

        比如要让GPIOA的Pin_7引脚口作为外部中断引脚,则要配置AFIO_EXTICR2,配置对应的12到15位,值设为0000,即配置成功。这只是直接操作寄存器,比较简单,如果是通过库函数配置呢?下面开始研究GPIO_EXTILineConfig内部的代码。

        

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
  uint32_t tmp = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
  
  tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));
  AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;
  AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
}

 上面就是GPIO_EXTILineConfig内部的代码和对应参数的宏定义。

        假设要配置GPIOB的Pin14为中断引脚。 GPIO_PortSourceGPIOB就是((uint8_t)0x01),GPIO_PinSource14就是((uint8_t)0x0E)。先计算tmp,tmp=0x0F<<(0x04*(0x0E&0x03))=0x0F00下一步的AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp啥意思,其实这个箭头是访问结构体成员,这个方括号表示访问数组的某个元素,~表示按位取反。

        如上图,AFIO是宏定义 ,将AFIO_BASE即AFIO基地址强转为AFIO_TypeDef *即AFIO_TypeDef类型的指针。也就是说,AFIO_TypeDef *指向了AFIO_TypeDef结构体,也就是AFIO指向了AFIO_TypeDef结构体,这才有了AFIO->EXTICR[]这个写法。

        好了,继续计算AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp。即AFIO->EXTICR[0x0E>>0x02]&=0xFF0F。得到AFIO->EXTICR[3]=AFIO->EXTICR[3]&0xFF0F,很明显,是要清除AFIO_EXTICR4的14中断线的四个bit位。因为是数组(下标从0开始),所以AFIO->EXTICR[3]表示第四个寄存器。

        下一步的AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)))。即AFIO->EXTICR[3]=AFIO->EXTICR[3] | (0x01<<(0x04*(0x0E&0x03))),结果为AFIO->EXTICR[3]=AFIO->EXTICR[3] | 0x0100,也就是将0001写入AFIO_EXTICR4的第8-11位,刚好是GPIOB的Pin14。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
void Encoder_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 1000 - 1; TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure); TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); TIM_Cmd(TIM1, ENABLE); GPIO_InitTypeDef GPIO_InitStructure1; GPIO_InitStructure1.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure1.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1; GPIO_InitStructure1.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure1); GPIO_InitTypeDef GPIO_InitStructure2; GPIO_InitStructure2.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure2.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13; GPIO_InitStructure2.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure2); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource4); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource10); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13); EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line0|EXTI_Line1|EXTI_Line4|EXTI_Line5|EXTI_Line10|EXTI_Line11|EXTI_Line12|EXTI_Line13; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_Init(&EXTI_InitStructure); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitTypeDef NVIC_InitStruct1; NVIC_InitStruct1.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStruct1.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct1.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStruct1.NVIC_IRQChannelSubPriority = 0x00; NVIC_Init(&NVIC_InitStruct1); NVIC_InitTypeDef NVIC_InitStruct2; NVIC_InitStruct2.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStruct2.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct2.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStruct2.NVIC_IRQChannelSubPriority = 0x00; NVIC_Init(&NVIC_InitStruct2); NVIC_InitTypeDef NVIC_InitStruct3; NVIC_InitStruct3.NVIC_IRQChannel = EXTI4_IRQn; NVIC_InitStruct3.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct3.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStruct3.NVIC_IRQChannelSubPriority = 0x00; NVIC_Init(&NVIC_InitStruct3); NVIC_InitTypeDef NVIC_InitStruct4; NVIC_InitStruct4.NVIC_IRQChannel = EXTI9_5_IRQn; NVIC_InitStruct4.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct4.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStruct4.NVIC_IRQChannelSubPriority = 0x00; NVIC_Init(&NVIC_InitStruct4); NVIC_InitTypeDef NVIC_InitStruct5; NVIC_InitStruct5.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStruct5.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct5.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStruct5.NVIC_IRQChannelSubPriority = 0x00; NVIC_Init(&NVIC_InitStruct5); }stm32f103系列芯片,当这段代码初始化时,以PA2PA3初始化的串口不能正常工作,是为什么
05-18

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值