单片机秒表 精确到0.1秒 c语言,基于51单片机精确到0.1秒可回看记录的秒表程序...

#include

unsigned char code leddata[]= {  0x3F,  0x06,  0x5B,  0x4F, //0 1 2 3

0x66,  0x6D,  0x7D,  0x07,  //4 5 6 7

0x7F,  0x6F,  0x77,  0x7C,  //8 9 A b

0x39,  0x5E,  0x79,  0x71,  //c d E F

0x76,  0x38,  0x37,  0x3E,  //H L n u

0x73,  0x5C,  0x40,  0x00,  //P o - 清屏

};

#define digitData P0          //数码管数据

#define startBtn    0       //按键值

#define resetBtn    1

#define counterBtn  2

sbit DX = P2^6;//段选

sbit WX = P2^7;//位选

sbit kaiShi = P3^4;//开始、暂停按键

sbit chongZhi = P3^5;//重置按键

sbit jiCi = P3^6;//计次、记录查看按键

unsigned int recode[8] = {0};//记录数据

unsigned char recodeNum = 0;//记录数据值位置

unsigned char showRe = 0; //查看哪项记录值

unsigned int times = 0; //当前计时时间

unsigned int saveTimes = 0;//暂停查看记录时保存时间数据

unsigned char counter = 0;//定时器次数,构成100ms

unsigned char shuanXi = 0,sXW = 1;//刷新数码管

unsigned char runState = 0;//0表示停止,1表示运行

unsigned char keyTemp[3]= {0}; //按键按下状态持续时间

//六位数码管显示 dat:显示内容下标 wei:哪一个数码管

void display(unsigned char dat,unsigned char wei)//wei 1-6

{

digitData = 0xff; //关掉显示 消除重影

WX = 1;

WX = 0;

//如果不先关闭显示,不论先段选还位选(位选前关闭都不行),而且必须先送段选,再送位选,

//先位选则当前位置会显示上次残留段选数据 导致重影

digitData = leddata[dat];//段选

DX = 1;

DX = 0;

digitData = ~(1<

WX = 1;

WX = 0;

}

//判断当前按键

unsigned char scanKey()

{

P3 = 0x70;//k1 k2 k3给高

if(kaiShi==0)//开始键按下

{

if(keyTemp[0] == 0) keyTemp[0]=1 ;//按键按下 开始记延时

}

else

{

keyTemp[0] = 0; //有抖动重新延时

}

if(chongZhi==0)

{

if(keyTemp[1] == 0) keyTemp[1]=1 ;

}

else

{

keyTemp[1] = 0;

}

if(jiCi==0)

{

if(keyTemp[2] == 0) keyTemp[2]=1 ;

}

else

{

keyTemp[2] = 0;

}

if(keyTemp[0]>5) return startBtn;  //5次 5*2ms 超过10ms 消抖

if(keyTemp[1]>5) return resetBtn;

if(keyTemp[2]>5) return counterBtn;

return 0xFF; //没有按键

}

void Timer0Init(void)        //2毫秒@11.0592MHz

{

//AUXR &= 0x7F;        //定时器时钟12T模式

TMOD &= 0xF0;        //设置定时器模式

TMOD |= 0x01;        //设置定时器模式

TL0 = 0xCF;        //设置定时初值

TH0 = 0xF8;        //设置定时初值

TF0 = 0;        //清除TF0标志

TR0 = 1;        //定时器0开始计时

ET0 = 1;         //运行定时器0中断

EA = 1;         //开全局中断

}

void main()

{

unsigned char keyValue = 0xFF,keyT = 0xFF;//按键值

unsigned char weiXian[6] = {0,22,0,0,22,0};

Timer0Init();

while(1)

{

if(shuanXi)//刷新sXW位置的数码管中

{

if(times>=6000) //十分钟

{

times = 0;

}

weiXian[0] = times/600;//分钟

weiXian[2] = times/10%60/10;

weiXian[3] = times/10%60%10;

weiXian[5] = times%10;

display(weiXian[sXW-1],sXW);

shuanXi = 0;

}

keyT = scanKey();//当前按键值

if(keyT!=keyValue)//当前按键值与上次按键值不同,则表示按键状态改变。需要做按键处理

{

keyValue = keyT;

//P1 = keyValue;

switch(keyValue)//按键处理

{

case startBtn://开始暂停按下

//if(runState) TR0 = 0; else TR0 = 1;

//runState ? (TR0 = 0) : (TR0 = 1);

runState = !runState;//改变状态

if(runState)//恢复时间

{

times = saveTimes;

}

else//保存时间

{

saveTimes = times;

}

break;

case resetBtn:  //重置

if(!runState)

{

times = 0;

saveTimes = 0;

recodeNum = 0;

P1 = 0xFF;

}

break;

case counterBtn:  //记录或查看记录

if(runState)//运行时,记录

{

if(recodeNum<8)

{

recode[recodeNum++] = times;

P1 = (0xFF<

}

}

else//暂停查看记录

{

P1 = (0xFF ^(1 << showRe));//点亮showRe位置的灯

times = recode[showRe++];

if(showRe >= recodeNum)

{

showRe = 0;//循环查看记录

}

}

break;

}

}

}

}

void T0_2ms() interrupt 1

{

//定时器重新赋初值 放在终端服务程序最开始有利于降低定时中断误差

TL0 = 0xCF;        //设置定时初值

TH0 = 0xF8;        //设置定时初值

if(++counter>=50 && runState)//运行状态下100ms 加0.1秒

{

times++;

counter = 0;

}

shuanXi = 1;//数码管周期刷新

if(++sXW>6) //六位循环刷新

{

sXW = 1;

}

if(keyTemp[0]) keyTemp[0]++;//按键持续

if(keyTemp[1]) keyTemp[1]++;//按键持续

if(keyTemp[2]) keyTemp[2]++;//按键持续

}

你可能感兴趣的:(单片机秒表,精确到0.1秒,c语言)