欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2702|回復(fù): 1
收起左側(cè)

AT89C51單片機(jī)定時(shí)器應(yīng)用設(shè)計(jì) Proteus仿真程序視頻

[復(fù)制鏈接]
ID:623141 發(fā)表于 2020-6-23 16:47 | 顯示全部樓層 |閱讀模式
一、設(shè)計(jì)目的
1、學(xué)習(xí)并掌握定時(shí)器/計(jì)數(shù)器的工作原理;
2、學(xué)習(xí)并掌握定時(shí)器/計(jì)數(shù)器控制程序設(shè)計(jì)方法;
3、學(xué)習(xí)并掌握矩陣鍵盤工作原理與程序設(shè)計(jì)方法;
4、學(xué)習(xí)并掌握顯示程序設(shè)計(jì);
二、實(shí)驗(yàn)設(shè)備
1、計(jì)算機(jī);
2、單片機(jī)開發(fā)板;
3、Keil C51編程軟件;
4、Proteus仿真軟件;
三、設(shè)計(jì)內(nèi)容
1、功能
必須使用定時(shí)器完成以下功能。
功能1:4位數(shù)碼管顯示“分鐘.秒”
功能2:K1設(shè)置鍵、K2加1鍵、K2減1鍵
(1)正常情況:顯示“分鐘.秒”
(2)按下K1:第一次按下調(diào)整分鐘狀態(tài)、第二次按下調(diào)整秒狀態(tài)、第三次按下正常顯示狀態(tài)
(3)按下K2:分鐘或秒加1
(4)按下K3:分鐘或秒減1
選做功能:鬧鐘功能(請先完成功能1和功能2并提交后,選做)
(1)當(dāng)?shù)竭_(dá)設(shè)定好的時(shí)間,蜂鳴器奏樂、LED閃爍報(bào)警;
(2)按下K4:停止報(bào)警,正常顯示;
(3)鬧鐘時(shí)間可調(diào);
(4)按下K1:第一次按下調(diào)整分鐘狀態(tài)、第二次按下調(diào)整秒狀態(tài)、第三次按下調(diào)整鬧鐘分鐘狀態(tài)、第四次按下調(diào)整鬧鐘秒狀態(tài)、第五次按下正常顯示狀態(tài)
(5)按下K2:按一下分鐘或秒加1
(6)按下K3:按一下分鐘或秒減1
2、硬件電路原理圖
3、設(shè)計(jì)程序(5號、宋體、單倍行距、分兩欄,要求程序設(shè)計(jì)規(guī)范化,添加必要的說明和注釋)
3.1必做題程序

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png

