找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5094|回复: 5
收起左侧

数字电子钟毕业设计源程序(加万年历和闹钟功能)

[复制链接]
ID:80332 发表于 2015-5-18 10:15 | 显示全部楼层 |阅读模式
/*
*  Desc:DS12C887 6位数码管显示
*  
*/
#include <AT89X51.h>

#define SEG_DAT P0
#define SEG_BIT P2
#define DS_DAT  P0
#define DS_SEC  0x00
#define DS_MIN  0x02
#define DS_HOR  0x04
#define DS_WEK  0x06
#define DS_DAY  0x07
#define DS_MON  0x08
#define DS_YER  0x09
#define DS_R_A  0x0A
#define DS_R_B  0x0B
#define DS_R_C  0x0C
#define DS_R_D  0x0D
#define DS_Y_S  0x0E    //年千百位

#define CNT_M   30     //控制闪烁速度,为偶数

#define BCD_DEC(X)  (((X & 0xF0) >> 4) * 10 + (X & 0x0F))
#define DEC_BCD(X)  (((X / 10) << 4) | (X % 10))

sbit DS_DS = P3^0;
sbit DS_RW = P3^1;
sbit DS_AS = P3^2;
sbit DS_CS = P3^3;

sbit KEY1  = P1^0;
sbit KEY2  = P1^1;
sbit KEY3  = P1^2;
sbit KEY4  = P1^3;

unsigned char dispMode = 0; //显示模式
unsigned char modify   = 0; //修改模式
unsigned char count    = 0; //修改模式下闪烁计数
unsigned char DIS[6];

unsigned char code C_DAT[]={        
    0xC0,/*0*/
    0xF9,/*1*/
    0xA4,/*2*/
    0xB0,/*3*/
    0x99,/*4*/
    0x92,/*5*/
    0x82,/*6*/
    0xF8,/*7*/
    0x80,/*8*/
    0x90,/*9*/
    0xBF,/*-*/
};
unsigned char code C_BIT[]={0xDF,0xEF,0xF7,0xFB,0xFD,0xFE};

void Delay(unsigned int t)
{
    unsigned int a,b;
    for (a=0; a<t; a++)
        for (b=0; b<123; b++)
            ;
}

void DS12887_Write(unsigned char addres,unsigned char dat)
{
    DS_AS = 1;
    DS_DS = 1;
    DS_RW = 1;
    DS_CS = 0;
    DS_DAT = addres;
    DS_AS = 0;  //add will be write when AS full down
    DS_RW = 0;
    DS_DAT = dat;
    DS_RW = 1;
    DS_AS = 1;
    DS_CS = 1;
}

unsigned char DS12887_Read(unsigned char addres)
{
    unsigned char d;
    DS_AS = 1;
    DS_DS = 1;
    DS_RW = 1;
    DS_CS = 0;
    DS_DAT = addres;
    DS_AS = 0;
    DS_DS = 0;
    DS_DAT = 0xFF;
    d = DS_DAT;
    DS_DS = 1;
    DS_AS = 1;
    DS_CS = 1;
    return d;
}

void DS12887_Init(void)
{
    if (DS12887_Read(DS_Y_S) == 0)
    {
        DS12887_Write(DS_Y_S, 0x20);
        DS12887_Write(DS_HOR, 0x12);
        DS12887_Write(DS_R_A, 0x20);
        DS12887_Write(DS_R_B, 0x02);  //BCD
    }
}

