设计与开发

单片机倒计时器设计 奥运倒计时器,请看单片机如何编程实现

小编 2025-06-08 设计与开发 23 0

奥运倒计时器,请看单片机如何编程实现

倒计时器简介

单片机倒计时器是基于定时而设计的实现及时报警的装置。它由键盘扫描、动态LED显示电路、报警三大部分构成,以实现对计时时间的控制。同时装置还用一个由电平控制的报警装置,用以实现倒计时时间到时进行声音提示。

倒计时器的实时性强,可操作性好,能应对不同要求进行过相应的调整以适应不同环境,倒计时器使用范围非常广泛,不难忘记奥运倒计时,场面让人震撼。

倒计时

工程设计

以proters仿真工程为例,建立一个倒计时工程,主要器件需要用到AT89C51单片机芯片,采用两个数码管显示,数码管采用共阴极,一个倒计时开启按钮,按钮按下低电平有效,一个扬声器,扬声器在工作时发出声音,PR1上拉排阻,一般可以根据亮度强弱调节电阻大小。

工程设计

单片机程序设计

程序设计可以分为几部的工作,1,定时器timer()初始化和开启;2,数码管显示驱动模块;3,倒计时器功能设计。4,按键检测和扬声器工作。用定时器主要就是可以做到更精确倒计时,数码管扫描显示也不好抖动,然而刷新显示数码管的周期也要选择一个合理的时间范围,一般不能大于50ms,不然人眼是可以看出来。

程序设计

程序代码

#include <reg52.H>

#include <intrins.h>

typedef unsigned char uint08;

typedef unsigned short int uint16;

typedef unsigned long int uint32;

#define INIT_TIME_VAR 10000 // 10 ms

#define BIT(a) (1<<a)

sbit BezzerIO = P1^6;

//共阴 数码管段码

char code LedDisplayCode1[] =

