tmp = (uint32_t)EXTI_BASE; #define EXTI_BASE (APB2PERIPH_BASE + 0x0400)
EXTI_Mode_Interrupt = 0x00;
EXTI_Mode_Event = 0x04;
EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line;
EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line;
tmp += EXTI_InitStruct->EXTI_Mode;
*(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;
1、(EXTI->IMR没有发现在哪里置1的)之前有一个认识误区,要开启EXTI线中断,那么EXTI_>IMR相应的位应该置1才对的,但左看右看程序EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line; 分明是把相应位清零呀!难道是不需要开启吗?于是我在void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)函数的最后写下EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line;一句函数,发现中断函数没有响应,所以在此函数中肯定有一条语句把相应的线中断请求置1了。经过仔细查看,原来如此!知道原因了。*(__IO uint32_t *)没有在意这个!其表示意思是往相应的地址寄存器写入数据。当EXTI->Mode选择中断模式时(EXTI->IMR偏移地址是0x00)*(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;表示的就是向EXTI->IMR寄存器写入数据,开启相应的中断请求。当EXTI->Mode选择事件模式时(EXTI->EMR偏移地址是0X04)*(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;表示的就是向EXTI->EMR寄存器写入数据,开启相应的事件请求。
2、(EXTI->IMR与EXTI->EMR之间的关系)原本以为是在开启事件请求的前提下再开启中断请求,当外部触发时才会响应中断函数。后来经过研究和查看手册得知,原来是这样的。:要产生中断,必须先配置好并使能中断线。根据需要的边沿检测设置2个触发寄存器,同时在中断屏蔽寄存器的相应位写’1’允许中断请求。当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位也随之被置’1’。在挂起寄存器的对应位写’1’,将清除该中断请求。如果需要产生事件,必须先配置好并使能事件线。根据需要的边沿检测通过设置2个触发寄存器,同时在事件屏蔽寄存器的相应位写’1’允许事件请求。当事件线上发生了需要的边沿时,将产生一个事件请求脉冲,对应的挂起位不被置’1’。通过在软件中断/事件寄存器写’1’,也可以通过软件产生中断/事件请求。所以可以得知它们之间没有什么关系,下面的框图表示的很清楚。
3、(软件触发的另一种方式)其实可以通过对EXTI->SWIER的配置实现软件触发中断的操作。经过测试发现了另外一种软件中断的方法:
在中断模式下你只要通过软件编程实现对触发端相同的操作就行了。比如中断模式我设置为下降沿触发,所以我只需要在我需要触发中断的时序中写下(PA0为线中断): GPIO_SetBits(GPIOA,GPIO_Pin_0); //高电平
Delay(26);
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//低电平,低电平维持的时间不需要太长,因为我们只需要产生下降沿就行了。
Delay(1);
Delay是一个简单的延时函数:void Delay(__IO uint32_t z) /*大约40ms*/
{
uint32_t x;
for(;z>0;z--)
for(x=0x26266;x>0;x--);
}
通过上面的操作就是实现软件触发的功效了。
|