單片機(jī)源程序如下:
/*****************************************
* 實(shí) 驗(yàn) 名 :4*4矩陣按鍵實(shí)驗(yàn)
* 實(shí)驗(yàn)說明 :采用循環(huán)方式實(shí)現(xiàn):數(shù)碼管顯示電子表:分鐘、秒,用3個按鍵實(shí)現(xiàn)調(diào)整
*            按鍵1:設(shè)置、確定
*            按鍵2:加1
*            按鍵3:減1
*****************************************/
#include <reg52.h>
#include <intrins.h>
#define FOSC 11059200L //晶振設(shè)置,默認(rèn)使用11.0592M Hz
//#define FOSC 12000000L //晶振設(shè)置,使用12M Hz
//#define FOSC 24000000L //晶振設(shè)置,使用24M Hz
#define TIME0_MS 50 //設(shè)定定時(shí)時(shí)間50ms
//IO接口定義
#define LED_PORT P0     //數(shù)碼管的段碼顯示控制接口
#define KEY_PORT P1     //鍵盤控制接口
sbit wela_1 = P2^4;     //數(shù)碼管個位顯示控制口
sbit wela_2 = P2^5;     //數(shù)碼管十位顯示控制口
sbit wela_3 = P2^6;     //數(shù)碼管百位顯示控制口
sbit wela_4 = P2^7;     //數(shù)碼管千位顯示控制口
//全局變量定義
unsigned char count;           //定時(shí)計(jì)數(shù)次數(shù)
unsigned char key_value;//鍵值
unsigned char qian,bai,shi,ge; //數(shù)碼管顯示的4位數(shù)字
unsigned char state=0;  //狀態(tài)變量,反映當(dāng)前狀態(tài):0-正常顯示,1-調(diào)分鐘,2-調(diào)秒
unsigned char miao,fen; //分鐘、秒
//LED顯示字模 0-F 共陽模式
unsigned code table[]= {0Xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
/*****************************************
* 函 數(shù) 名 :Delayms
* 函數(shù)功能 :實(shí)現(xiàn) ms級的延時(shí)
* 輸    入 :ms
* 輸    出 :無
*****************************************/
void Delayms(unsigned int ms)
{
    unsigned int i,j;
    for(i=0;i<ms;i++)
    #if FOSC == 11059200L
        for(j=0;j<114;j++);
    #elif FOSC ==12000000L
      for(j=0;j<123;j++);
    #elif FOSC ==24000000L
        for(j=0;j<249;j++);
    #else
        for(j=0;j<114;j++);
    #endif
}
/*****************************************
* 函 數(shù) 名 :Timer0Init
* 函數(shù)功能 :定時(shí)器0初始化
* 輸    入 :無
* 輸    出 :無
*****************************************/
void Timer0Init()
{
    TMOD=0x01; //設(shè)置定時(shí)器0工作方式為1
    TH0=(65536-FOSC/12/1000*TIME0_MS)/256;    //設(shè)置定時(shí)器初值高8位
    TL0=(65536-FOSC/12/1000*TIME0_MS)%256;    //設(shè)置定時(shí)器初值低8位
    ET0=1; //開啟定時(shí)器0中斷
    TR0=1; //開啟定時(shí)器0   
    EA=1;  //開總中斷
}
/*****************************************
* 函 數(shù) 名 :LEDdisplay
* 函數(shù)功能 :4位數(shù)碼管顯示函數(shù),循環(huán)顯示各個位上的數(shù)據(jù)
* 輸    入 :num要顯示的數(shù)據(jù)
* 輸    出 :無
*************************************/
void LEDdisplay()
{
    wela_1 = 1;   //關(guān)閉所有數(shù)碼管
    wela_2 = 1;
    wela_3 = 1;
    wela_4 = 1;
    wela_4=0;   //顯示千位,千位數(shù)碼管的位控制為0
    LED_PORT=table[qian];   //取table數(shù)組中的段碼送段碼顯示控制接口
    Delayms(1); //延時(shí)幾毫秒
    LED_PORT = 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
    wela_4=1;   //熄滅千位
   
    wela_3=0;  //顯示百位,百數(shù)碼管的位控制為0
    LED_PORT=table[bai]& 0x7F ;    //取table數(shù)組中的段碼送段碼顯示控制接口 0x7f實(shí)現(xiàn)顯示小數(shù)點(diǎn)
    Delayms(1); //延時(shí)幾毫秒
    LED_PORT = 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
    wela_3=1;   //熄滅百位
   
    wela_2=0;  //顯示十位,十位數(shù)碼管的位控制為0
    LED_PORT=table[shi];    //取table數(shù)組中的段碼送段碼顯示控制接口
    Delayms(1); //延時(shí)幾毫秒
    LED_PORT = 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
    wela_2=1;   //熄滅十位
   
    wela_1=0;  //顯示個位,個位數(shù)碼管的位控制為0
    LED_PORT=table[ge]; //取table數(shù)組中的段碼送段碼顯示控制接口
    Delayms(1); //延時(shí)幾毫秒
    LED_PORT = 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
    wela_1=1;   //熄滅個位
}
/*****************************************
* 函 數(shù) 名 :KeyScan
* 函數(shù)功能 :4*4鍵盤掃描
* 輸    入 :無
* 輸    出 :num 獲取的鍵值,若沒有鍵值則返回 0xff
*************************************/
unsigned char KeyScan()
{
    unsigned chartemp,num;
    num = 0xff;
//************************************
    KEY_PORT=0xfe;                 //P3口:1111 1110 行0為低電平(0)
    temp=KEY_PORT;                 //讀取P3口,送temp
    temp=temp&0xf0;                //temp高四位不變(保存列值),低四位清零
    while(temp!=0xf0)              //temp高四位不等于1111,說明列線中有0,說明有鍵按下
    {
        Delayms(5);                //延時(shí)消抖
        temp=KEY_PORT;             //再次讀取P3口,送temp
        temp=temp&0xf0;            //temp高四位不變,低四位清零
        while(temp!=0xf0)          //temp高四位不等于1111,說明列線中有0,說明確實(shí)有鍵按下
        {
            temp=KEY_PORT;         //讀取P3口,送temp
            switch(temp)
            {
                case0xee:num=1;    //高四位:1110(列0=0),低四位:1110(行0=0),說明行0與列0交叉位置按鍵按下
                   break;
                case0xde:num=2;    //高四位:1101(列1=0),低四位:1110(行0=0),說明行0與列1交叉位置按鍵按下
                   break;
                case0xbe:num=3;    //高四位:1011(列2=0),低四位:1110(行0=0),說明行0與列2交叉位置按鍵按下
                   break;
                case0x7e:num=4;    //高四位:0111(列3=0),低四位:1110(行0=0),說明行0與列3交叉位置按鍵按下
                   break;
            }
            while(temp!=0xf0)      //temp高四位不等于1111,說明列線中有0,說明有鍵按下沒松開(釋放)
            {
                temp=KEY_PORT;     //讀取P3口,送temp
                temp=temp&0xf0;     //temp高四位不變(保存列值),低四位清零
            }
        }
    }
    //************************************
    KEY_PORT=0xfd;                 //P3口:1111 1101 行1為低電平(0)
    temp=KEY_PORT;
    temp=temp&0xf0;
    while(temp!=0xf0)
    {
        Delayms(5);                //延時(shí)消抖
        temp=KEY_PORT;
        temp=temp&0xf0;
        while(temp!=0xf0)
        {
            temp=KEY_PORT;
            switch(temp)
            {
                case0xed:num=5;    //高四位:1110(列0=0),低四位:1101(行1=0),說明行1與列0交叉位置按鍵按下
                   break;
                case0xdd:num=6;    //高四位:1101(列1=0),低四位:1101(行1=0),說明行1與列1交叉位置按鍵按下
                   break;
                case0xbd:num=7;    //高四位:1011(列2=0),低四位:1101(行1=0),說明行1與列2交叉位置按鍵按下
                   break;
                case0x7d:num=8;    //高四位:0111(列3=0),低四位:1101(行1=0),說明行1與列3交叉位置按鍵按下
                   break;
            }
            while(temp!=0xf0)
            {
                temp=KEY_PORT;
                temp=temp&0xf0;
            }
        }
    }
    //***********************************
    KEY_PORT=0xfb;                 //P3口:1111 1011 行2為低電平(0)
    temp=KEY_PORT;
    temp=temp&0xf0;
    while(temp!=0xf0)
    {
        Delayms(5);                //延時(shí)消抖
        temp=KEY_PORT;
        temp=temp&0xf0;
        while(temp!=0xf0)
        {
            temp=KEY_PORT;
            switch(temp)
            {
                case0xeb:num=9;    //高四位:1110(列0=0),低四位:1011(行2=0),說明行2與列0交叉位置按鍵按下
                   break;
                case0xdb:num=10;   //高四位:1101(列1=0),低四位:1011(行2=0),說明行2與列1交叉位置按鍵按下
                   break;
                case0xbb:num=11;   //高四位:1011(列2=0),低四位:1011(行2=0),說明行2與列2交叉位置按鍵按下
                   break;
                case0x7b:num=12;   //高四位:0111(列3=0),低四位:1011(行2=0),說明行2與列3交叉位置按鍵按下
                   break;
            }
            while(temp!=0xf0)
            {
                temp=KEY_PORT;
                temp=temp&0xf0;            
            }
        }
    }
    //************************************
    KEY_PORT=0xf7;                 //P3口:1111 0111 行3為低電平(0)
    temp=KEY_PORT;
    temp=temp&0xf0;
    while(temp!=0xf0)
    {
        Delayms(5);                //延時(shí)消抖
        temp=KEY_PORT;
        temp=temp&0xf0;
        while(temp!=0xf0)
        {
            temp=KEY_PORT;
            switch(temp)
            {
                case0xe7:num=13;   //高四位:1110(列0=0),低四位:0111(行3=0),說明行3與列0交叉位置按鍵按下
                   break;
                case 0xd7:num=14;   //高四位:1101(列1=0),低四位:0111(行3=0),說明行3與列1交叉位置按鍵按下
                   break;
                case0xb7:num=15;   //高四位:1011(列2=0),低四位:0111(行3=0),說明行3與列2交叉位置按鍵按下
                   break;
                case0x77:num=16;   //高四位:0111(列3=0),低四位:0111(行3=0),說明行3與列3交叉位置按鍵按下
                   break;
            }
            while(temp!=0xf0)
            {
                temp=KEY_PORT;
                temp=temp&0xf0;
            }
        }
    }
    //************************************
    return num;
}
/*****************************************
* 函 數(shù) 名 :Key1
*************************************/
void Key3()     //key3減1鍵
{
    if(state==1)    //狀態(tài)為1,調(diào)分鐘狀態(tài)
        if(fen==0)  //分鐘值為0,則減1為59
            fen=59;
        else        //分鐘值不為0,則減1
            fen--;  //因此,分鐘的變化規(guī)律是0,59,...,1,0,59,...   
    if(state==2)    //狀態(tài)為2,調(diào)秒狀態(tài)
        if(miao==0) //秒值為0,則減1為59
            miao=59;
        else        //秒值不為0,則減1
            miao--; //因此,秒的變化規(guī)律是0,59,...,1,0,59,...
}
/*****************************************
* 函 數(shù) 名 :KeyHandle
* 函數(shù)功能 :鍵處理程序
* 輸    入 :無
* 輸    出 :無
*************************************/
void KeyHandle()
{
    switch(key_value)          //判斷鍵值,哪個按鍵按下?
    {
        case1:Key1();break;    //key1按下,調(diào)用key1()函數(shù)
        case2:Key2();break;    //key2按下,調(diào)用key2()函數(shù)
        case3:Key3();break;    //key3按下,調(diào)用key3()函數(shù)
        default:break;
    }
}
/*****************************************
* 函 數(shù) 名 :main
* 函數(shù)功能 :主函數(shù)
* 輸    入 :無
* 輸    出 :無
*************************************/
void main()
{
    Timer0Init();
    count = 0;
    fen = 59;
    miao = 58;
   
    while(1)
    {
        if(count == 20)     //達(dá)到1s=50ms*20次
        {
            count=0;        //計(jì)數(shù)值回零
            miao++;     //秒加1
            if(miao == 60)  //秒為60
            {
                miao = 0;   //秒回零
                fen ++; //分加一
                if(fen ==60) // 分為60
                   fen =0; //分回零
            }
        }
        
        key_value = KeyScan();
        KeyHandle();
        
        while(state!=0)        
        {
            ET0=0; //關(guān)閉定時(shí)器0中斷
            
            key_value=KeyScan();//調(diào)用鍵掃描函數(shù)獲得鍵值
            
            KeyHandle();       //調(diào)用鍵處理函數(shù)運(yùn)行各個鍵處理函數(shù)
            qian=fen/10;       //取分鐘的十位
            bai=fen%10;        //取分鐘的個位
            shi=miao/10;       //取秒的十位
            ge=miao%10;        //取秒的個位
            
            LEDdisplay();      //顯示當(dāng)前時(shí)間
        }
        
        //處理LED顯示
        qian=fen%100/10;   
        bai=fen%10;
        shi=miao%100/10;
        ge=miao%10;
        
        LEDdisplay();
    }
}
/*****************************************
* 函 數(shù) 名 :Timer0Int
* 函數(shù)功能 :定時(shí)器0中斷函數(shù) , 每隔TIME0_MS ms進(jìn)入
* 輸    入 :無
* 輸    出 :無
*************************************/
void Timer0Int() interrupt 1
{
    TH0=(65536-FOSC/12/1000*TIME0_MS)/256;//重新裝入初值高8位
    TL0=(65536-FOSC/12/1000*TIME0_MS)%256;//重新裝入初值低8位
    count++;           //計(jì)數(shù)值加1
}


3.2選做題程序


/****************************************************************************************
* 實(shí) 驗(yàn) 名:4*4矩陣按鍵實(shí)驗(yàn)
* 實(shí)驗(yàn)說明:采用循環(huán)方式實(shí)現(xiàn):數(shù)碼管顯示電子表:分鐘、秒,用3個按鍵實(shí)現(xiàn)調(diào)整
*            按鍵1:設(shè)置、確定
*            按鍵2:加1
*            按鍵3:減1
****************************************************************************************/
#include<reg52.h>
#include<intrins.h>
#defineFOSC 11059200L //晶振設(shè)置,默認(rèn)使用11.0592M Hz
//#defineFOSC 12000000L //晶振設(shè)置,使用12M Hz
//#defineFOSC 24000000L //晶振設(shè)置,使用24M Hz
#defineTIME0_MS 50 //設(shè)定定時(shí)時(shí)間50ms
#defineT10MS (65536-FOSC/12/100)   //10ms定時(shí):T10MS為定時(shí)器初值(16位)
//IO接口定義
#defineLED_PORT P0     //數(shù)碼管的段碼顯示控制接口
#defineKEY_PORT P1     //鍵盤控制接口
sbitwela_1 = P2^4;     //數(shù)碼管個位顯示控制口
sbitwela_2 = P2^5;     //數(shù)碼管十位顯示控制口
sbitwela_3 = P2^6;     //數(shù)碼管百位顯示控制口
sbitwela_4 = P2^7;     //數(shù)碼管千位顯示控制口
sbitspeak_IO =P3^6 ;      //蜂鳴器控制引腳
sbitLED1 = P3^5;                  //LED1控制引腳
//全局變量定義
unsignedchar count;           //定時(shí)器計(jì)數(shù)次數(shù)
unsignedchar count_2;             //計(jì)數(shù)器變量
unsignedchar key_value;//鍵值
unsignedchar qian,bai,shi,ge; //數(shù)碼管顯示的4位數(shù)字
unsignedchar alarm_qian,alarm_bai,alarm_shi,alarm_ge; //數(shù)碼管顯示的4位數(shù)字
unsignedchar state=0;  //狀態(tài)變量,反映當(dāng)前狀態(tài):0-正常顯示,1-調(diào)分鐘,2-調(diào)秒
unsignedchar miao,fen; //分鐘、秒
unsignedchar alarm_miao,alarm_fen; //分鐘、秒
//LED顯示字模 0-F 共陽模式
unsignedcode table[]={0Xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsignedchar code SONG[] ={
//祝你平安(217字節(jié))
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,
0x26,0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,
0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,0x20,0x80,0x2b,0x20,
0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,
0x39,0x10,0x26,0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,
0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,0x2b,0x20,0x30,0x10,
0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,
0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,
0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,
0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x1c,0x20,
0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,
0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,
0x2b,0x10,0x2b,0x80,0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,
0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,
0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,
0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,
0x40,0x10,0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,
0x00,
//路邊的野花不要采(164字節(jié))
0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,
0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,
0xFF,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,
0x20,0x30,0x20,0x2B,0x40,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,
0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x30,0x1C,
0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,
0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0x20,0x30,0x1C,
0x10,0x20,0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x15,0x1F,0x05,0x20,0x10,0x1C,0x10,0x20,
0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x30,0x1C,
0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,
0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x30,0x20,0x30,0x1C,
0x10,0x18,0x40,0x1C,0x20,0x20,0x20,0x26,0x40,0x13,0x60,0x18,
0x20,0x15,0x40,0x13,0x40,0x18,0x80,
0x00,
};
/*******************************************************************************
* 函 數(shù) 名:Delayms
* 函數(shù)功能:實(shí)現(xiàn) ms級的延時(shí)
* 輸    入 :ms
* 輸    出 :無
*******************************************************************************/
voidDelayms(unsigned int ms)
{
unsignedint i,j;
for(i=0;i<ms;i++)
#ifFOSC == 11059200L
for(j=0;j<114;j++);
#elifFOSC == 12000000L
for(j=0;j<123;j++);
#elifFOSC == 24000000L
for(j=0;j<249;j++);
#else
for(j=0;j<114;j++);
#endif
}
/*******************************************************************************
* 函 數(shù) 名:Delayus
* 函數(shù)功能:us級延時(shí)
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidDelayus(unsigned int us)
{
unsignedint i,j;
for(i =0;i < us;i++ )
{
for(j =0;j<3;j++ );
}
}
/*******************************************************************************
* 函 數(shù) 名:Timer0Init
* 函數(shù)功能:定時(shí)器0初始化
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidTimer0Init()
{
TMOD=0x01;//設(shè)置定時(shí)器0工作方式為1
TH0=(65536-FOSC/12/1000*TIME0_MS)/256;    //設(shè)置定時(shí)器初值高8位
TL0=(65536-FOSC/12/1000*TIME0_MS)%256;    //設(shè)置定時(shí)器初值低8位
ET0=1;//開啟定時(shí)器0中斷
TR0=1;//開啟定時(shí)器0
EA=1;  //開總中斷
}
/*******************************************************************************
* 函 數(shù) 名:Time1_Init
* 函數(shù)功能:定時(shí)器1初始化
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidTime1Init()
{
TMOD|= 0x10;       //工作模式選擇:定時(shí)器T1工作在方式1:16位定時(shí)器模式
ET1  = 1;           //定時(shí)器T1中斷允許
EA   = 1;           //總中斷允許
TH1  = T10MS>>8;    //裝初值高8位,延時(shí)10ms
TL1  = T10MS;       //裝初值低8位,延時(shí)10ms
}
/*******************************************************************************
* 函 數(shù) 名:LEDdisplay
* 函數(shù)功能:4位數(shù)碼管顯示函數(shù),循環(huán)顯示各個位上的數(shù)據(jù)
* 輸    入 :num要顯示的數(shù)據(jù)
* 輸    出 :無
*******************************************************************************/
voidLEDdisplay()
{
wela_1= 1;  //關(guān)閉所有數(shù)碼管
wela_2= 1;
wela_3= 1;
wela_4= 1;
wela_4=0;   //顯示千位,千位數(shù)碼管的位控制為0
LED_PORT=table[qian];   //取table數(shù)組中的段碼送段碼顯示控制接口
Delayms(1); //延時(shí)幾毫秒
LED_PORT= 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
wela_4=1;   //熄滅千位
wela_3=0;  //顯示百位,百數(shù)碼管的位控制為0
LED_PORT=table[bai]& 0x7F ;    //取table數(shù)組中的段碼送段碼顯示控制接口 0x7f實(shí)現(xiàn)顯示小數(shù)點(diǎn)
Delayms(1); //延時(shí)幾毫秒
LED_PORT= 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
wela_3=1;   //熄滅百位
wela_2=0;  //顯示十位,十位數(shù)碼管的位控制為0
LED_PORT=table[shi];    //取table數(shù)組中的段碼送段碼顯示控制接口
Delayms(1); //延時(shí)幾毫秒
LED_PORT= 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
wela_2=1;   //熄滅十位
wela_1=0;  //顯示個位,個位數(shù)碼管的位控制為0
LED_PORT=table[ge]; //取table數(shù)組中的段碼送段碼顯示控制接口
Delayms(1); //延時(shí)幾毫秒
LED_PORT= 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
wela_1=1;   //熄滅個位
}
/*******************************************************************************
* 函 數(shù) 名:LEDdisplay_alarm
* 函數(shù)功能:4位數(shù)碼管顯示函數(shù),循環(huán)顯示各個位上的數(shù)據(jù)
* 輸    入 :num要顯示的數(shù)據(jù)
* 輸    出 :無
*******************************************************************************/
voidLEDdisplay_alarm()
{
wela_1= 1;  //關(guān)閉所有數(shù)碼管
wela_2= 1;
wela_3= 1;
wela_4= 1;
wela_4=0;   //顯示千位,千位數(shù)碼管的位控制為0
LED_PORT=table[alarm_qian]; //取table數(shù)組中的段碼送段碼顯示控制接口
Delayms(1); //延時(shí)幾毫秒
LED_PORT= 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
wela_4=1;   //熄滅千位
wela_3=0;  //顯示百位,百數(shù)碼管的位控制為0
LED_PORT=table[alarm_bai]& 0x7F ;  //取table數(shù)組中的段碼送段碼顯示控制接口 0x7f實(shí)現(xiàn)顯示小數(shù)點(diǎn)
Delayms(1); //延時(shí)幾毫秒
LED_PORT= 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
wela_3=1;   //熄滅百位
wela_2=0;  //顯示十位,十位數(shù)碼管的位控制為0
LED_PORT=table[alarm_shi];  //取table數(shù)組中的段碼送段碼顯示控制接口
Delayms(1); //延時(shí)幾毫秒
LED_PORT= 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
wela_2=1;   //熄滅十位
wela_1=0;  //顯示個位,個位數(shù)碼管的位控制為0
LED_PORT=table[alarm_ge];   //取table數(shù)組中的段碼送段碼顯示控制接口
Delayms(1); //延時(shí)幾毫秒
LED_PORT= 0xff;        //熄滅數(shù)碼管,因共陽極所以0xff送段碼顯示控制接口
wela_1=1;   //熄滅個位
}
/*******************************************************************************
* 函 數(shù) 名:KeyScan
* 函數(shù)功能:4*4鍵盤掃描
* 輸    入 :無
* 輸    出 :num 獲取的鍵值,若沒有鍵值則返回 0xff
*******************************************************************************/
unsignedchar KeyScan()
{
unsignedchar temp,num;
num= 0xff;
//**************************************************************************
KEY_PORT=0xfe;                 //P3口:1111 1110 行0為低電平(0)
temp=KEY_PORT;                 //讀取P3口,送temp
temp=temp&0xf0;                //temp高四位不變(保存列值),低四位清零
while(temp!=0xf0)              //temp高四位不等于1111,說明列線中有0,說明有鍵按下
{
Delayms(5);                //延時(shí)消抖
temp=KEY_PORT;             //再次讀取P3口,送temp
temp=temp&0xf0;            //temp高四位不變,低四位清零
while(temp!=0xf0)          //temp高四位不等于1111,說明列線中有0,說明確實(shí)有鍵按下
{
temp=KEY_PORT;         //讀取P3口,送temp
switch(temp)
{
case0xee:num=1;    //高四位:1110(列0=0),低四位:1110(行0=0),說明行0與列0交叉位置按鍵按下
break;
case0xde:num=2;    //高四位:1101(列1=0),低四位:1110(行0=0),說明行0與列1交叉位置按鍵按下
break;
case0xbe:num=3;    //高四位:1011(列2=0),低四位:1110(行0=0),說明行0與列2交叉位置按鍵按下
break;
case0x7e:num=4;    //高四位:0111(列3=0),低四位:1110(行0=0),說明行0與列3交叉位置按鍵按下
break;
}
while(temp!=0xf0)      //temp高四位不等于1111,說明列線中有0,說明有鍵按下沒松開(釋放)
{
temp=KEY_PORT;     //讀取P3口,送temp
temp=temp&0xf0;     //temp高四位不變(保存列值),低四位清零
}
}
}
//**************************************************************************
KEY_PORT=0xfd;                 //P3口:1111 1101 行1為低電平(0)
temp=KEY_PORT;
temp=temp&0xf0;
while(temp!=0xf0)
{
Delayms(5);                //延時(shí)消抖
temp=KEY_PORT;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=KEY_PORT;
switch(temp)
{
case0xed:num=5;    //高四位:1110(列0=0),低四位:1101(行1=0),說明行1與列0交叉位置按鍵按下
break;
case0xdd:num=6;    //高四位:1101(列1=0),低四位:1101(行1=0),說明行1與列1交叉位置按鍵按下
break;
case0xbd:num=7;    //高四位:1011(列2=0),低四位:1101(行1=0),說明行1與列2交叉位置按鍵按下
break;
case0x7d:num=8;    //高四位:0111(列3=0),低四位:1101(行1=0),說明行1與列3交叉位置按鍵按下
break;
}
while(temp!=0xf0)
{
temp=KEY_PORT;
temp=temp&0xf0;
}
}
}
//**************************************************************************
KEY_PORT=0xfb;                 //P3口:1111 1011 行2為低電平(0)
temp=KEY_PORT;
temp=temp&0xf0;
while(temp!=0xf0)
{
Delayms(5);                //延時(shí)消抖
temp=KEY_PORT;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=KEY_PORT;
switch(temp)
{
case0xeb:num=9;    //高四位:1110(列0=0),低四位:1011(行2=0),說明行2與列0交叉位置按鍵按下
break;
case0xdb:num=10;   //高四位:1101(列1=0),低四位:1011(行2=0),說明行2與列1交叉位置按鍵按下
break;
case0xbb:num=11;   //高四位:1011(列2=0),低四位:1011(行2=0),說明行2與列2交叉位置按鍵按下
break;
case0x7b:num=12;   //高四位:0111(列3=0),低四位:1011(行2=0),說明行2與列3交叉位置按鍵按下
break;
}
while(temp!=0xf0)
{
temp=KEY_PORT;
temp=temp&0xf0;
}
}
}
//**************************************************************************
KEY_PORT=0xf7;                 //P3口:1111 0111 行3為低電平(0)
temp=KEY_PORT;
temp=temp&0xf0;
while(temp!=0xf0)
{
Delayms(5);                //延時(shí)消抖
temp=KEY_PORT;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=KEY_PORT;
switch(temp)
{
case0xe7:num=13;   //高四位:1110(列0=0),低四位:0111(行3=0),說明行3與列0交叉位置按鍵按下
break;
case0xd7:num=14;   //高四位:1101(列1=0),低四位:0111(行3=0),說明行3與列1交叉位置按鍵按下
break;
case0xb7:num=15;   //高四位:1011(列2=0),低四位:0111(行3=0),說明行3與列2交叉位置按鍵按下
break;
case0x77:num=16;   //高四位:0111(列3=0),低四位:0111(行3=0),說明行3與列3交叉位置按鍵按下
break;
}
while(temp!=0xf0)
{
temp=KEY_PORT;
temp=temp&0xf0;
}
}
}
//**************************************************************************
returnnum;
}
/*******************************************************************************
* 函 數(shù) 名:Key1
* 函數(shù)功能:1號鍵處理程序
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidKey1()     //key1改變狀態(tài)
{
state++;    //狀態(tài)值加1
if(state==5)//若狀態(tài)加到3,
{
state=0;    //則回0
ET0= 1;
}
//因此,按下key1狀態(tài)state變化規(guī)律為:0,1,2,0,1,2,...
//狀態(tài)state=0:正常顯示
//狀態(tài)state=1:調(diào)分鐘
//狀態(tài)state=2:調(diào)秒
}
/*******************************************************************************
* 函 數(shù) 名:Key2
* 函數(shù)功能:2號鍵處理程序
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidKey2()     //key2加1鍵
{
if(state==1)    //狀態(tài)為1,調(diào)分鐘狀態(tài)
if(fen==59) //分鐘值為59,則加1為0
fen=0;
else        //分鐘值不為59,則加1
fen++;  //因此,分鐘的變化規(guī)律是0,1,...,59,0,1,...
if(state==2)    //狀態(tài)為2,調(diào)秒狀態(tài)
if(miao==59)//秒值為59,則加1為0
miao=0;
else        //秒值不為59,則加1
miao++; //因此,秒的變化規(guī)律是0,1,...,59,0,1,...
if(state==3)    //狀態(tài)為1,調(diào)鬧鐘分鐘狀態(tài)
if(alarm_fen==59)   //分鐘值為59,則加1為0
alarm_fen=0;
else        //分鐘值不為59,則加1
alarm_fen++;    //因此,鬧鐘分鐘的變化規(guī)律是0,1,...,59,0,1,...
if(state==4)    //狀態(tài)為2,調(diào)鬧鐘秒狀態(tài)
if(alarm_miao==59)//秒值為59,則加1為0
alarm_miao=0;
else        //秒值不為59,則加1
alarm_miao++;   //因此,秒的變化規(guī)律是0,1,...,59,0,1,...
}
/*******************************************************************************
* 函 數(shù) 名:Key3
* 函數(shù)功能:3號鍵處理程序
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidKey3()     //key3減1鍵
{
if(state==1)    //狀態(tài)為1,調(diào)分鐘狀態(tài)
if(fen==0)  //分鐘值為0,則減1為59
fen=59;
else        //分鐘值不為0,則減1
fen--;  //因此,分鐘的變化規(guī)律是0,59,...,1,0,59,...
if(state==2)    //狀態(tài)為2,調(diào)秒狀態(tài)
if(miao==0) //秒值為0,則減1為59
miao=59;
else        //秒值不為0,則減1
miao--; //因此,秒的變化規(guī)律是0,59,...,1,0,59,...
if(state==3)    //狀態(tài)為1,調(diào)分鐘狀態(tài)
if(alarm_fen==0)    //分鐘值為0,則減1為59
alarm_fen=59;
else        //分鐘值不為0,則減1
alarm_fen--;    //因此,分鐘的變化規(guī)律是0,59,...,1,0,59,...
if(state==4)    //狀態(tài)為2,調(diào)秒狀態(tài)
if(alarm_miao==0)   //秒值為0,則減1為59
alarm_miao=59;
else        //秒值不為0,則減1
alarm_miao--;   //因此,秒的變化規(guī)律是0,59,...,1,0,59,...
}
/*******************************************************************************
* 函 數(shù) 名:KeyHandle
* 函數(shù)功能:鍵處理程序
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidKeyHandle()
{
switch(key_value)          //判斷鍵值,哪個按鍵按下?
{
case1:Key1();break;    //key1按下,調(diào)用key1()函數(shù)
case2:Key2();break;    //key2按下,調(diào)用key2()函數(shù)
case3:Key3();break;    //key3按下,調(diào)用key3()函數(shù)
default:break;
}
}
/*******************************************************************************
* 函 數(shù) 名:PlaySong
* 函數(shù)功能:歌曲播放子程序,i為播放哪一段曲目
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidPlaySong(unsigned char i)
{
unsignedchar Temp1,Temp2;
unsignedint Addr;
count_2= 0;                //中斷計(jì)數(shù)器清0
Addr= i * 217;
ET0= 0; //關(guān)閉定時(shí)器0中斷
while(key_value!= 4)
{
Temp1= SONG[Addr++];  //讀取音符的頻率值
if (Temp1 == 0xFF )   //休止符0xFF
{
TR1= 0;           //停止定時(shí)器T1
Delayus(100);      //延時(shí)100us
}
elseif ( Temp1 == 0x00 )   //歌曲結(jié)束符0x00
{
return;
}
else
{
Temp2= SONG[Addr++];//讀取一個音的時(shí)長
TR1= 1;             //啟動定時(shí)器T1
while(key_value!= 4)
{
key_value= KeyScan();
if (key_value == 4)
ET0= 1; //打開定時(shí)器0中斷
speak_IO= ~speak_IO;
LED1= ~LED1;
Delayus(Temp1);
if (Temp2 == count_2 )//一個音結(jié)束
{
count_2= 0;
break;
}
}
}
}
}
/*******************************************************************************
* 函 數(shù) 名:main
* 函數(shù)功能:主函數(shù)
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidmain()
{
Timer0Init();
Time1Init();   //定時(shí)器1中斷初始化
count= 0;
fen= 59;
miao= 58;
alarm_fen= 0;
alarm_miao= 2;
while(1)
{
if(count== 20)     //達(dá)到1s=50ms*20次
{
count=0;        //計(jì)數(shù)值回零
miao++;     //秒加1
if(miao== 60)  //秒為60
{
miao= 0;   //秒回零
fen++; //分加一
if(fen== 60) // 分為60
fen= 0; //分回零
}
}
key_value=KeyScan();//調(diào)用鍵掃描函數(shù)獲得鍵值
KeyHandle();       //調(diào)用鍵處理函數(shù)運(yùn)行各個鍵處理函數(shù)
//鬧鐘
if ((alarm_miao == miao) && (alarm_fen == fen) )
{
PlaySong(0);    //播放第一首歌
miao++;
}
while(state!=0)
{
ET0= 0; //關(guān)閉定時(shí)器0中斷
key_value=KeyScan();//調(diào)用鍵掃描函數(shù)獲得鍵值
KeyHandle();       //調(diào)用鍵處理函數(shù)運(yùn)行各個鍵處理函數(shù)
qian=fen/10;       //取分鐘的十位
bai=fen%10;        //取分鐘的個位
shi=miao/10;       //取秒的十位
ge=miao%10;        //取秒的個位
alarm_qian=alarm_fen/10;       //取鬧鐘的分鐘的十位
alarm_bai=alarm_fen%10;        //取鬧鐘的分鐘的個位
alarm_shi=alarm_miao/10;       //取鬧鐘的秒的十位
alarm_ge=alarm_miao%10;        //取鬧鐘的秒的個位
if((state == 1)||(state == 2) )
LEDdisplay();      //顯示當(dāng)前時(shí)間
elseif( (state == 3)||(state == 4) )
LEDdisplay_alarm();//顯示當(dāng)前鬧鐘時(shí)間
else
;
}
//處理LED顯示
qian=fen%100/10;
bai=fen%10;
shi=miao%100/10;
ge=miao%10;
LEDdisplay();
}
}
/*******************************************************************************
* 函 數(shù) 名:Timer0Int
* 函數(shù)功能:定時(shí)器0中斷函數(shù) , 每隔TIME0_MS ms進(jìn)入
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidTimer0Int() interrupt 1
{
TH0=(65536-FOSC/12/1000*TIME0_MS)/256;//重新裝入初值高8位
TL0=(65536-FOSC/12/1000*TIME0_MS)%256;//重新裝入初值低8位
count++;           //計(jì)數(shù)值加1
}
/*******************************************************************************
* 函 數(shù) 名:Time1Int
* 函數(shù)功能:定時(shí)器1中斷子函數(shù),count為10ms計(jì)數(shù)器變量
* 輸    入 :無
* 輸    出 :無
*******************************************************************************/
voidTime1Int() interrupt 3  //定時(shí)器1中斷子函數(shù)
{
TH1  = T10MS>>8;   //16位數(shù)右移8位得到高8位,TH1裝初值高8位,定時(shí)10ms
TL1  = T10MS;      //TL1裝初值低8位,定時(shí)10ms
count_2++;           //計(jì)數(shù)器變量加1
}