{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

//共阳 数码管段码

char code LedDisplayCode2[] =

{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

// 数码管显示 缓存

uint08 AppRefreshDisplayBuf[2];

// 数码管显示 开启显示标志

uint08 AppRefreshDisplayflag=0;

uint16 time10msCount;

/*

void delay_ms(uint16 ms)

{

uint16 i,j;

for(i=0;i<ms;i++)

{

for(j=0;j<255;j++)

{

_nop_();

}

}

}

*/

// 定时器初始化

void TimerInit()

{

TMOD = 0X01; // 设置工作模式1

TH0 = (65536 - INIT_TIME_VAR)/256;//(65536-X)设定初值10ms,X=10000

TL0 = (65536 - INIT_TIME_VAR)%256; //(65536-X)设定初值10ms,X=10000

EA = 1; // 允许全部中断

ET0 = 1; // 允许定时器中断

TR0 = 1; // 开启定时

}

static uint08 BitFlag=0;

// 刷新显示数码管

void refreshDisplay(void)

{

uint08 code refreshDisplayCode[2]={0x01,0x02};

static uint08 refreshDisplayPt; // 刷新位地址

static uint08 refreshDisplayBuf[2]; // 刷新位段码

if(AppRefreshDisplayflag)

{

refreshDisplayBuf[0] = AppRefreshDisplayBuf[0];

refreshDisplayBuf[1] = AppRefreshDisplayBuf[1];

AppRefreshDisplayflag = 0;

}

refreshDisplayPt ++;

if(refreshDisplayPt>1) refreshDisplayPt=0;

P0 = 0x00; // 关闭上次的数码

P2 = 0x03; // 关闭上次的数码

_nop_();

_nop_();

P2 = refreshDisplayCode[refreshDisplayPt]; // 第一个数码管点亮

P0 = LedDisplayCode1[refreshDisplayBuf[refreshDisplayPt]];

}

void main()

{

uint08 CountDown;

// 定时器初始化

TimerInit();

// 初始化端口

P0 = 0x00;

P2 = 0x00;

P1 = 0x80;

CountDown = 0;

while(1)

{

if(!(P1 & BIT(7)))

{

CountDown = 15;

// 倒计时器 开始运行

AppRefreshDisplayBuf[0] = CountDown%10;

AppRefreshDisplayBuf[1] = CountDown/10%10;

AppRefreshDisplayflag = 1;

time10msCount = 0;

BezzerIO = 0; // 扬声器关闭

}

if( CountDown )

{

if(time10msCount>100) // 1 S

{

time10msCount = 0;

CountDown--;

if( CountDown == 0)

{

BezzerIO = 1; // 扬声器开启

}

// 倒计时器 开始运行

AppRefreshDisplayBuf[0] = CountDown%10;

AppRefreshDisplayBuf[1] = CountDown/10%10;

AppRefreshDisplayflag = 1;

}

}

}

}

void timer1() interrupt 1 //定时2ms

{

TH0 = (65536 - INIT_TIME_VAR)/256;//(65536-X)设定初值10ms,X=10000

TL0 = (65536 - INIT_TIME_VAR)%256; //(65536-X)设定初值10ms,X=10000

refreshDisplay(); // 刷新数码管

time10msCount++;

}

效果图

头条文章--在Excel中实现“世界杯”倒计时器设计

哈喽,大家好,上次我们利用了OnTime方法实现了数码管时钟的设计,感觉它还是蛮神奇的,不是吗?呵呵,当时我在视频里就说过,我准备利用这个方法继续推出有关倒计时的作品。

为什么我们要设计倒计时器呢?倒计时器已成为人们日常生活中必不可少的物品,广泛用于个人家庭以及车站、码头、剧院、办公室等公共场所,给人们的生活、学习、工作、娱乐带来极大的方便。随着技术的发展,人们已不再满足于钟表原先简单的报时功能,希望出现一些新的功能,诸如日历的显示、闹钟的非接触式止闹、跑表功能、重要日期倒计时显示等,以带来更大的方便,而所有这些,又都是以数字化的倒计时器为基础的,而作为办公室Office办公工作人员,做的事情也很杂,很有可能领导会将单位某个活动、节日等事宜的时间提示让你用倒计时的方式通过电脑呈现在LED屏幕供单位上下都天天能够看到。但是,作为Office办公工作人员一般都不是很懂用单片机技术去设计,鉴于如此情况,是否我们就没法做到设计倒计时器呢?答案是否定的,我们同样可以利用Office高级应用技术在Office组件,比如在Excel、PowerPoint等里边实现设计倒计时器。因此,研究实用倒计时器及其扩展应用,有着非常现实的意义,具有很大的实用价值。

鉴于对OnTime方法的痴迷,我们以模拟世界杯倒计时为题设计了本期的倒计时作品,希望能够给予各位粉丝技术上的帮助,同时也是为了抛砖引玉哦,更感谢大家的厚爱哦!

好了,不废话了,我们还是以干货的形式给大家分享吧!

一、Excel下世界杯倒计时器前端界面设计

倒计时黑屏幕、四个表单按钮。如下图所示

图1 Excel下世界杯倒计时器前端界面

二、Excel下世界杯倒计时器后台窗体界面

插入6个组合框选择列表控件和2个命令按钮。如下图所示

图2 Excel下世界杯倒计时器后端窗体界面

三、Excel下世界杯倒计时器功能代码实现及前端界面四个表单按钮控件运行宏指定

(一) Excel下世界杯倒计时器功能代码实现

1、模块1代码:

Public TimeOn As Double '公有全局变量TimeOn为当前的瞬时时间,便于回传数据

Public Uload_Form_Flag As Boolean '公有全局变量Uload_Form_Flag为是否卸载关闭窗体的标志,便于回传数据

Public DateTime_Str, yr '公有全局变量DateTime_Str、yr分别为取得的日期时间串、取得的年号,便于回传数据

Sub Main() '“倒计时器”开启的引导主程序

Call 复位倒计时

SelectDate_Time_Form.Show

If Uload_Form_Flag = False Then '凡是经过窗体点击了确定后,都强制性将Uload_Form_Flag置为False造 _

成假象窗体未关闭

Call 开始倒计时

Else

DateTime_Str = "" '一旦取消了倒计时操作后,立即清空日期时间串变量DateTime_Str的值

MsgBox "您取消了实施倒计时器工作的操作!", vbInformation, "提示"

Exit Sub

End If

End Sub

'Application.OnTime方法的参数说明

'Application.OnTime(EarliestTime,Procedure as String,LatestTime],[Schedule])

'EarliestTime调用程序的时间

'Procedure调用程序的程序名,类型String

'LatestTime程序执行的结束时间,可选,默认不停调用

'Schedule默认True:预定新的调用过程,False非预定调用新的过程

Sub 开始倒计时() '“倒计时器”的具体子程序定义

Dim End_Date As Date

End_Date = VBA.CDate(DateTime_Str) '未来日期时间da

If End_Date < Now Then '未来时间比当前时间早,则报错,终止程序运行

MsgBox "未来时间" & Format(End_Date, "yyyy-m-d hh:mm:ss") & "小于或迟于当前时间" & Now & _

"的错误,退出!", vbInformation, "提示"

Call 复位倒计时

Exit Sub

Else

TimeOn = Now + TimeSerial(0, 0, 1) '等价于Now + TimeValue("00:00:01")以1秒的步进定时跳变

s = DateDiff("s", Now, End_Date) 's首先取得在这个时间差内,以秒为单位的所有秒数

y = Int(s / 31536000) '一年按照365天换算算是【31536000】秒,取整强烈建议用Int(s / 31536000)纯 _

粹去小数非四舍五入的的整除而非s\31536000这种纯粹去小数非四舍五入的的整除,原因是s\31536000容 _

易发生数据溢出,以下类似

s = s - y * 31536000 '取得即将取“月”数所用的秒数

mon = Int(s / 2592000) '一月按30天换算算是【2592000】秒,非四舍五入取整得到月数mon

s = s - mon * 2592000 '取得即将取“天”数所用的秒数

d = Int(s / 86400) '一天换算是【86400】秒,非四舍五入取整得到天数d

s = s - d * 86400 '取得即将取“小时”数所用的秒数

h = s \ 3600 '一小时换算是【3600】秒,非四舍五入取整"s\3600"("s\3600"针对短数据可以这样非四 _

舍五入的整除)得到小时数h,以下解释类似

s = s - h * 3600 '取得即将取“分钟”数所用的秒数

m = s \ 60 '一分钟换算是【60】秒,非四舍五入取整得到分钟数m

s = s - m * 60 '取得最后零头“秒”数s

If y = 0 And mon = 0 And d = 0 And h = 0 And m = 0 And s = 0 Then

Dim rg As Range, str_words As String, start_Font_Size As Integer, end_Font_Size As Integer

MsgBox "时间到!", vbInformation, "提醒"

str_words = Format(End_Date, "yyyy年") & "世界杯欢迎您!"

Set rg = Sheets(1).Cells(1, 1)

rg.HorizontalAlignment = xlCenter 'rg范围中的内容居中对齐

start_Font_Size = 1 '设置动画起始字体号1号

end_Font_Size = 40 '设置动画结束字体号40号

'调用两次scale_words过程,以增强文字缩放动画效果

scale_words str_words, rg, start_Font_Size, end_Font_Size '第一次调用字体缩放动画过程

scale_words str_words, rg, start_Font_Size, end_Font_Size '第二次调用字体缩放动画过程

DateTime_Str = "" '完成了倒计时,清空日期时间串变量DateTime_Str的值

Exit Sub '强行结束过程

Else

'倒计时器剩余的日期串

Countdown_Remain_date_str = "距离 " & Format(End_Date, "yyyy年mm月dd日") & "“世界杯”开幕" & Chr(10) _

& "还有:" & y & " 年 " & mon & " 个月 " & d & " 天"

'倒计时器剩余的时间串

Countdown_Remain_time_str = Chr(10) & "剩余时间[" & h & " 小时 " & m & " 分钟 " & s & " 秒]" & Chr(10)

'倒计时器呈现的当前时间串

Countdown_NowTime_str = "当前时间:" & Format(Now, "yyyy年m月d日 hh:mm:ss")

'倒计时器串为以上三个字符串的合并连接

Countdown_str = Countdown_Remain_date_str & Countdown_Remain_time_str & Countdown_NowTime_str

Cells(1, 1) = Countdown_str

Application.OnTime TimeOn, "开始倒计时", , True '开始定时地回调过程“开始倒计时”自身

End If

End If

End Sub

Sub 暂停倒计时()

If DateTime_Str = "" Then '若获得的日期时间串为空,则终止任何操作

prompt_str = "您没有启动倒计时或复位过倒计时" & Chr(10) & "或可能刚才点击了<启动倒计时>按" _

& Chr(10) & "钮却未选择倒计时参数!" & Chr(10) & "禁止暂停倒计时!"

MsgBox prompt_str, vbInformation, "提示"

Exit Sub

Else '否则,执行应有的暂停倒计时操作

Application.OnTime TimeOn, "开始倒计时", , False '终止定时地回调过程“开始倒计时”自身

End If

End Sub

Sub 继续倒计时()

If DateTime_Str = "" Then '若获得的日期时间串为空,则终止任何操作

prompt_str = "您没有启动倒计时或复位过倒计时" & Chr(10) & "或可能刚才点击了<启动倒计时>按" _

& Chr(10) & "钮却未选择倒计时参数!" & Chr(10) & "无法继续倒计时!"

MsgBox prompt_str, vbInformation, "提示"

Exit Sub

Else '否则,执行应有的继续倒计时操作

Application.OnTime TimeOn, "开始倒计时", , True '继续开始定时地回调过程“开始倒计时”自身

End If

End Sub

Sub 复位倒计时()

On Error Resume Next

Application.OnTime TimeOn, "开始倒计时", , False '终止定时地回调过程“开始倒计时”自身

Reseted_Countdown_str = "距离 ----年--月--日“世界杯”开幕" & Chr(10) & "还有: - 年 - 个月 - 天" & Chr(10) _

& "剩余时间[ - 小时 - 分钟 - 秒]" & Chr(10) & "当前时间:----年--月--日 --:--:--"

Cells(1, 1).Font.Size = 24

Cells(1, 1) = Reseted_Countdown_str

DateTime_Str = "" '一旦复位倒计时操作后,立即清空日期时间串变量DateTime_Str的值

On Error GoTo 0

End Sub

'If y Mod 400 = 0 Or (y Mod 100 <> 0 And y Mod 4 = 0) Then 闰年--2月29天,否则平年--2月28天

Function Is_LeepYear(y) As Boolean '判断是否是闰年Leep year

If y Mod 400 = 0 Or (y Mod 100 <> 0 And y Mod 4 = 0) Then

Is_LeepYear = True '闰年

Else

Is_LeepYear = False '平年

End If

End Function

'缩放文字的动画效果过程,其中:str_words缩放的文字、在rg区域缩放,缩放文字字体动画开始字体大

'小s_fontsize、结束动画文字字体大小e_fontsize

Sub scale_words(str_words As String, rg As Range, s_fontsize As Integer, e_fontsize As Integer)

rg = str_words

m = s_fontsize 'm获取了形式参数开始字体大小变量s_fontsize的值

Do While m <= e_fontsize '当前字体大小小于或等于给定的形式参数结束字体大小变量e_fontsize时循环

rg.Font.Size = m '设置瞬时字体大小

m = m + 1 'm不断变化

delay 0.01 '每次循环延时0.01秒

Loop

End Sub

Sub delay(t As Single) '自定义一个延时过程,单精度类型变量t代表延时时间间隔

Dim t1 As Single

t1 = Timer 't1记下瞬时的时间触发器Timer的值(Timer会不断变化的)

Do

DoEvents '转让控制权,让操作系统执行其他任务

Loop While Timer - t1 < t '新的Timer和之前的t1的差值小于给定的延时间隔时间t,则循环

End Sub

2、窗体代码:

Private Sub UserForm_Initialize() '窗体启动初始化

Uload_Form_Flag = False

year_ComboBox.Style = fmStyleDropDownList

month_ComboBox.Style = fmStyleDropDownList

day_ComboBox.Style = fmStyleDropDownList

hour_ComboBox.Style = fmStyleDropDownList

minute_ComboBox.Style = fmStyleDropDownList

second_ComboBox.Style = fmStyleDropDownList

month_ComboBox.Enabled = False

day_ComboBox.Enabled = False

hour_ComboBox.Enabled = False

minute_ComboBox.Enabled = False

second_ComboBox.Enabled = False

year_ComboBox.Clear

day_ComboBox.Clear

hour_ComboBox.Clear

minute_ComboBox.Clear

second_ComboBox.Clear

For i = 1900 To 9999 '年份选择列表初始化

year_ComboBox.AddItem i

Next

year_ComboBox.Value = Year(Date) + 1 '设定默认年份为现在年份+1,并将选择焦点定格在年份选择列表

year_ComboBox.SetFocus

End Sub

'窗体卸载关闭事件

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)

