沥沥小鱼 2024-04-24 10:26 采纳率: 45.5%
浏览 21

stm32外部中断按键+流水灯

我的按键写了中断但是没有用
想请各位帮我看看是什么原因
Key.c

#include "stm32f10x.h"
#include "LED.h"
#define KEY1_INT_GPIO_PORT         GPIOB//组 PB
#define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)//时钟需要开启AFIO 配置中断 APB2
#define KEY1_INT_GPIO_PIN          GPIO_Pin_10//引脚
#define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOB//端口
#define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource10//引脚
#define KEY1_INT_EXTI_LINE         EXTI_Line10//中断线
#define KEY1_INT_EXTI_IRQ          EXTI0_IRQn//中断源中断/事件
#define KEY1_IRQHandler            EXTI0_IRQHandler//中断服务函数
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  /*优先级选择,组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  /* 中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
  /* 主优先级*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /*子优先级*/
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /*使能中断*/
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  //初始化
  NVIC_Init(&NVIC_InitStructure);
}
void EXTI_Key_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure; 
    EXTI_InitTypeDef EXTI_InitStructure;
    /*时钟设置*/
    RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);                                            
    /* NVIC中断*/
    NVIC_Configuration();    
    /*按键使用的GPIO*/
  GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
  /* 浮空 */    
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
    /* 选择EXTI信号源 Selects the GPIO pin used as EXTI Line */
  GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); 
  /*中断事件*/
  EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
    /* 中断模式*/
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 触发模式,上升沿*/
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  /* 使能 */    
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}

Key.h

#ifndef __KEY_H
#define __KEY_H

#define KEY1_INT_GPIO_PORT         GPIOB//组 PB
#define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)//时钟需要开启AFIO 配置中断 APB2
#define KEY1_INT_GPIO_PIN          GPIO_Pin_10//引脚
#define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOB//端口
#define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource10//引脚
#define KEY1_INT_EXTI_LINE         EXTI_Line10//中断线
#define KEY1_INT_EXTI_IRQ          EXTI0_IRQn//中断源中断/事件
#define KEY1_IRQHandler            EXTI0_IRQHandler//中断服务函数
static void NVIC_Configuration(void);
void EXTI_Key_Config(void);
void KEY1_IRQHandler(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "PWM.h"
#define KEY1_INT_GPIO_PORT         GPIOB//组 PB
#define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)//时钟需要开启AFIO 配置中断 APB2
#define KEY1_INT_GPIO_PIN          GPIO_Pin_10//引脚
#define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOB//端口
#define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource10//引脚
#define KEY1_INT_EXTI_LINE         EXTI_Line10//中断线
#define KEY1_INT_EXTI_IRQ          EXTI0_IRQn//中断源中断/事件
#define KEY1_IRQHandler            EXTI0_IRQHandler//中断服务函数
uint8_t KeyNum;
int j=500;

 //流水灯点亮(从中间向两边)
//显示指定次数的呼吸灯
void led_breath_show(uint8_t num_times)
{
    for (uint8_t i = 0; i < num_times; ++i)
    {
        for (uint16_t i = 0; i <= 100; ++i)
        {
            PWM_SetCompare3(i);
            Delay_ms(10);
        }
        for (uint16_t i = 0; i <= 100; ++i)
        {
            PWM_SetCompare3(100 - i);
            Delay_ms(10);
        }
    }
} 
void led_waterfall_up(void)
{
    static const uint16_t waterfall_sequence[] = {~0x18, ~0x3C, ~0x7E, ~0xFF};
    for (uint8_t i = 0; i < sizeof(waterfall_sequence) / sizeof(waterfall_sequence[0]); ++i)
    {
        GPIO_Write(GPIOA, waterfall_sequence[i]);
        Delay_ms(500+j);
    }
}
void led_waterfall_down(void)
{
    static const uint16_t waterfall_sequence[] = {~0x7E, ~0x3C, ~0x18, ~0x00};
    for (uint8_t i = 0; i < sizeof(waterfall_sequence) / sizeof(waterfall_sequence[0]); ++i)
    {
        GPIO_Write(GPIOA, waterfall_sequence[i]);
        Delay_ms(500+j);
    }
}
void KEY1_IRQHandler(void)
{
  //获取中断线EXTI line状态
    if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
    {
        //翻转LED灯    
        void LED1_Turn(void);
        EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
    }  
}
int main(void)
{
    PWM_Init();
    //Key_Init();
    KEY1_IRQHandler();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    while (1)
    {
        //KeyNum = Key_GetNum();
        
            led_waterfall_up();
          led_breath_show(5);
          led_waterfall_down();
          led_breath_show(6);
            
        
    }
  • 写回答

7条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-04-24 10:26
    关注

    引自免费微信小程序:皆我百晓生

    根据您提供的代码,看起来STM32的按键中断配置似乎没有问题,但可能在主循环中的处理部分存在一些小错误。在main.c文件中,中断服务函数KEY1_IRQHandler()的调用位置是不正确的。它不应该放在while (1)循环之前,而应该作为中断处理程序被系统自动调用。

    首先,移除main.c中的这行:

    KEY1_IRQHandler();
    

    然后,确保在主循环中正确处理按键中断。当按键按下时,你应该调用一个函数来改变流水灯的行为,例如增加或减少流水灯的闪烁次数。以下是修改后的main.c代码片段:

    #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "LED.h"
    #include "Key.h"
    #include "PWM.h"
    
    ...
    
    void KEY1_IRQHandler(void)
    {
      // 获取中断线EXTI line状态
      if (EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
      {
          // 翻转LED灯,这里可以改为增加或减少流水灯的闪烁次数
          j += 100; // 每次按键按下,延时时间增加100ms
          EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
      }  
    }
    
    int main(void)
    {
        ...
        while (1)
        {
            led_waterfall_up();
            led_breath_show(5);
            led_waterfall_down();
            led_breath_show(6 * j); // 使用j值动态调整流水灯闪烁次数
            
            // 这里不需要手动调用中断服务函数
            // KEY1_IRQHandler();
        }
    }
    

    这样,每次按键按下时,j变量会递增,从而影响流水灯的闪烁速度。当然,为了更清晰地控制这个行为,你可以创建一个单独的函数来处理按键事件,并在主循环中调用它。

    另外,请确保你的硬件连接正确,按键连接到定义的GPIO引脚上,并且已经将按键连接到GND或Vcc(取决于你的按键类型)以触发中断。同时,确保你的STM32开发板上的复位按钮没有触发任何干扰。

    如果你的问题仍然存在,建议检查Keil uVision或其他IDE的调试器,查看中断是否真正被触发,以及中断处理函数是否被正确执行。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月24日