|
由于工作需要,最近需要使用STM32F303VC芯片来做一个带霍尔的电机驱动,使用的TIM1定时器,霍尔信号采用普通端口识别。9 f, Y' o) _) ?2 ?/ b 初始代码使用论坛里面下载下来的测试程序https://www.stmcu.org.cn/module/ ... ht=STM32F3%2BEEPROM3 P; T+ Y9 ]. i5 v/ n/ \3 J5 q' ^ 主要问题出在霍尔信号上,发现一直无法进入外触发中断,即使使用EXTI_GenerateSWInterrupt(EXTI_Linex);也无法正常进入中断。 查看了库文件stm32f30x_exti.c中的相关配置信息,如下:# l. n4 t' U n/ b! ?; r* \ ##### How to use this driver #####+ M- H# z, O0 S' B( r# [ ===============================================================================: ]9 ~7 X4 S6 t$ o# N4 O' b [..] In order to use an I/O pin as an external interrupt source, follow steps below:; _4 p/ ?) e9 Z$ _ (#) Configure the I/O in input mode using GPIO_Init().5 D( }3 z. Y# j! t) M$ f (#) Select the input source pin for the EXTI line using" w: ]" `% a0 j3 L$ c6 a 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).. N- U1 r" P# b& w; \7 a4 b( z% D (#) Configure NVIC IRQ channel mapped to the EXTI line using NVIC_Init().7 _: x; L. l, E2 n& o( |; Q) }/ t) l' I (#) Optionally, you can generate a software interrupt using the function ( C3 E- F& E5 }- u3 r# _2 } EXTI_GenerateSWInterrupt(). [..] (@) SYSCFG APB clock must be enabled to get write access to SYSCFG_EXTICRx, ]( v% s5 W" H0 u. m e) w registers using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 按照以上的配置,配置顺序应该是:端口设置-->触发源配置--> 外触发设置-->中断优先级设置;& p2 V! Q8 l5 x5 t 原先的程序是这样的: void Ext_Init(void) {+ u3 S4 b9 S& Z- }2 a GPIO_InitTypeDef GPIO_InitStructure;0 s2 [) ^1 Y/ g$ W9 L: t EXTI_InitTypeDef EXTI_InitStructure;3 c4 O g- R- V! H9 g, a% e NVIC_InitTypeDef NVIC_InitStructure;! c& J7 A) d! Q/ Z 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); ! s6 b+ p' {) M4 }; R GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;/ f8 w* W( [+ M4 h/ I$ K GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); , H4 L3 \+ N0 a; u8 S SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6 | GPIO_PinSource7 | GPIO_PinSource8);- s. W1 k: W0 {1 ~* U* ^/ D 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;0 F, O- ^) O3 F EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); - i/ |" w# [5 S8 I( N3 q2 V NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);" y8 `- e# _' ^3 A+ H NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;# P6 {. u) K2 f. T" W6 X NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; . E5 E+ J9 _* j8 U& n8 i, U NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/ G( \5 @8 k9 Q i5 T( D! { NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; ' @ R% k `. s6 Q# t. C' N NVIC_Init(&NVIC_InitStructure); } 这个代码调试了有很久,一直找不出问题,网上有些说需要把这个函数提前到比较前面,测试了,也没用,也有说是调换配置的顺序,也是没有用处。) h+ [! N, \4 C# ]. \/ S5 U! H 后来干脆直接用keil的软件仿真功能来看各个端口的配置信息,一步一步调试,才发现原来SYSCFG_EXTILineConfig、EXTI_InitStructure.EXTI_Line这两个函数只能一个通道一个通道设置,不能像端口配置GPIO_Init一样可以合在一起配置,无法得到想要的功能,只会出错。9 G5 J6 f+ S0 T \6 C' X% y, N 以下是正确的配置方式: SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6);//只能一个一个设置 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource7);5 x( M, e7 [- Z4 i1 d SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource8);/ o/ _9 X& @3 h4 L R- ~ EXTI_InitStructure.EXTI_Line=EXTI_Line6; //只能一个一个设置 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;2 I4 K: N! s$ z& u8 B7 N EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE;/ j& X+ \6 b! g/ [, a6 t, L9 M EXTI_Init(&EXTI_InitStructure); EXTI_InitStructure.EXTI_Line=EXTI_Line7; 7 k! K( P; h2 |" l EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; g7 ]3 R( u1 t# B) t7 v$ s EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); 5 s1 C0 K- E4 j* r* v EXTI_InitStructure.EXTI_Line=EXTI_Line8; + d4 ~2 z- q8 H9 b& E& s1 | EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;8 u' S' O7 C& c' t" A. O EXTI_InitStructure.EXTI_LineCmd = ENABLE;: B/ x: \! w. v. P: [* u( z EXTI_Init(&EXTI_InitStructure); ~( Y4 N' `! n' z 正确配置后,使用EXTI_GenerateSWInterrupt函数就能直接进入中断了,最后再将RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG,ENABLE);去掉,才能通过端口进入中断。 这个问题也是算是个低级问题,只能怪自己不够仔细了。. I6 H4 r; K, S. `4 r' _ 分享一下错误经验,让各位大佬见笑了。 |
微信公众号
手机版
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6 | GPIO_PinSource7 | GPIO_PinSource8);, F( s# Q+ p$ @3 z3 }
楼主就不应该这么写,乖乖的分开写
是的,没错,还有 EXTI_Init(&EXTI_InitStructure)这个函数里,也只能一个一个设置