STM32中断实验,

STM32中断实验,在debug模式下led可以交叉亮灭,但在正常情况下全暗
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include <stdio.h>

void GPIO_init(void) // GPIO 的初始化配置  
{  
GPIO_InitTypeDef GPIO_InitStructure; // 定义一个 GPIO_InitTypeDef 类型的结构体  
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE);   
// 开启 AFIO 时钟和 GPIOB 的外设时钟  
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); // 禁用 JTAG 功能  
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5 |GPIO_Pin_6|GPIO_Pin_7;  
// 选择要控制的 GPIOB 引脚  
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚速率为 50MHz  
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 设置引脚模式为通用推挽输出  
GPIO_Init(GPIOB, &GPIO_InitStructure); // 调用库函数,初始化 GPIOB  
}  
void TIM2_Configuration(void)  
{  
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // 定义一个定时器初始化参数结构体  
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE); // 开启 APB1 的 TIM2 外设时钟  
TIM_DeInit(TIM2); // 复位TIM2定时器,使之进入初始状态
    TIM_TimeBaseStructure.TIM_Prescaler= (7200 - 1); // 设置预分频系数为(7200-1)  
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 向上计数模式  
TIM_TimeBaseStructure.TIM_Period=10000; // 自动加载值设置,累计 10000 个时钟周期(1s)后溢出  
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  
// 根据 TIM_TimeBaseStructure 中指定的参数初始化 TIM2 里的相关寄存器  
 TIM_ClearFlag(TIM2, TIM_FLAG_Update); // 清除溢出中断标志  
 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); // 使能 TIM2 中断,允许更新中断  
 TIM_Cmd(TIM2, ENABLE); // 使能 TIM2 外设  
}  
void TIM2_NVIC_Configuration(void)  
{  
 NVIC_InitTypeDef NVIC_InitStructure; // 定义 NVIC 初始化结构体  
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 选择中断优先级分组 0  
 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; // 选择配置 TIM2 全局中断  
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 占先优先级为 0  
 NVIC_InitStructure.NVIC_IRQChannelSubPriority =1; // 响应优先级为 1  
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能 TIM2 中断通道  
 NVIC_Init(&NVIC_InitStructure); // 根据以上配置初始化 NVIC  
}  
int main()  

{

 int led_state=0;
 
 GPIO_init();  
 GPIO_WriteBit(GPIOB,GPIO_Pin_4,(BitAction)0x01);  //status
 GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)0x01);     //R
 GPIO_WriteBit(GPIOB,GPIO_Pin_6,(BitAction)0x01);  //T
 GPIO_WriteBit(GPIOB,GPIO_Pin_7,(BitAction)0x01);  //User
 TIM2_NVIC_Configuration();  
 TIM2_Configuration();  
 while(1)  
 { 
    if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) // 1S 时间到,检测到 TIM2 中断  
    {  
            led_state++; // 状态加 1  
            switch (led_state)  
            {  
                case 1: // 状态 1:灭掉 User1,点亮 Status  
                    GPIO_WriteBit(GPIOB,GPIO_Pin_7,(BitAction)0x01);                    
                    GPIO_WriteBit(GPIOB,GPIO_Pin_4,(BitAction)0x00);  
                    break;  
                
                case 2: // 状态 2:灭掉 Status,点亮 RS485-R  
                    GPIO_WriteBit(GPIOB,GPIO_Pin_4,(BitAction)0x01);  
                    GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)0x00);  
                    break;  
                
                case 3: // 状态 3:灭掉 RS485-R,点亮 RS485-T  
                    GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)0x01); 
                    GPIO_WriteBit(GPIOB,GPIO_Pin_6,(BitAction)0x00); 
                    break;  
                
                case 4: // 状态 4:灭掉 RS485-T,点亮 User1  
                    GPIO_WriteBit(GPIOB,GPIO_Pin_6,(BitAction)0x01);  
                    GPIO_WriteBit(GPIOB,GPIO_Pin_7,(BitAction)0x00);  
                    led_state=0; // led_state 置 0,下个 1s 时间到后可再次进入状态 1  
                    break;  
                
                default:
                    break;
                }  
            TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update); // 清除中断标志位  
    }
}  
}   
  

你这个定时器中断服务函数的内容怎么放在main函数的while循环里咯!这是有问题的哦!

既然使能了定时器中断,就该在中断函数里做main函数里那个循环里的功能,否则默认的中断服务函数清空了标志,导致main里读不到状态,自然无法计数,也就无法实现状态切换

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7526172
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:用stm32中断实现led亮灭灯和串口通信
  • 除此之外, 这篇博客: STM32(1):点亮LED(上)中的 debug时钟设置 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 那么我们的时钟是多少呢?如果你是调试模式,这个时钟是通过目标选项(Options For Target)来进行配置,开心就好:
    file
    如果是直接烧录到STM32的板子里面,默认使用的是HSI(High Speed Internal,内部高速时钟),即8MHz;所以为了Debug的效果和烧录之后的效果保持一致,最好是设置为一致的时钟频率。

  • 您还可以看一下 李博老师的STM32智能浇花系统从0到1开发实战课程中的 STM32智能浇花系统-02点亮LED灯小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    答案:

    该问题可能是由时钟频率不一致导致的。在调试模式下,时钟频率由目标选项进行配置,与烧录之后的频率不一致可能会导致LED在调试模式下能够交叉亮灭,但在正常模式下却全暗。

    解决方法如下:

    1. 确认时钟频率设置

    在代码中确认时钟频率设置是否与烧录之后的配置一致。具体方法如下:

    RCC_DeInit();  // 复位时钟
    RCC_HSEConfig(RCC_HSE_ON);  // 开启外部高速时钟
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);  // 等待外部高速时钟启动
    
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  // 设置PLL时钟
    RCC_PLLCmd(ENABLE);  // 开启PLL时钟
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);  // 等待PLL时钟启动
    
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  // 将SYSCLK设置为PLL时钟
    while (RCC_GetSYSCLKSource() != 0x08);  // 等待SYSCLK稳定
    
    RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB时钟 = 系统时钟
    RCC_PCLK2Config(RCC_HCLK_Div1); // APB2时钟 = AHB时钟
    RCC_PCLK1Config(RCC_HCLK_Div2); // APB1时钟 = AHB时钟/2
    
    1. 确认中断设置

    在检查时钟设置无误之后,还需要确认中断设置是否正确。具体方法如下:

    • 开启指定外设的时钟
    if (GPIOx == GPIOA) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    else if (GPIOx == GPIOB) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    else if (GPIOx == GPIOC) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    
    • 配置GPIO引脚的输入/输出模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  // 配置引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 设置为浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIO
    
    • 配置外部中断的触发方式
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;  // 中断线0
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;  // 中断模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;  // 触发方式
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;  // 开启中断线0
    EXTI_Init(&EXTI_InitStructure);  // 初始化中断
    
    • 编写中断服务函数
    void EXTI0_IRQHandler(void) {
      if (EXTI_GetFlagStatus(EXTI_Line0) != RESET) {  // 判断中断标志是否置位
        EXTI_ClearFlag(EXTI_Line0);  // 清除中断标志位
        // 在此添加中断处理代码
      }
    }
    

    参考资料: