atmega8 定时
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一.设计要求
(1)用Proteus 完成电路图的绘制
(2)4位数码管点亮显示功能实现
(3)从0分00秒0毫秒正常计时**分**秒**毫秒功能实现
(4)固定时间正常计时功能实现
(5)固定时间倒计时功能实现
(6)自由设定时间后正常计时功能实现
(7)自由设定时间后倒计时功能实现
二. 硬件设计
单片机:atmega8 .PB输出口,控制数码管显示的数字;PC输出口,控制数码管显示位置;PD输入口,控制4个按钮,分别为时间分+1,时间秒+1,开始计时,停止计时。
数码管:4位8段共阴数码管,公共极为阴极,对应脚输入+5V电压后点亮。
电阻:100Ω电阻4个。
按钮:点动按钮4个。
不按下按钮时,单片机PD4个输入口为低电频,按下按钮时PD4个输入口为高电频。
三.软件设计
基本设计思路:
首先利用单片机PB,PC口控制4位8段数码管动态显示时间。
PD口控制2个按钮,分别用来控制时间秒和时间分+1;再设计1个定时器,正数计时,当计时0.1秒后,显示+1。
逢10,秒位进1后归0;秒位逢60,分进1后归0;分位逢10后全部清零,重新开始计时。
倒数计时只需要当0.1秒后,显示-1。
逢0,秒位-1后归0;秒位逢0,分-1后归0;所有位都为0后停止计时。
程序设计:
#include <mega8.h>
unsigned char dispCode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //定义8位数字显示
unsigned char dispBit[]={0xf7,0xfb,0xfd,0xfe};//显示位置控制
unsigned char dispBuf[4]={0,0,0,0};
unsigned char second=50;
unsigned char t,x,y,z;
unsigned char minute=9;
unsigned char dispbitcnt=0;
unsigned int tcnt;
xianshi(void)
{
for(c=0;c<100;c++)
{dispBuf[0]=t;
dispBuf[1]=second%10;
dispBuf[2]=second/10;
dispBuf[3]=minute%10;
PORTC=0xff;
if(dispbitcnt==4)
{
dispbitcnt=0;
}
if(dispbitcnt==1 || dispbitcnt==3)
{
PORTB=dispCode[dispBuf[dispbitcnt]]|0x80;
}
else
{
PORTB=dispCode[dispBuf[dispbitcnt]];}
PORTC=dispBit[dispbitcnt];
dispbitcnt++;
for(a=0;a<200;a++); }}
interrupt [TIM0_OVF] void timer0_ovf_isr(void) //正数计时函数
{ tcnt++;
if(tcnt==50) //计数50次后为0.1秒
{ tcnt=0;
t++; //显示增加0.1秒
if(t==10) //逢10进1
{t=0;
second++;}
if(second==60) //逢60进1
{ second=0;minute++;}
if(minute==60)minute=0;
}
TCNT0=0x05;
}
void main(void) //主函数
{int c,a; //输入口、输出口、定时设置。
PORTB=0x00; DDRB=0xFF;PORTC=0x00;DDRC=0x0F;PORTD=0x00;DDRD=0x00; TCCR0=0x00;TCNT0=0x05;TCCR1A=0x00;TCCR1B=0x00;TCNT1H=0x00;TCNT1L=0x00; ICR1H=0x00;ICR1L=0x00;OCR1AH=0x00;OCR1AL=0x00;OCR1BH=0x00;OCR1BL=0x00; ASSR=0x00;TCCR2=0x00;TCNT2=0x00;OCR2=0x00;MCUCR=0x00;TIMSK=0x01; ACSR=0x80;SFIOR=0x00;#asm("sei")
while (1) //显示死循环
{
if(PIND.0==1) //按钮1控制秒+1。
{minute++;xianshi(); }
if(PIND.1==1) //按钮2控制分+1.
{second++;xianshi();}
if(PIND.2==1) //按钮3控制开始计时。
{ TCCR0=0X02; xianshi();}
if(PIND.3==1) //按钮4控制停止计时。
{TCCR0=0X00;xianshi();}
}
使用倒数计时的函数时,只需要把正数计时的函数替换为倒数计时的函数即可。
interrupt [TIM0_OVF] void timer0_ovf_isr(void) //倒数计时函数
{ TCNT0=0x05;
tcnt++;
if(tcnt==50)
{ tcnt=0;
if(t==0){t=9;second--;}
if(second==0)
{if(minute==0) //当全部显示为0时,停止计时。
{t=0, TCCR0=0X00;}
else { minute--; second=59; }}
else t--;
}}。