由于工作需要,最近需要使用STM32F303VC芯片来做一个带霍尔的电机驱动,使用的TIM1定时器,霍尔信号采用普通端口识别。1 S1 U4 u1 g9 g1 D5 o 初始代码使用论坛里面下载下来的测试程序https://www.stmcu.org.cn/module/ ... ht=STM32F3%2BEEPROM4 ~2 I2 Y+ i7 X( B* g; c 主要问题出在霍尔信号上,发现一直无法进入外触发中断,即使使用EXTI_GenerateSWInterrupt(EXTI_Linex);也无法正常进入中断。" }0 y' }! M6 U: g E 查看了库文件stm32f30x_exti.c中的相关配置信息,如下: ##### How to use this driver #####1 P! u0 K5 @; k; c5 y8 @, y% ?( R =============================================================================== [..] In order to use an I/O pin as an external interrupt source, 1 F0 A T/ @/ J/ S# D follow steps below: (#) Configure the I/O in input mode using GPIO_Init(). (#) Select the input source pin for the EXTI line using2 Y) o: G0 U q2 a% P SYSCFG_EXTILineConfig().$ f( g# C% m. Z2 a. F (#) 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(). [..]8 ~- D# ]& f/ s* a! [ (@) SYSCFG APB clock must be enabled to get write access to SYSCFG_EXTICRx registers using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);7 z7 W, \1 w/ D$ }0 @& O+ J 1 ~; i- P+ s! z. X! F 按照以上的配置,配置顺序应该是:端口设置-->触发源配置--> 外触发设置-->中断优先级设置; 原先的程序是这样的: \+ y- h9 r+ S3 }; l* L void Ext_Init(void)1 N4 F* E9 c& A @ u; x q {* |& i! u% K1 N) w GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; 9 \4 Z& x- @9 M% z RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);8 ~# d7 u+ K8 n9 s // RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG,ENABLE); //注意与下行代码的区别,该函数会影响外触发中断,即使在其他函数中出现也会有影响# {$ w. }# b7 A 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;; N+ O. x) f, O' c8 ~+ Y0 z+ A 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;+ r" v+ |. X% U9 R9 U! J3 y9 I GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); . m; ~/ r }+ Y1 }% c/ [% F SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6 | GPIO_PinSource7 | GPIO_PinSource8);" n7 h& b0 Q7 A 6 I9 U5 d+ B% j% I EXTI_InitStructure.EXTI_Line=EXTI_Line6 | EXTI_Line7 | EXTI_Line8; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;( z& o2 a3 X4 h4 a6 s* H$ M; g$ w EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;7 l! ]6 b" E5 A& `0 c# ? EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); 9 k) ~$ o$ v# @; E% t0 D* R NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);7 \/ `9 T, r) H, `6 U, X NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;5 j! s t8 s7 b+ X NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; : J/ Q! Y, a. b+ x! f" @0 V NVIC_Init(&NVIC_InitStructure); } 这个代码调试了有很久,一直找不出问题,网上有些说需要把这个函数提前到比较前面,测试了,也没用,也有说是调换配置的顺序,也是没有用处。% y3 _, L" r5 a 后来干脆直接用keil的软件仿真功能来看各个端口的配置信息,一步一步调试,才发现原来SYSCFG_EXTILineConfig、EXTI_InitStructure.EXTI_Line这两个函数只能一个通道一个通道设置,不能像端口配置GPIO_Init一样可以合在一起配置,无法得到想要的功能,只会出错。6 e, N3 f* d6 `, ~ 以下是正确的配置方式:: `4 O+ l( Q7 { SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6);//只能一个一个设置$ l/ c- ^6 p# d+ D& L# G8 ` SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource7);( ]) |7 L) B. l6 ? e: w0 @2 x SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource8); % g- @7 [0 Z& f: _3 B5 n. \8 ?( O EXTI_InitStructure.EXTI_Line=EXTI_Line6; //只能一个一个设置 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;% |& R' ? P! I: T EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE;& N, T' x' b$ ?8 N$ d EXTI_Init(&EXTI_InitStructure);" N. S; n" ?3 }/ x6 V EXTI_InitStructure.EXTI_Line=EXTI_Line7; 0 E3 V; p- z+ N) w EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;% v8 [- L& {( m c3 V: A( T EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;8 K3 C8 }6 O/ V r }4 t EXTI_InitStructure.EXTI_LineCmd = ENABLE;1 y% z2 h" ^6 d+ [" f EXTI_Init(&EXTI_InitStructure); ' b9 g, r5 s% A% b+ N- { EXTI_InitStructure.EXTI_Line=EXTI_Line8; & L( |% I, H% o* p2 Y* D9 W0 @9 u EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;6 h M _1 ]) c7 n/ O8 [" d EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);$ e* P4 G! H4 O; M+ j% N6 o 正确配置后,使用EXTI_GenerateSWInterrupt函数就能直接进入中断了,最后再将RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG,ENABLE);去掉,才能通过端口进入中断。 这个问题也是算是个低级问题,只能怪自己不够仔细了。 分享一下错误经验,让各位大佬见笑了。 # i1 j) H3 l4 @2 S; v- C |
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6 | GPIO_PinSource7 | GPIO_PinSource8);
楼主就不应该这么写,乖乖的分开写
是的,没错,还有 EXTI_Init(&EXTI_InitStructure)这个函数里,也只能一个一个设置