You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F103C8基于SysTick寄存器编程的LED按键控制代码验证

STM32F103C8寄存器级代码验证(按键无响应+LED闪烁需求)

需求与环境

  • 硬件:STM32F103C8,系统时钟8MHz
  • 外设连接:
    • PA1:上拉输入(按键)
    • PB8、PB9:推挽输出(LED)
  • 功能要求:第一次按下按键,LED每秒闪烁;再次按下按键,关闭所有LED
  • 问题:Proteus仿真中按键无响应,需验证代码正确性

原始代码

#include "stm32f10x.h"
int main(void){
    int S=0;
    RCC->APB2ENR|=0x0000000C;
    GPIOA->CRL=0;
    GPIOB->CRH=0;
    GPIOA->CRL|=0x00000880;
    GPIOA->ODR=1;
    GPIOB->CRH|=0x00000011;
    SysTick->LOAD=8000000;
    SysTick->VAL=0;
    SysTick->CTRL=5;
    while(1){
        if(!(GPIOA->IDR&(1<<1))){
            while(1){
        if((SysTick->CTRL&(1<<16))){
            if(S==0){
            GPIOB->BSRR=(1<<8);
            GPIOB->BSRR=(1<<25);
                S=1;
            }
                else{
                GPIOB->BSRR=(1<<24);
            GPIOB->BSRR=(1<<9);
                    S=0;
                }
            }
        if(!(GPIOA->IDR&0x02)){
        break;
        }
        }
                GPIOB->BSRR=(1<<24);
        GPIOB->BSRR=(1<<25);
        }
    }
}

代码问题分析

1. GPIOA上拉配置错误

PA1配置为上拉输入时,需要将对应ODR位置1以启用内部上拉电阻。原始代码中GPIOA->ODR=1仅设置了PA0的上拉,PA1的上拉未启用,导致按键按下时电平检测异常。

2. SysTick延时周期错误

8MHz时钟下,SysTick要实现1秒延时,LOAD寄存器应设置为7999999(因为SysTick从LOAD值递减到0时触发计数,总周期为LOAD+1个时钟周期)。原始代码设置为8000000会导致实际延时略大于1秒。

3. 按键检测无消抖处理

按键按下/释放时存在机械抖动,直接检测电平会导致误触发(比如多次进入/退出闪烁逻辑),需要添加消抖延时。

4. 内部循环按键检测逻辑缺陷

内部循环中检测到按键按下直接退出,但未处理抖动,且没有等待按键释放,容易导致误操作。

修正后的代码

#include "stm32f10x.h"

// 简单软件消抖函数
void Key_Delay(void){
    uint32_t i;
    for(i=0; i<20000; i++);
}

int main(void){
    int S=0;
    // 使能GPIOA和GPIOB时钟
    RCC->APB2ENR |= 0x0000000C;
    
    // 配置PA1为上拉输入
    GPIOA->CRL &= ~0x00000F00; // 清除PA1的CRL位[7:4]
    GPIOA->CRL |= 0x00000800;  // PA1: CNF1=10(上拉输入), MODE1=00(输入)
    GPIOA->ODR |= (1<<1);      // 启用PA1内部上拉
    
    // 配置PB8、PB9为推挽输出
    GPIOB->CRH &= ~0x000000FF; // 清除PB8、PB9的CRH位[7:0]
    GPIOB->CRH |= 0x00000011;  // PB8/PB9: CNF=00(推挽输出), MODE=01(10MHz输出)
    
    // 配置SysTick为1秒周期
    SysTick->LOAD = 7999999;   // 8MHz时钟,LOAD=8000000-1
    SysTick->VAL = 0;          // 清除当前计数值
    SysTick->CTRL = 5;         // 使能SysTick,使用处理器时钟
    
    while(1){
        // 检测按键按下(带消抖)
        if(!(GPIOA->IDR & (1<<1))){
            Key_Delay();
            if(!(GPIOA->IDR & (1<<1))){
                // 等待按键释放
                while(!(GPIOA->IDR & (1<<1)));
                Key_Delay();
                
                // 进入闪烁循环
                while(1){
                    // 检测SysTick计数完成标志(自动清除)
                    if(SysTick->CTRL & (1<<16)){
                        if(S == 0){
                            // PB8亮,PB9灭
                            GPIOB->BSRR = (1<<8);
                            GPIOB->BSRR = (1<<25);
                            S = 1;
                        } else {
                            // PB8灭,PB9亮
                            GPIOB->BSRR = (1<<24);
                            GPIOB->BSRR = (1<<9);
                            S = 0;
                        }
                    }
                    
                    // 检测按键按下退出闪烁(带消抖)
                    if(!(GPIOA->IDR & (1<<1))){
                        Key_Delay();
                        if(!(GPIOA->IDR & (1<<1))){
                            // 等待按键释放
                            while(!(GPIOA->IDR & (1<<1)));
                            Key_Delay();
                            break;
                        }
                    }
                }
                // 退出闪烁后关闭所有LED
                GPIOB->BSRR = (1<<24);
                GPIOB->BSRR = (1<<25);
                S = 0;
            }
        }
    }
}

修正说明

  • 启用PA1的内部上拉电阻,确保按键未按下时为高电平,按下时为低电平。
  • 修正SysTick的LOAD值,保证1秒准确延时。
  • 添加软件消抖函数,避免按键抖动导致的误触发。
  • 优化按键检测逻辑,增加按键释放等待,确保单次按键触发一次操作。

内容的提问来源于stack exchange,提问作者Tchalago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:07:01