单片机实验代码——多功能时钟程序

来源:互联网 发布:java开发人员岗位职责 编辑:程序博客网 时间:2024/05/16 18:50

上次说的多功能时钟代码如下,闹钟功能暂时还没有搞定。另外,直接对P0赋值来改变S1、S2、S3、S4的值的想法竟然在多模式下是无效的,这使得我昨天整整一个白天都在纠结原因,结果还是没有结果。今天上课的时候有时间再研究下吧。

#include <reg51.h>#define uint unsigned int#define uchar unsigned charsbit S1 = P1^3;sbit S2 = P1^1;sbit S3 = P1^2;sbit S4 = P1^0;sbit beep = P2^7; //蜂鸣器sbit a = P0^0;sbit b = P0^1;sbit c = P0^2;sbit d = P0^3;sbit e = P0^4;sbit f = P0^5;sbit g = P0^6;sbit p = P0^7;sbit key1 = P1^4; //开始/暂停sbit key2 = P1^5; //功能键sbit key3 = P3^6;sbit key4 = P3^7;bit flag_add, flag_ring; //定义两个位变量uchar icount, th, tl, mode;uchar clock[5], stopwatch[5], tmp[5], alarm[2] = {0, 0};uchar *point = clock;uchar clockPosition = 3, alarmPosition = 0;  //时钟设置模式下, 光标所在的位置; 默认在0uchar clockTmp = 0, alarmTmp = 0; //用于时钟模式下临时计数bit changeDisplay = 0, clockTmpBit = 0, alarmTmpBit = 0; //用于时钟模式下临时标志位uchar code N[10] = {0xc0, 0xf9 ,0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; //0-9数码管的编码(共阳极)uchar code Z[10] = {0x40, 0x79 ,0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10}; //0-9数码管的编码(共阳极), 带小数点//延时函数, 针对12MHz时钟void delayms(uint xms){uint i,j;for(i = xms; i > 0; i--)for(j = 110; j > 0; j--);}void alarm_ring() //蜂鸣器报警声音{beep = 0;   delayms(100);   beep = 1;   }uchar alarmtime(){    uchar flag_alarm;    for(icount = 0; icount < 2; icount++)    {        if(alarm[icount] == clock[icount+3])            flag_alarm = 1;        else        {            flag_alarm = 0;            break;        }}    return flag_alarm;}void setZero(uchar *p){for(icount = 0; icount < 5; icount++)p[icount] = 0;}void init(){TMOD = 0x11; //定时器1, 0 都工作方式1th = 0xd8; //(65536-10000)/256  //定时10mstl = 0xf0; //(65536-10000)%256TH0 = TH1 = th;TL0 = TL1 = tl;EA = 1; //打开总中断ET0 = ET1 = 1; //允许定时器1, 0 中断请求TR0 = 1; //时钟-定时器0TR1 = 0; //秒表-定时器1mode = 1;//初始化时钟和秒表的时分秒计数值setZero(clock);setZero(stopwatch);setZero(tmp);}void displayDatas(uchar thous, uchar hund, uchar ten, uchar pbit){P0 = 0xff;S1 = 0;    S2 = S3 = S4 = 1;    //P1 = 0x07;P0 = thous;delayms(5); S2 = 0;    S1 = S3 = S4 = 1;    //P1 = 0x0d;P0 = hund;delayms(5);S3 = 0;    S2 = S1 = S4 = 1;    //P1 = 0x0b;P0 = ten;delayms(5);S4 = 0;    S2 = S3 = S1 = 1;    //P1 = 0x0e;P0 = pbit;delayms(5);}void display(){switch(mode){        case 1:            if(!changeDisplay)                displayDatas(N[point[4]/10], Z[point[4]%10], N[point[3]/10], Z[point[3]%10]);            else                displayDatas(N[point[2]/10], Z[point[2]%10], N[point[1]], N[point[0]]);            break;case 2://时钟设置模式下, 选中位置闪烁clockTmp++;if(clockTmp == 20){clockTmp = 0;clockTmpBit = ~clockTmpBit;}if(clockTmpBit)            {                switch(clockPosition)                {                    case 3:                        displayDatas(N[point[4]/10], Z[point[4]%10], 0xff, 0xff);break;                    case 4:                        displayDatas(0xff, 0xff, N[point[3]/10], Z[point[3]%10]);break;                }}            else{                displayDatas(N[point[4]/10], Z[point[4]%10], N[point[3]/10], Z[point[3]%10]);}            break;case 3:            if(point[3]%10 == 0)            {                displayDatas(N[point[2]/10], Z[point[2]%10], N[point[1]], N[point[0]]);            }else if(point[3]/10 == 0){displayDatas(Z[point[3]%10], N[point[2]/10], Z[point[2]%10], N[point[1]]);}else if(point[3]/10 < 6){displayDatas(N[point[3]/10], Z[point[3]%10], N[point[2]/10], Z[point[2]%10]);}else{displayDatas(N[5], Z[9], N[5], Z[9]);}break;case 4:            alarmTmp++;if(alarmTmp == 20){alarmTmp = 0;alarmTmpBit = ~alarmTmpBit;}if(alarmTmpBit)            {                switch(alarmPosition)                {                    case 0:                        displayDatas(N[point[1]/10], Z[point[1]%10], 0xff, 0xff);break;                    case 1:                        displayDatas(0xff, 0xff, N[point[0]/10], Z[point[0]%10]);break;                }}            else{                displayDatas(N[point[1]/10], Z[point[1]%10], N[point[0]/10], Z[point[0]%10]);}break;}}//检测功能模式键是否被按下void checkModeKey(){if(!key4){delayms(10);if(!key4){            while(!key4);            mode++;switch(mode){                case 1:                    point = clock;TR0 = 1;                    break;case 2: //定时器0是不会关闭的, 即使在设置模式下for(icount = 0; icount < 5; icount++){tmp[icount] = clock[icount]; //将设置之前的值暂存到临时数组}point = tmp;                    clockPosition = 3;break;case 3: //秒表模式                    //TR0 = 0;point = stopwatch;break;case 4: //闹钟设置模式point = alarm;                    alarmPosition = 0;break;                case 5:                    mode = 1;                    point = clock;TR0 = 1;                    break;}}}}//选中位数值增1, 用于时钟模式的设置状态下void addValue(uchar Position){flag_add = 1;point[Position]++;switch(Position){case 2:case 3:if(point[Position] >= 60)point[Position] = 0;break;case 4:if(point[Position] >= 24)point[Position] = 0;break;default:if(point[Position] >= 10)point[Position] = 0;}}//检测是否有键按下, 并执行相应功能void checkKey(){checkModeKey();if(flag_ring && alarmtime()) {alarm_ring();if(!key1 || !key2 || !key3 || !key4)//这里用来取消闹钟报警,任一键取消报警{delayms(10);if(!key1 || !key2 || !key3 || !key4){while(!(key1 && key2 && key3 && key4));flag_ring = 0; //清除报警标志}}}switch(mode){        case 1:            if(key1 == 0)            {                delayms(10);                if(key1 == 0)                {                    changeDisplay = ~changeDisplay;                    while(!key1);                }            }            break;case 2:if(!key1) //左移光标位            {                delayms(10);                if(!key1)                {                    while(!key1);                    clockPosition++;                    if(clockPosition > 4)                    {                        clockPosition = 3;                    }                }            }            else if(!key2) //选中位增1            {                delayms(10);                if(!key2)                {                    while(!key2);                    addValue(clockPosition);                                    }            }            else if(!key3) //选中确定更改            {                uchar timediff;                delayms(10);                if(!key3)                {                    while(!key3);                    timediff = clock[3]*60+clock[2]-point[3]*60-point[2];                    if(flag_add || timediff <= 30) //如果addValue()执行, 更新clock[], 否则超过30秒未操作返回时钟模式                    {                        for(icount = 0; icount < 5; icount++)                        {                            clock[icount] = point[icount]; //将设置的值存到clock[]                        }                    }                    point = clock;                    mode = 1; //将模式变成时钟模式                    flag_add = 0;                                    }            }break;case 3:if(!key1){delayms(10); //延时大约10ms, 去抖动if(!key1) //开始/暂停键按下{                    while(!key1);TR1 = ~TR1;}}else if(!key2){delayms(10); //延时大约10ms, 去抖动if(!key2) //清零键按下{                    while(!key2);TR1 = 0;TH1 = th;TL1 = tl;for(icount = 0; icount < 5; icount++){stopwatch[icount] = 0;}}}break;        case 4:            if(!key1) //左移光标位            {                delayms(10);                if(!key1)                {                    while(!key1);                    clockPosition++;                    if(clockPosition > 1)                    {                        clockPosition = 0;                    }                }            }            else if(!key2) //选中位增1            {                delayms(10);                if(!key2)                {                    while(!key2);                    addValue(alarmPosition);                                    }            }            else if(!key3) //选中确定更改            {                delayms(10);                if(!key3)                {                    while(!key3);                    for(icount = 0; icount < 2; icount++)                    {                        alarm[icount] = point[icount]; //将设置的值存到clock[]                    }                    point = clock;                    mode = 1; //将模式变成时钟模式                    flag_add = 0;                    flag_ring = ~flag_ring;                }            }break;}}void timeCounter(uchar *timer){timer[0]++; //0.01秒if(timer[0] >= 10){timer[0] = 0;timer[1]++; //0.1秒if(timer[1] >= 10){timer[1] = 0;timer[2]++; //秒if(timer[2] >= 60){timer[2] = 0;timer[3]++; //60秒if(timer[3] >= 60){timer[3] = 0;timer[4]++; //3600秒if(timer[4] >= 24){timer[4] = 0;}}}}}}main(){init();while(1){checkKey(); //检测是否有键按下display(); //显示计时值}}//定时器0中断响应函数, 用于时钟计时void T0_time() interrupt 1{TH0 = th; //重置计数值TL0 = tl;timeCounter(clock);}//定时器1中断响应函数, 用于秒表计时void T1_time() interrupt 3{TH1 = th; //重置计数值TL1 = tl;timeCounter(stopwatch);}

代码还是不够精简,有时间再改进吧。

原创粉丝点击