我的 STM32F103C8T6 微控制器有问题。我正在使用(作为练习)外部中断来打开/关闭 LED,方法是按下外部开关,该开关又连接到 PC13。我正在使用 StdPeriph 库。
芯片编程后,没有任何反应。相反,当我使用调试器(在Coocox中调试)时,芯片工作正常。我不知道问题出在哪里。
你能帮我吗?
这是我的代码:
#include<stm32f10x.h>
#include<stm32f10x_rcc.h>
#include<stm32f10x_gpio.h>
#include<stm32f10x_exti.h>
#include<misc.h>
typedef enum{
on,
off
}state;
state led=on;
int main(void){
// enable clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
// uncomment to disable/remap JTAG pins
GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
// configure PC13 as input
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
// configure PB8 as led output
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
// connect PC13 to EXTI controller
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource13);
// enable and configure EXTI controller
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line13;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
// enable IRQ
NVIC_EnableIRQ(EXTI15_10_IRQn);
NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
// Configure NVIC
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitStructure);
// switch on led
GPIO_WriteBit(GPIOB,GPIO_Pin_8,Bit_SET);
while(1);
return 0;
}
void EXTI15_10_IRQHandler(void){
// clear pending bit
if(EXTI_GetITStatus(EXTI_Line13)!=RESET){
EXTI_ClearITPendingBit(EXTI_Line13);
}
if(led==off){
GPIO_WriteBit(GPIOB,GPIO_Pin_8,Bit_SET);
led=on;
}else{
GPIO_WriteBit(GPIOB,GPIO_Pin_8,Bit_RESET);
led=off;
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t * file,uint32_t line){
/* Infinite loop */
while (1);
}
#endif
我也遇到这个问题了。我用的是STM32F030。 对我来说,问题是没有启用 SYSCFG 时钟,它是 RCC APB2ENR 寄存器的位 0。我猜这个设置是在调试中启用的,以便软件可以调试?否则时钟将被禁用!
通过查阅STM32F1参考手册终于找到了这个,稍微全面一点。
对按钮和按键使用外部中断通常是一个非常糟糕的主意。您应该改用定时器中断。
您可以在这里看到定时器中断中按键的简单实现(支持单击、双击、长按事件):https://www.diymat.co.uk/arm- Three-function-click-double-and -长按按钮库定时器中断驱动/
我对上述控制器不了解,但我曾研究过STM32L4系列控制器。在 STM32L4 中,按钮连接到 PC13 引脚。我观察到按下按钮时 GPIO 去抖。在 EXTI15_10_IRQHandler() 中实现去抖逻辑。确保每次按下按钮时中断仅到达此函数一次。可能是调试器正在减慢处理器的速度(与自由运行相比,CPU 以较低的频率运行),并且您正在正确地获取中断。
您是否使用不同的构建配置进行调试?如果是这样,请尝试创建
led
变量 volatile
并查看是否有帮助。
如果不是:添加一些延迟循环,即在 ISR 中清除 EXTI 位后添加 voliatile unsigned i; for (i=0; i < 50000u; ++i);
。在中断服务中使用阻塞延迟通常是一种不好的做法(如果它曾经是一个好的做法......),但可能有助于查看它是否与未正确完成的反跳有关。如果有帮助,那么最有可能出现的问题是开关去抖。
编辑:考虑使用位带(如果可能)来访问输出端口,然后你可以做类似
bind_band_led_port ^= 1;
的事情,但这只是一个旁注。