四、本任務(wù)中的幾個功能如何實(shí)現(xiàn)?(說明設(shè)計(jì)思路)
設(shè)計(jì)思路:
例程“矩陣按鍵調(diào)整時(shí)間實(shí)驗(yàn)”符合選做功能框架、不同點(diǎn)為計(jì)時(shí)采用的是依靠程序運(yùn)行時(shí)間,不準(zhǔn)確,例程“動態(tài)數(shù)碼管與定時(shí)器中斷實(shí)驗(yàn)”采用定時(shí)器計(jì)時(shí),則考慮用前者為基礎(chǔ),將后者的定時(shí)器計(jì)時(shí)代碼整合。即可完成必做功能。選做功能以必做功能為依托,增加鬧鐘功能,鬧鐘的播放樂曲依托蜂鳴器實(shí)驗(yàn)例程完成,鬧鐘實(shí)現(xiàn)采用當(dāng)設(shè)定時(shí)間的分、秒與單片機(jī)當(dāng)前計(jì)時(shí)一致時(shí)(if語句)、開始報(bào)警。
編程過程:
必做功能,
1.  在例程基礎(chǔ)上增加分鐘計(jì)時(shí),當(dāng)秒為60時(shí),秒回零,分鐘加一,分鐘為60時(shí),回零。
2.  LED顯示函數(shù)中,百位顯示小數(shù)點(diǎn):將table中的碼段&0x7f,顯示小數(shù)點(diǎn);實(shí)現(xiàn)功能。
3.  在按下key1后,應(yīng)當(dāng)關(guān)閉中斷,停止當(dāng)前計(jì)時(shí),待state為3時(shí)(恢復(fù)為計(jì)時(shí)功能)重新開中斷。
選做功能:
1.  增加Playsong函數(shù),對Playsong中加入按鍵掃描,將函數(shù)中while(1)改為while(key_value!= 4),用作實(shí)現(xiàn)按下key4停止功能。
2.  修改三個按鍵處理函數(shù),對key1,增加state的顯示狀態(tài),用于設(shè)置調(diào)整鬧鐘時(shí)間的模式,對key2和key3,增加響應(yīng)state下的調(diào)整功能。

51hei.png


全部資料51hei下載地址:
選做-定時(shí)器應(yīng)用設(shè)計(jì).rar (6.55 MB, 下載次數(shù): 16)

回復(fù)

使用道具 舉報(bào)

ID:328014 發(fā)表于 2020-8-2 17:15 | 顯示全部樓層
好資料,51黑有你更精彩!!!
回復(fù)

使用道具 舉報(bào)

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

本版積分規(guī)則

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

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

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