Uload_Form_Flag = True '一旦执行窗体卸载关闭(释放窗体曾经占用的资源空间),则将 _

Uload_Form_Flag状态标志置为真,表示窗体已卸载关闭

Cancel = False '同时,将“取消卸载关闭窗体”标志置为“假”,以表示“不取消窗体卸载关 _

闭”(即允许卸载关闭窗体)

End Sub

Private Sub ConfirmBtn_Click() '确定参数选择

mon = month_ComboBox.Value

dy = day_ComboBox.Value

h = hour_ComboBox.Value

h = IIf(h = "", 0, h)

m = minute_ComboBox.Value

m = IIf(m = "", 0, m)

s = second_ComboBox.Value

s = IIf(s = "", 0, s)

If yr = "" Or mon = "" Or dy = "" Then

MsgBox "日期中“年、月、日”少选或未选,请重新选定!", vbInformation, "提示"

year_ComboBox.Clear

For i = 1900 To 9999 '年份选择列表初始化

year_ComboBox.AddItem i

Next

month_ComboBox.Clear

day_ComboBox.Clear

hour_ComboBox.Clear

minute_ComboBox.Clear

second_ComboBox.Clear

year_ComboBox.Value = Year(Date) + 1 '设定默认年份为现在年份+1,并将选择焦点定格在 _

