找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5728|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

數(shù)字電子鐘畢業(yè)設(shè)計源程序(加萬年歷和鬧鐘功能)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:80332 發(fā)表于 2015-5-18 10:15 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
/*
*  Desc:DS12C887 6位數(shù)碼管顯示
*  
*/
#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     //控制閃爍速度,為偶數(shù)

#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; //修改模式下閃爍計數(shù)
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;        //顯示小數(shù)點
        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;
}
/*計算當(dāng)月的天數(shù)*/
unsigned char getDay(void)
{
    unsigned char tYear,tMonth;
    tYear = BCD_DEC(DS12887_Read(DS_YER));  //當(dāng)前年
    tMonth = BCD_DEC(DS12887_Read(DS_MON));//當(dāng)前月
    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)      //根據(jù)顯示模式確定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();
    }
}

評分

參與人數(shù) 2黑幣 +53 收起 理由
T阿里巴巴 + 3 贊一個!
admin + 50 共享資料的積分獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩

相關(guān)帖子

回復(fù)

使用道具 舉報

沙發(fā)
ID:82310 發(fā)表于 2015-6-7 16:54 | 只看該作者
用1602顯示,該怎樣寫鬧鐘的程序哦
回復(fù)

使用道具 舉報

板凳
ID:82310 發(fā)表于 2015-6-7 16:56 | 只看該作者
我做的是一個電子表,想加一個鬧鐘,鬧鐘模塊該怎么寫哦
回復(fù)

使用道具 舉報

地板
ID:83082 發(fā)表于 2015-6-15 21:20 | 只看該作者
有原理圖沒
回復(fù)

使用道具 舉報

5#
ID:94340 發(fā)表于 2015-11-1 20:06 | 只看該作者
為什么沒有原理圖
回復(fù)

使用道具 舉報

6#
ID:191450 發(fā)表于 2017-5-1 16:29 | 只看該作者

 樓主能分享一下原理圖嗎?
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表