STM32 60秒倒计时功能详解:初学者指南(附完整代码与仿真图)


STM32 60秒倒计时代码详解(适合初学者)

文件下载
https://pan.baidu.com/s/1sjLb45Aq0-pRn7HZnOPVIA?pwd=sgfi 提取码: sgfi

以下代码实现了一个基于STM32的60秒倒计时功能,通过数码管动态扫描显示时间。代码结构简单,适合初学者理解GPIO控制、数码管驱动和基础计时逻辑。下面分步骤解析代码流程和核心思想。


一、代码整体流程
  1. 头文件与延时函数
    代码开头引入STM32标准库头文件,并定义了一个简单的软件延时函数 Delay()。该函数通过循环空操作消耗时间,精度较低但实现简单。

  2. 数码管码表定义
    定义数组 tab[],存储0-9的数码管段码(共阳极数码管编码)。例如:0xc0 对应数字“0”的段码。

  3. GPIO初始化
    • 启用GPIOB和GPIOA的时钟(RCC_APB2PeriphClockCmd)。
    • 配置GPIO为推挽输出模式(GPIO_Mode_Out_PP),用于控制数码管的段选(GPIOB)和位选(GPIOA)。

  4. 主循环逻辑
    动态显示:交替点亮十位和个位数码管,利用人眼视觉暂留效果实现“同时显示”。
    计时逻辑:通过变量 count 计数到100次后,增加倒计时数值 number,60秒后归零。


二、核心思想详解
1. 数码管驱动原理

段选与位选
段选(GPIOB):控制数码管的各段(a-g)亮灭,通过写入 tab[] 中的段码值显示具体数字。
位选(GPIOA):选择当前点亮的数码管位置(PA0控制十位,PA1控制个位)。
动态扫描:快速切换位选信号(十位→个位→十位…),每次只点亮一个数码管,但因切换速度快(约1ms),人眼会认为两者同时亮起。

// 示例:显示十位
GPIO_ResetBits(GPIOA, GPIO_Pin_1); // 关闭个位
GPIO_SetBits(GPIOA, GPIO_Pin_0);   // 开启十位
GPIO_Write(GPIOB, tab[number/10]); // 输出十位段码
Delay(1000);                       // 短暂延时保持显示
2. 倒计时实现

计时逻辑
count 变量用于记录循环次数,每循环100次(约200ms延时×100=20秒)后,number 加1。
• 当 number 达到60时归零,实现60秒循环。
注意:此方法依赖软件延时,实际时间精度较低(受循环执行速度影响),适合学习基础原理,实际项目建议使用硬件定时器。

++count;
if (count == 100) {  // 每100次循环增加1秒(具体时间由Delay参数决定)
    ++number;
    count = 0;
}
if (number >= 60) {  // 60秒归零
    number = 0;
}
3. 软件延时的局限性

问题Delay() 函数通过空循环消耗时间,期间CPU无法执行其他任务(阻塞式延时)。
改进方向:实际项目中可使用定时器中断或SysTick定时器实现非阻塞延时,提高系统效率。


三、代码优化建议(拓展知识点)
  1. 硬件定时器
    STM32的定时器(如TIM3)可配置为1秒中断,在中断服务函数中更新计时值,精度更高且不阻塞主循环。

  2. 数码管消隐
    在切换位选信号时,可先关闭所有位选,避免切换过程中的残影。

  3. 按键控制
    可增加按键中断功能,实现暂停、重置等交互操作。


完整代码

//头文件
#include "stm32f10x.h"

//=============================================================================
//函数名称:Delay
//功能概要:延时函数
//参数说明:无
//函数返回:无
//=============================================================================
void  Delay (uint32_t nCount)
{
  for(; nCount != 0; nCount--);
}
//=============================================================================
//函数名称:main
//功能概要:主函数
//参数说明:无
//函数返回:int
//=============================================================================
int main(void)
{
	unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//数码管码表

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All;//PB1
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	int number = 0,count=0 ;
	while(1){
		GPIO_ResetBits(GPIOA,GPIO_Pin_1);
		GPIO_SetBits(GPIOA,GPIO_Pin_0);
		GPIO_Write(GPIOB,tab[number/10]) ;
		Delay(1000);
		
		GPIO_ResetBits(GPIOA,GPIO_Pin_0);
		GPIO_SetBits(GPIOA,GPIO_Pin_1);		
		GPIO_Write(GPIOB,tab[number%10]) ;
		Delay(1000);
		++count ;
		if(count == 100){
			++number ;
			count = 0 ;
		}
		if(number >= 60){
			number = 0 ;
		}
	}
	while(1){
		GPIO_SetBits(GPIOB,GPIO_Pin_1);
		Delay(99000);
		GPIO_ResetBits(GPIOB,GPIO_Pin_1);
		Delay(99000);
	}

    
}

仿真图

总结

本代码通过GPIO控制数码管动态显示,结合简单计数实现60秒倒计时。核心思想是动态扫描显示软件计数计时,适合初学者理解嵌入式开发的基础逻辑。后续可在此基础上学习定时器、中断等进阶内容,提升代码效率和功能复杂度。

作者:小美和浪浪

物联沃分享整理
物联沃-IOTWORD物联网 » STM32 60秒倒计时功能详解:初学者指南(附完整代码与仿真图)

发表回复