基于51单片机的数字秒表实现

//基于51单片机的八位数字秒表
//开发语言:C51
//所选芯片:AT89S51
//开发者:jnu.bluecoffee
//开发日期:2009年6月18日
//小弟刚刚入道,完全原创。如有转载,请注明出处。

#include 
<reg51.h>
#include 
<intrins.h>

#define DIG_NONE 0xff;
#define DIG_1 0x7f
#define DIG_2 0xbf
#define DIG_3 0xdf
#define DIG_4 0xef
#define DIG_5 0xf7
#define DIG_6 0xfb
#define DIG_7 0xfd
#define DIG_8 0xfe
#define LINE  0xf7//根据共阴共阳以及接法要调整

typedef unsigned 
char Byte;
typedef bit 
bool;

sbit START 
= P3^0;
sbit RESET 
= P3^1;

Byte data dis_digit;
Byte data min;
Byte data sec;
Byte data msec;
bool data isStarted;
Byte data dis_digit;
Byte data dis_index;
Byte data dis_buff[
8];
Byte data dis_num[
8];

//根据共阴共阳以及数码管接法这里要的表要调整
Byte code number[11]=0x280x7E0xA20x620x740x610x210x7A0x200x60,0xff};//0,1,2,3,4,5,6,7,8,9,关显示,数码管码表
Byte dis_buff[8];        // 显示缓冲区
Byte dis_num[8];         // 秒计数值, BCD码
Byte dis_index;
    
bit    Scan_Key();
void Proc_Key();
void Delayms(Byte ms);
void Update_buff();
void Msec_Increment();
void Reset(void);
bool Get_Key(bit key);//有效为1
void MCU_Init(void);
void Timer0_Overflow();
void Timer1_Overflow();


//sbit    K1 = P3^2;

void Msec_Increment()//中断里面的设置
{
    msec 
+= 1;
    
if (msec == 100)
    {    
        msec 
= 0;
        sec 
+= 1
    }
    
if (sec == 60)
    {
        sec 
= 0;
        min 
+= 1;
    }
    
if (min == 60)
        min 
= 0;
}


void MCU_Init()
{
    P1 
= 0xff;
    P2 
= 0xff;
    
    TMOD 
= 0x12;
    TH1 
= 0xd8;
    TL1 
= 0xf0;
    TH0 
= 0x9c;
    TL0 
= 0x00;
    
////定时器1选用方式1工作,扫描周期0.01s=10ms,定时器0选用工作方式3工作,自动装入,扫描周期0.1ms=100μs
    
    Reset();
    
    min 
= 0;
    sec 
= 0;
    msec 
= 0;
                               
    dis_digit 
= 0x7f;        // 初始显示P20口数码管
    dis_index = 0;
    
    IE 
= 0x8a;                // 使能timer0, timer1中断
    
    TR0 
= 1;
    TR1 
= 0;
    
    isStarted 
= 0;
}

void Reset()
{
    min 
= 0;
    sec 
= 0;
    msec 
= 0;  
    
    Update_buff();
}

void Update_buff()
{
    dis_num[
0= min / 10;
    dis_num[
1= min % 10;
    dis_num[
3= sec / 10;
    dis_num[
4= sec % 10;
    dis_num[
6= msec / 10;
    dis_num[
7= msec % 10;
    
    
//这里根据数码管的顺序进行调整
    dis_buff[0= number[dis_num[7]];
    dis_buff[
1= number[dis_num[6]];
    dis_buff[
2= LINE;
    dis_buff[
3= number[dis_num[4]];
    dis_buff[
4= number[dis_num[3]];
    dis_buff[
5= LINE;
    dis_buff[
6= number[dis_num[1]];
    dis_buff[
7= number[dis_num[0]];
}

bool Get_Key(bit key)//有效为1,这里按下为低电平
{
    
if (key == 0)
        
return 1;
    
else
        
return 0;
}

void timer0() interrupt 1
{
    P2 
= 0xff;                            // 先关闭所有数码管
    P1 = dis_buff[dis_index];            // 显示代码传送到P0口
    P2 = dis_digit;                        // 

    dis_digit 
= _cror_(dis_digit,1);    // 位选通值右移(P20<-P27), 下次中断时选通下一位数码管
    
//_cror_()为字符循环右移函数 
    dis_index++;                        // 
                    
    dis_index 
&= 0x07;            // 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描
}

void timer1() interrupt 3
{    
    TH1 
= 0xd8;
    TL1 
= 0xf0;
    Msec_Increment();
    Update_buff();
}


void delayms(unsigned char ms)    
// 延时子程序
{                        
    unsigned 
char i;
    
while(ms--)
    {
        
for(i = 0; i < 120; i++);
    }
}

void main(void)
{
    
bool startkey, resetkey;
    MCU_Init();
    
while(1)
    {
        startkey 
= Get_Key(START);
        resetkey 
= Get_Key(RESET);
        
        
if (startkey == 1)
        {
            Delayms(
50);
            startkey 
= Get_Key(START);
            
if (startkey == 1)
            {
                isStarted 
= !isStarted;
                TR1 
= !TR1;    
            }
        }
        
        
if (resetkey == 1 && isStarted == 0)
        {
            Delayms(
20);
            resetkey 
= Get_Key(RESET);
            
if (resetkey == 1 && isStarted == 0)
            {
                Reset();
            }    
        }
    }
}

posted on 2009-06-20 12:16  bluecoffee  阅读(1464)  评论(0编辑  收藏  举报