年份选择列表

year_ComboBox.SetFocus

Else

DateTime_Str = yr & "-" & mon & "-" & dy & " " & h & ":" & m & ":" & s

Unload SelectDate_Time_Form

Uload_Form_Flag = False '强制性将Uload_Form_Flag置为False造成假象窗体未关闭,便于真正在模块1 _

中间“倒计时器”程序正常执行

End If

End Sub

Private Sub CancelBtn_Click() '取消操作

Unload SelectDate_Time_Form

Exit Sub

End Sub

Private Sub year_ComboBox_DropButtonClick() '用ComboBox_DropButtonClick()方法而不用ComboBox_Change _

()的原因是只有DropButtonClick()是点击组合框的下拉倒三角按钮的触发行为事件对月份组合框实施开启功能 _

,这样月份的组合框才能保证一表单启动初始化后是禁用的,开始选择年的时候,月份选择列表跟随初始化

yr = year_ComboBox.Value

month_ComboBox.Enabled = True

month_ComboBox.Clear

For i = 1 To 12

month_ComboBox.AddItem i

Next

End Sub

Private Sub month_ComboBox_Change() '选择月的时候,天数选择列表跟随初始化

i = month_ComboBox.Value

day_ComboBox.Enabled = True

Select Case i

Case 1, 3, 5, 7, 8, 10, 12: days_31

