面向单片机编程(五)- 多位数码管倒计时
标签: 单片机 C51 数码管 倒计时
在之前的文章中我们学习了单片机是如何实现一位数码管显示数字,一位数码管只能显示个位数让我们观察到,那如何显示十位数、百位数,甚至更大的数字呢。其实也并不复杂,我们可以选用多位数码管来进行显示数字,当每一个0到来的时候下一个十位的数码管再开始工作就可以了。
功能概述上一章节我们介绍了一位数码管的功能,下面介绍多位数码管与一位数码管的共同点和不同点。每位数码管都分为段码线和位码线以此来控制数码管的工作,多位数码管并不是很多很多个一位数码管组成的,实际上他们的8根段码线是共用的,而对每个数码管进行控制的线叫做选位线,共阴数码管哪个选位线是低电平,哪个数码管就会显示,反之共阳数码管也是一样的。
显示原理多位数码管也是由LED灯组和成的,它的段同样也是a,b,c,d,e,f,g,dp,但是多位数码管比一位数码管多了一个选位线,因此我们需要对这个选位线的引脚也进行定义。
电路连接
所使用的单片机为AT89C52,数码管为共阳的数码管,开始全部P0设置为低电平,开始运行后发生变化。
程序设计
设计的程序首先根据我们连接好的电路图来进行,首先我们明确我们需要让我们的两位的共阳数码管显示59倒计时到0,对多位数码管上的引脚和单片机上的IO口进行定义,当我们在写这个程序时有两种思路,一种是利用循环和延时的方式来实现数字的倒数,而另一种方式需要用到新的知识定时器的方式,定时器是C51单片机一个专门用来计数的模块,但是其定义也需要我们去记忆,因此本章我们选用循环来进行倒计时。
多位数码管59倒计时到0显示,功能实现代码如下:
#include<reg52.h>
#define uchar unsigned char#define uint unsigned intuchar code table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};uchar code LED_W[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};void delay(uint i){uint x,j;for(j=0;j<128;j++);for(x=0;x<=148;x++);}void display(uint temp){P0=0;P2=0xfb;P0=table[temp/100];delay(2);P0=0;P2=0xfd;P0=table[temp%100/10];P0=P0 | 0x80;delay(2);P0=0;P2=0xfe;P0=table[temp%10];delay(2);}void main(){uint i=100,j;while(1){ if(i!=0){for(j=0;j<10;j++){display(i);}i--;}else{while(1){ uint i;for(i=0;i<10;i++){P2=0xfe;P0=0x3f;delay(2);P2=0xfd;P0=0x3f;delay(2);P2=0xfb;P0=0x3f;delay(2);}P2=0xff;delay(200);}}}}
总结
多位数码管的学习和一位数码管类似,只不过需要对选位线来进行编写,不同的多位数码管也都是需要用逻辑的方式改变选位线引脚的电平来控制属于哪个的数码管显示。共阴数码管和共阳数码管是不一样的字码,这需要大家对其进行区分。接下来我们将学习如何使用数码管实现时间的计时。
奥运倒计时器,请看单片机如何编程实现
倒计时器简介
单片机倒计时器是基于定时而设计的实现及时报警的装置。它由键盘扫描、动态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++;
}
效果图
相关问答
单片机倒计时程序 编写?工作过程:首先上电之后先调整定时时间,每按一次加键定时加十分钟,减键同理,当设置好分钟之后按下设置键等到数码管闪动后松开按键进入小时设置,每按一次加...
如何将数码管与LCD同时接入 单片机 ,我想做一个999秒的 倒计时 ,同时用LCD显示我的英文名字?用个引脚比较多的单片机就可以了。比如STC89C52等等。数码管用扫描方式,LCD如果用1602就直接写,也不会占用单片机多少时间。用个引脚比较多的单片机就可以了...
单片机 的主 程序 为什么是死循环?朋友们好,我是电子及工控技术,我来回答这个问题。我们从单片机的工作原理可以看出单片机是执行程序来完成我们所要求的任务的,在单片机中有很多子程序,单片机...
怎样51 单片机 调用两个 子程序 - 少女耷哒哒哒哒哒 的回答 - 懂得估计是进入到倒计时程序,一直没有出来。主程序直接调用洗涤程序。定时器,每到1s时,再去调用一下倒计时程序。MOVR0,#08HMOVA,#0FEHLOOP:MOVP1,ALCA...
急求:用51 单片机 实现从99 倒计时 按键控制实验,要求按下K1开...[最佳回答]建议去我的领地5d6d的proteus论坛看看那里有很多单片机仿真实例,包括仿真图和源码搜5d6d和proteus2个关键词建议去我的领地5d6d...
89 c 52独立按键介绍?主要器件主要有数码管(用来显示倒计时间、成功抢答的选手编号)按键(主持人按键、选手按键)使用独立键盘吧,程序循环等待按键输入,一旦有选手按下抢答键...
单片机 为什么叫 单片机 ?单片机之所以叫单片机,是因为单片机芯片把CPU、数据存储器、程序存储器、总线系统都集成到了一个芯片上。要搞清楚这个问题,我们必须先搞明白计算机的组成部分...
单片机 继电器仿真_汽配人问答[最佳回答]啊首先你的数码管为什么选择2个一组的呢,仿真里面有8个一组的如果你做实物,你的数码管不能直接接入的,建议用驱动,简单三极管就能驱动。如果你做时...
厨房定时器拆解- 一起装修网[回答]挺好的*。有大用处。单片机的厨房*器有电路程序论文。看你买的是哪种,有静音式的,也有滴答声的。一是简单,二是时间准确如果视力没什么问题,*上...
【普通计算器上的显示器是什么显示器就是那种8字型的那种我...[回答]1、普通计算器上的显示器称为笔段式液晶显示器.一般为定制液晶产品.可以做成任意形状笔段,比如早期的BP机,数字式电表,数字万用表,液晶显示器上有数...