|
由于工作需要,最近需要使用STM32F303VC芯片来做一个带霍尔的电机驱动,使用的TIM1定时器,霍尔信号采用普通端口识别。 初始代码使用论坛里面下载下来的测试程序https://www.stmcu.org.cn/module/ ... ht=STM32F3%2BEEPROM 主要问题出在霍尔信号上,发现一直无法进入外触发中断,即使使用EXTI_GenerateSWInterrupt(EXTI_Linex);也无法正常进入中断。 查看了库文件stm32f30x_exti.c中的相关配置信息,如下: ##### How to use this driver ##### =============================================================================== [..] In order to use an I/O pin as an external interrupt source, follow steps below: (#) Configure the I/O in input mode using GPIO_Init(). (#) Select the input source pin for the EXTI line using SYSCFG_EXTILineConfig(). (#) Select the mode(interrupt, event) and configure the trigger selection (Rising, falling or both) using EXTI_Init(). For the internal interrupt, the trigger selection is not needed (the active edge is always the rising one). (#) Configure NVIC IRQ channel mapped to the EXTI line using NVIC_Init(). (#) Optionally, you can generate a software interrupt using the function EXTI_GenerateSWInterrupt(). [..] (@) SYSCFG APB clock must be enabled to get write access to SYSCFG_EXTICRx registers using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 按照以上的配置,配置顺序应该是:端口设置-->触发源配置--> 外触发设置-->中断优先级设置; 原先的程序是这样的: void Ext_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); // RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG,ENABLE); //注意与下行代码的区别,该函数会影响外触发中断,即使在其他函数中出现也会有影响 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6 | GPIO_PinSource7 | GPIO_PinSource8); EXTI_InitStructure.EXTI_Line=EXTI_Line6 | EXTI_Line7 | EXTI_Line8; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } 这个代码调试了有很久,一直找不出问题,网上有些说需要把这个函数提前到比较前面,测试了,也没用,也有说是调换配置的顺序,也是没有用处。 后来干脆直接用keil的软件仿真功能来看各个端口的配置信息,一步一步调试,才发现原来SYSCFG_EXTILineConfig、EXTI_InitStructure.EXTI_Line这两个函数只能一个通道一个通道设置,不能像端口配置GPIO_Init一样可以合在一起配置,无法得到想要的功能,只会出错。 以下是正确的配置方式: SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6);//只能一个一个设置 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource7); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource8); EXTI_InitStructure.EXTI_Line=EXTI_Line6; //只能一个一个设置 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_InitStructure.EXTI_Line=EXTI_Line7; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_InitStructure.EXTI_Line=EXTI_Line8; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); 正确配置后,使用EXTI_GenerateSWInterrupt函数就能直接进入中断了,最后再将RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG,ENABLE);去掉,才能通过端口进入中断。 这个问题也是算是个低级问题,只能怪自己不够仔细了。 分享一下错误经验,让各位大佬见笑了。 |
微信公众号
手机版
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6 | GPIO_PinSource7 | GPIO_PinSource8);
楼主就不应该这么写,乖乖的分开写
是的,没错,还有 EXTI_Init(&EXTI_InitStructure)这个函数里,也只能一个一个设置