void Display(void)
{
    unsigned char i;

    if (dispMode == 0)                          //显示模式0,时分秒
    {
        i = DS12887_Read(DS_HOR) & 0x7F;
        DIS[0] = C_DAT[i >> 4];
        DIS[1] = C_DAT[i & 0x0F] & 0x7F;
        i = DS12887_Read(DS_MIN);
        DIS[2] = C_DAT[i >> 4];
        DIS[3] = C_DAT[i & 0x0F] & 0x7F;
        i = DS12887_Read(DS_SEC);
        DIS[4] = C_DAT[i >> 4];
        DIS[5] = C_DAT[i & 0x0F] & 0x7F;
        if (modify != 0 && count > CNT_M)   //修改模式123下闪烁
        {
            DIS[2 * (modify - 1)] = 0xFF;
            DIS[2 * (modify - 1) + 1] = 0xFF;
        }
    } else if (dispMode == 1)                   //显示模式1,年
    {
        DIS[0] = 0xFF;
        i = DS12887_Read(DS_Y_S);               //年高两位,在RAM里0x0E
        DIS[1] = C_DAT[i >> 4];
        DIS[2] = C_DAT[i & 0x0F];
        i = DS12887_Read(DS_YER);               //年低两位
        DIS[3] = C_DAT[i >> 4];
        DIS[4] = C_DAT[i & 0x0F];
        DIS[5] = 0xFF;
        if (modify != 0 && count > CNT_M)   //修改模式45下闪烁
        {
            DIS[2 * (modify - 4) + 1] = 0xFF;
            DIS[2 * (modify - 4) + 2] = 0xFF;
        }
    } else if (dispMode == 2)                   //显示模式2,月日 星期
    {
        i = DS12887_Read(DS_MON);               //月
        if (i < 10)
            DIS[0] = 0xFF;
        else
            DIS[0] = C_DAT[i >> 4];
        DIS[1] = C_DAT[i & 0x0F] & 0x7F;        //显示小数点
        i = DS12887_Read(DS_DAY);               //日
        DIS[2] = C_DAT[i >> 4];
        DIS[3] = C_DAT[i & 0x0F];
        i = DS12887_Read(DS_WEK);               //星期
        DIS[4] = C_DAT[10];                     //用'-'隔开
        DIS[5] = C_DAT[(i - 1) & 0x0F];         //1~7,第一天是星期天
        if (modify != 0 && count > CNT_M)   //修改模式789下闪烁
        {
            if (modify != 9)                    //星期修改时,‘-’不闪烁
                DIS[2 * (modify - 7)] = 0xFF;
            DIS[2 * (modify - 7) + 1] = 0xFF;
        }
    }
    for (i=0; i<6; i++)
    {
        SEG_DAT = DIS[ i];
        SEG_BIT = C_BIT[ i];
        Delay(1);
        SEG_BIT = 0xFF;
    }
        count++;                        //用于修改模式下闪烁
        if (count > 2 * CNT_M)
                count = 0;
}
/*计算当月的天数*/
unsigned char getDay(void)
{
    unsigned char tYear,tMonth;
    tYear = BCD_DEC(DS12887_Read(DS_YER));  //当前年
    tMonth = BCD_DEC(DS12887_Read(DS_MON));//当前月
    switch (tMonth)
    {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:return 31;  //1、3、5、7、8、10、12 月均为31天
    case 4:
    case 6:
    case 9:
    case 11:return 30;  //4、6、9、11 月均为30天
    case 2:            
        if (tYear%4==0) //2月闰年为29天
            return 29;
        else
            return 28;  //平年为28天
    default:    return 0;
    }
}
void Key(void)  
{
    unsigned char i;
    P1 = 0xFF;
    if (KEY1 == 0)                           //显示模式更改
    {
        Delay(10);
        if (KEY1 == 0)
        {
                        if (modify)                                                        //修改模式下用于退出修改
                                modify = 0;
                        else {
                                DS12887_Write(DS_R_B, 0x62);
                                dispMode++;
                                if (dispMode > 2)
                                        dispMode = 0;
                        }
        }
        while (KEY1 == 0)
            Display();
    }
    if (KEY2 == 0)                                      //修改模式
    {
        Delay(10);
        if (KEY2 == 0)
        {
            if (modify == 0)            //时分秒123,年45,月日星期789
            {
                modify = 3 * dispMode + 1;
                DS12887_Write(DS_R_B, 0xE2);
            } else {
                modify++;
                switch (dispMode)      //根据显示模式确定modify初值
                {
                case 0:
                case 2:
                    if (modify > (3 * dispMode + 3))   
//时分秒,日星期模式下每个是3位
                    {
                        modify = 0;
                        DS12887_Write(DS_R_B, 0x62);
                    }
                    break;
                case 1:
                    if (modify > (3 * dispMode + 2))    //年模式下是2位
                    {
                        modify = 0;
                        DS12887_Write(DS_R_B, 0x62);
                    }
                    break;
                }
            }
        }
        while (KEY2 == 0)
            Display();
    }
    if (KEY3 == 0)                                      //+
    {
        Delay(10);
        if (KEY3 == 0)
        {
            switch (modify)
            {
            case 1:                                     //时
                i = BCD_DEC(DS12887_Read(DS_HOR));
                i++;
                if (i > 23)
                    i = 0;
                DS12887_Write(DS_HOR, DEC_BCD(i));
                break;
            case 2:                                     //分
                i = BCD_DEC(DS12887_Read(DS_MIN));
                i++;
                if (i > 59)
                    i = 0;
                DS12887_Write(DS_MIN, DEC_BCD(i));
                break;
            case 3:                                     //秒
                i = BCD_DEC(DS12887_Read(DS_SEC));
                i++;
                if (i > 59)
                    i = 0;
                DS12887_Write(DS_SEC, DEC_BCD(i));
                break;
            case 4:                                     //年高两位
                i = BCD_DEC(DS12887_Read(DS_Y_S));
                i++;  
                if (i > 21)
                    i = 19;
                DS12887_Write(DS_Y_S, DEC_BCD(i));
                break;
            case 5:                                     //年低两位
                i = BCD_DEC(DS12887_Read(DS_YER));
                i++;  
                if (i > 99)
                    i = 0;
                DS12887_Write(DS_YER, DEC_BCD(i));
                break;
            case 7:                                     //月
                i = BCD_DEC(DS12887_Read(DS_MON));
                i++;  
                if (i > 12)
                    i = 1;
                DS12887_Write(DS_MON, DEC_BCD(i));
                break;
            case 8:                                     //日
                i = BCD_DEC(DS12887_Read(DS_DAY));
                i++;  
                if (i > getDay())
                    i = 1;
                DS12887_Write(DS_DAY, DEC_BCD(i));
                break;
            case 9:                                     //星期
                i = BCD_DEC(DS12887_Read(DS_WEK));
                i++;  
                if (i > 7)
                    i = 1;
                DS12887_Write(DS_WEK, DEC_BCD(i));
                break;
            }
        }
        while (KEY3 == 0)
            Display();
    }
    if (KEY4 == 0)
    {
        Delay(10);
        if (KEY4 == 0)
        {
            switch (modify)
            {
            case 1:                                     //时
                i = BCD_DEC(DS12887_Read(DS_HOR));
                if (i == 0)
                    i = 24;
                i--;
                DS12887_Write(DS_HOR, DEC_BCD(i));
                break;
            case 2:                                     //分
                i = BCD_DEC(DS12887_Read(DS_MIN));
                if (i == 0)
                    i = 60;
                i--;
                DS12887_Write(DS_MIN, DEC_BCD(i));
                break;
            case 3:                                     //秒
                i = BCD_DEC(DS12887_Read(DS_SEC));
                if (i == 0)
                    i = 60;
                i--;
                DS12887_Write(DS_SEC, DEC_BCD(i));
                break;
            case 4:                                     //年高两位
                i = BCD_DEC(DS12887_Read(DS_Y_S));
                if (i == 19)
                    i = 22;
                i--;
                DS12887_Write(DS_Y_S, DEC_BCD(i));
                break;
            case 5:                                     //年低两位
                i = BCD_DEC(DS12887_Read(DS_YER));
                if (i == 0)
                    i = 99;
                else
                    i--;
                DS12887_Write(DS_YER, DEC_BCD(i));
                break;
            case 7:                                     //月
                i = BCD_DEC(DS12887_Read(DS_MON));
                if (i == 1)
                    i = 12;
                else
                    i--;
                DS12887_Write(DS_MON, DEC_BCD(i));
                break;
            case 8:                                     //日
                i = BCD_DEC(DS12887_Read(DS_DAY));
                if (i == 1)
                    i = getDay();
                else
                    i--;
                DS12887_Write(DS_DAY, DEC_BCD(i));
                break;
            case 9:                                     //星期
                i = BCD_DEC(DS12887_Read(DS_WEK));
                if (i == 1)
                    i = 7;
                else
                    i--;
                DS12887_Write(DS_WEK, DEC_BCD(i));
                break;
            }
        }
        while (KEY4 == 0)
            Display();
    }
}
void main (void)
{
    unsigned char i;
    DS12887_Init();
    while (1)
    {
        Key();
        Display();
    }
}

评分

参与人数 2黑币 +53 收起 理由
T阿里巴巴 + 3 赞一个!
admin + 50 共享资料的积分奖励!

查看全部评分

回复

使用道具 举报

ID:82310 发表于 2015-6-7 16:54 | 显示全部楼层
用1602显示,该怎样写闹钟的程序哦
回复

使用道具 举报

ID:82310 发表于 2015-6-7 16:56 | 显示全部楼层
我做的是一个电子表,想加一个闹钟,闹钟模块该怎么写哦
回复

使用道具 举报

ID:83082 发表于 2015-6-15 21:20 | 显示全部楼层
有原理图没
回复

使用道具 举报

ID:94340 发表于 2015-11-1 20:06 | 显示全部楼层
为什么没有原理图
回复

使用道具 举报

ID:191450 发表于 2017-5-1 16:29 | 显示全部楼层

 楼主能分享一下原理图吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表