Case 4, 6, 9, 11: days_30

Case 2: days_29_Or_28

End Select

End Sub

Private Sub day_ComboBox_Change() '选择日的时候,小时选择列表跟随初始化

hour_ComboBox.Enabled = True

hour_ComboBox.Clear

For i = 0 To 23

hour_ComboBox.AddItem i

Next

End Sub

Private Sub hour_ComboBox_Change() '选择小时的时候,分选择列表跟随初始化

minute_ComboBox.Enabled = True

minute_ComboBox.Clear

For i = 0 To 59

minute_ComboBox.AddItem i

Next

End Sub

Private Sub minute_ComboBox_Change() '选择分的时候,秒选择列表跟随初始化

second_ComboBox.Enabled = True

second_ComboBox.Clear

For i = 0 To 59

second_ComboBox.AddItem i

Next

End Sub

Sub days_31() '月大--31天

day_ComboBox.Clear

For i = 1 To 31

day_ComboBox.AddItem i

Next

End Sub

Sub days_30() '月小--30天

day_ComboBox.Clear

For i = 1 To 30

day_ComboBox.AddItem i

Next

End Sub

Sub days_29_Or_28() '闰年2月份29天,平年2月份28天(例如2020年就是闰年)

day_ComboBox.Clear

If Is_LeepYear(yr) Then '闰年2月份天数

