由于工作需要,最近需要使用STM32F303VC芯片来做一个带霍尔的电机驱动,使用的TIM1定时器,霍尔信号采用普通端口识别。 初始代码使用论坛里面下载下来的测试程序https://www.stmcu.org.cn/module/ ... ht=STM32F3%2BEEPROM 主要问题出在霍尔信号上,发现一直无法进入外触发中断,即使使用EXTI_GenerateSWInterrupt(EXTI_Linex);也无法正常进入中断。; I( W) H. C2 X( _) [ 查看了库文件stm32f30x_exti.c中的相关配置信息,如下:0 p' Q( k$ s- y% S2 H ##### How to use this driver #####) D9 Q. g6 ?# d9 c1 I8 [0 } =============================================================================== [..] In order to use an I/O pin as an external interrupt source, 1 F8 y/ O; u3 P1 v X7 K follow steps below:) f; Z2 W/ Q5 _. M7 S& |4 _- B (#) Configure the I/O in input mode using GPIO_Init().2 x9 y ]1 y* \: I; @( J0 g: ` (#) 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); B7 ?2 { v- y3 s' ~7 F, N 2 V" y1 a' m6 Q/ ]; K0 R+ I% R 按照以上的配置,配置顺序应该是:端口设置-->触发源配置--> 外触发设置-->中断优先级设置; 原先的程序是这样的: void Ext_Init(void) {9 N2 V! M; R6 \) p, g1 r* @+ r GPIO_InitTypeDef GPIO_InitStructure;% o9 Y! s2 S# F; n9 o( s% x EXTI_InitTypeDef EXTI_InitStructure;. H& j+ r+ W1 ~- t- K$ I NVIC_InitTypeDef NVIC_InitStructure; ) S, \9 {) x, E7 z: @# |1 Q+ t RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); // RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG,ENABLE); //注意与下行代码的区别,该函数会影响外触发中断,即使在其他函数中出现也会有影响1 V! ]' t) B4 {8 g2 \* A RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);0 Q; C$ M, o/ G8 K t, l5 y - v5 P+ C) b$ V' j GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;( x' N. Y% I% W: o+ ~9 X2 P+ f GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure);( C1 M1 p7 u# J& Z q3 `% r 7 _: p- W' D# M: ?6 o7 }) ?% y$ [ 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;" W M! K. @' J2 \: a/ o GPIO_Init(GPIOD, &GPIO_InitStructure);& E/ J+ D% Z7 Y) H! p! T SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6 | GPIO_PinSource7 | GPIO_PinSource8);) q) O1 J+ f. T k) Q EXTI_InitStructure.EXTI_Line=EXTI_Line6 | EXTI_Line7 | EXTI_Line8;$ t7 ?. m4 I$ f EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;0 P( {6 ^2 ^: s0 \* N( I EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);9 S4 m2 [' I1 Z; i1 X' w * X, r8 _* Z, A& ?" X P7 U% ^ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); T" v5 P) X$ t; Z 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); & z" ]1 M+ \! U0 J# ~3 i% { } " G h: m- R/ c8 l 这个代码调试了有很久,一直找不出问题,网上有些说需要把这个函数提前到比较前面,测试了,也没用,也有说是调换配置的顺序,也是没有用处。4 w9 X8 E6 L* d8 `7 _# N 后来干脆直接用keil的软件仿真功能来看各个端口的配置信息,一步一步调试,才发现原来SYSCFG_EXTILineConfig、EXTI_InitStructure.EXTI_Line这两个函数只能一个通道一个通道设置,不能像端口配置GPIO_Init一样可以合在一起配置,无法得到想要的功能,只会出错。0 ?$ @, U# o: I% h 以下是正确的配置方式: SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6);//只能一个一个设置/ ^- ~- B( @# [ V0 l! D% a" v4 ]" b SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource7);* v* N, j3 w/ P9 y3 ?, Y6 A4 d: y% u) z SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource8); ! q3 f- `. B7 A" ? EXTI_InitStructure.EXTI_Line=EXTI_Line6; //只能一个一个设置 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;0 ` [3 P) B( @) J: Z EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;: m: s( ^( `% Y1 N; @* g2 S7 Q EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);2 P. M" C1 ^ C# d2 O 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); ! W: q. x4 s$ h1 b EXTI_InitStructure.EXTI_Line=EXTI_Line8; + T F8 y9 r) I2 ~/ W% X EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);+ j- o$ Y7 b9 a$ k# R+ X 正确配置后,使用EXTI_GenerateSWInterrupt函数就能直接进入中断了,最后再将RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG,ENABLE);去掉,才能通过端口进入中断。! l+ A7 B+ U* w+ m9 [ 这个问题也是算是个低级问题,只能怪自己不够仔细了。 分享一下错误经验,让各位大佬见笑了。. A& M1 J+ \& L) @2 K/ q |
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,GPIO_PinSource6 | GPIO_PinSource7 | GPIO_PinSource8);$ Q. m: E; @2 J! l4 j! e3 e' e) E7 k# ?
楼主就不应该这么写,乖乖的分开写
是的,没错,还有 EXTI_Init(&EXTI_InitStructure)这个函数里,也只能一个一个设置