For i = 1 To 29

day_ComboBox.AddItem i

Next

Else '平年2月份天数

For i = 1 To 28

day_ComboBox.AddItem i

Next

End If

End Sub

3、ThisWorkbook代码:

Private Sub Workbook_Open() '工作簿一打开,就实施复位“倒计时器”的操作

Call 复位倒计时

End Sub

(二)Excel下世界杯倒计时器前端界面四个表单按钮控件运行宏指定

分别给这四个表单控件按钮指定运行宏。如下图所示

图3 四个表单控件按钮的运行宏指派

四、Excel下世界杯倒计时器运行测试界面

1、启动倒计时功能:点击“启动倒计时”按钮后,弹出选择日期时间的对话框选择。如下图所示

图4 启动倒计时

2、如果点击了参数选择窗体上的<取消>或者标题栏的<X>关闭按钮,则提示取消操作。如下图所示

图5 点击了<取消>或<X>关闭按钮的结果

3、确定要进行选择日期时间参数:选择日期时间参数后点击“确定”命令按钮。如下图所示

图6 日期时间参数选择

4、点击“确定”后的效果:执行确定命令后,开始倒计时。如下图所示

图7 确定参数后的效果

5、时间到提示:时间到了会自然提示“时间到!”提示。如下图所示

图8 时间到提醒

6、点击上图的“确定”后,前端界面出现文字缩放动画展示。如下图所示。

图9 倒计时到的前端界面文字缩放动画

五、关键技术小结

1、判断闰年和平年的方法:If y Mod 400 = 0 Or (y Mod 100 <> 0 And y Mod 4 = 0) Then 闰年--2月29天,否则平年--2月28天

2、实现窗体上各组合框选择列表的联动跟随变化:类似如下图所示

图10 各组合框选择列表的跟随智能变化

3、充分利用Select Case语句实现各个月份天数的设定:如下图所示。

图11 各月份天数设定

4、倒计时器时间到的前端文字缩放动画展示技术。代码如下截图所示

图12 时间到的前端文字缩放动画展示代码

好了,倒计时的完整设计的头条文章就分享到这里,希望大家多多点评和关注(“头条号:跟我学office高级办公”)哦!

相关问答

倒计时器 的种类有哪些?

[回答]倒计时器选北京大荣亚太科贸有限公司好,北京大荣亚太科贸有限公司专业提供各种LED显示产品,包括LED点阵屏,数码管时钟等各种计时产品;以及重大活动...

猜你喜欢