• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

用89c51单片机编写时钟程序

随便86 2016-12-21 浏览量:1361
#include <reg51.h>
sfr P1M0 =0x92;
sfr P1M1 =0x91;
char buf[4] ={0x01,0x02,3,4};
char hour=0,min=0,sec=0;
char code TAB[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
 
int time;
void delay(void){
   unsigned int j;
   j=1000;
   for(;j--;);
  }
unsigned int count=0;
void dir(void){
 P0= TAB[buf[0]]  ;
 P1=0x08;
  delay();
  P0=0xff;  //£¿£¿£¿
   P1=0x02;
 P0= TAB[buf[1]]  ;
   if(count>10)P0&=0x7f;
 P1=0x02;
  delay();
  P0=0xff;
 
  P1=0x04;
 P0= TAB[buf[2]]  ;
  //if(count>10)P0&=0x7f;
  delay();
  P0=0xff;
 P1=0x01; 
 P0= TAB[buf[3]]  ;
  delay();
  P0=0xff;
    P1=0x00;

void t1(void) interrupt  3 {
 TL1= (char)(15536&0x00ff);
   TH1= (char)(15536>>8);
     count++;
   if(count>19){
    count=0;
    //buf[3]++;
    time++;
    if(time>3599)   time=0;
    hour++
    if(hour>23)
   } 
}    

 
void main(void){
 char min,sec;
 hour
   P1M0 =0x0f;
 P1M1 =0x00;
  TMOD=0x10; 
 TH1= (char)(15536>>8);
 TL1= (char)(15536&0x00ff); 
 IE=0x88;
  TR1=1;
 while(1) {
  
  min=(char)(time/60) ;
  buf[0]=min/10;   buf[1]=min%10;
  
  sec=(char)(time%60) ;
  buf[2]=sec/10;   buf[3]=sec%10;
  
  dir();
  
 }
}


这个程序每步的解释,想在加点每到1小时蜂鸣器喊5秒,每10分20分30分等时间数码管闪烁10次

0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案
  • #include <reg51.h>

    #define uchar unsigned char
    #define uint  unsigned int
    uchar hour=23,min=59,sec=45;        //定义小时、分钟和秒变量
    uchar count_10ms;                         //定义10ms计数器
    sbit        K1 = P3^2;                        //定义K1键
    sbit        K2 = P3^3;                        //定义K2键
    sbit        K3 = P3^4;                        //定义K3键
    sbit        K4 = P3^5;                        //定义K4键
    sbit  BEEP=P3^7;                        //定义蜂鸣器
    bit K1_FLAG=0;                                //定义按键标志位,当按下K1键时,该位置1,K1键未按下时,该位为0。
    uchar code bit_tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选表,用来选择哪一只数码管进行显示
    uchar code seg_data[]={0x28, 0x7E, 0xA2, 0x62, 0x74, 0x61, 0x21, 0x7A, 0x20, 0x60,0xff};//0,1,2,3,4,5,6,7,8,9,关显示,数码管码表
                                                            //0~F、熄灭符和字符"-"的显示码(字形码)
    uchar disp_buf[8];                                //定义显示缓冲单元
    /********以下是延时函数********/
    void Delay_ms(uint xms)                                
    {
            uint i,j;
            for(i=xms;i>0;i--)                              //i=xms即延时约xms毫秒
                    for(j=110;j>0;j--);
    }
    /*********以下是蜂鸣器响一声函数********/
    void  beep()
    {
      BEEP=0;                       //蜂鸣器响
      Delay_ms(100); 
      BEEP=1;                   //关闭蜂鸣器
      Delay_ms(100);    
    }
    /********以下是走时转换函数,负责将走时数据转换为适合数码管显示的数据********/        
    void conv(uchar in1,in2,in3)                //形参in1、in2、in3接收实参hour、min、sec传来的数据
    {
            disp_buf[0] =in1/10;                        // 小时十位
            disp_buf[1] = in1%10;                // 小时个位
            disp_buf[3] = in2/10;                // 分钟十位
            disp_buf[4] = in2%10;                // 分钟个位
            disp_buf[6] = in3/10;                // 秒十位
            disp_buf[7] = in3%10;                // 秒个位
            disp_buf[2] = 17;                        // 第3只数码管显示"-"(在 seg_data表的第17位)
            disp_buf[5] = 17;                        // 第6只数码管显示"-"
    }

    /********以下是显示函数********/
    void Display()
    {
            uchar tmp;                                //定义显示暂存
            static uchar disp_sel=0;                //显示位选计数器,显示程序通过它得知现正显示哪个数码管,初始值为0
            tmp=bit_tab[disp_sel];                //根据当前的位选计数值决定显示哪只数码管
            P2=tmp;                                //送P2控制被选取的数码管点亮
            tmp=disp_buf[disp_sel];                //根据当前的位选计数值查的数字的显示码
            tmp=seg_data[tmp];                        //取显示码
            P0=tmp;                                //送到P0口显示出相应的数字
            disp_sel++;                                //位选计数值加1,指向下一个数码管
            if(disp_sel==8)                        
            disp_sel=0;                                //如果8个数码管显示了一遍,则让其回0,重新再扫描
    }
    /********以下是定时器T0中断函数, 用于数码管的动态扫描********/
    void timer0() interrupt 1
    {
            TH0 = 0xf8;TL0 = 0xcc;                //重装计数初值,定时时间为2ms        
            Display();                                //调显示函数

    /********以下是定时器T1中断函数, 用于产生用于产生秒、分钟和小时信号********/
    void timer1() interrupt 3
    {
            TH1 = 0xdc;TL0 = 0x00;                //重装计数初值,定时时间为10ms
            count_10ms++;                        //10ms计数器加1
            if(count_10ms >= 100)                
            {
                    count_10ms = 0;                //计数100次后恰好为1s,此时10ms计数器清0
                    sec++;                                //秒加1
                    if(sec == 60)
                    {
                            sec = 0;
                            min++;                //若到60秒,分钟加1
                            if(min ==60)
                            {
                                    min = 0;
                                    hour++;                //若到60分钟,小时加1
                                    if(hour ==24)
                                    {
                                            hour = 0;min=0;sec=0; //若到24小时,小时、分钟和秒单元清0
                                    }
                            }
                    }
            }
    }        
    /********以下是按键处理函数,用来对按键进行处理********/
    void  KeyProcess()
    {
            TR1=0;                                //若按下K1键,则定时器T1关闭,时钟暂停
            if(K2==0)                                //若按下K2键
             {
                    Delay_ms(10);                //延时去抖
                    if(K2==0)
                    {
                            while(!K2);                //等待K2键释放
                            beep();
                            hour++;                //小时调整
                            if(hour==24)
                            {
                                    hour = 0;
                            }
                    }
            }
            if(K3==0)                                //若按下K3键
             {
                    Delay_ms(10);
                    if(K3==0)
                    {
                            while(!K3);                //等待K3键释放
                            beep();
                               min++;                //分钟调整
                            if(min==60)
                            {
                                    min = 0;
                            }                
                    }
            }
            if(K4==0)                                //若按下K4键
             {
                    Delay_ms(10);
                    if(K4==0)
                    {
                            while(!K4);                //等待K4键释放
                            beep();
                            TR1=1;                //调整完毕后,时钟恢复走时
                            K1_FLAG=0;                //将K1键按下标志位清0 
                    }
            }        
    }
    /*********以下是定时器T0/T1初始化函数********/
    void  timer_init()

            TMOD = 0x11;                        // 定时器0, 1工作模式1, 16位定时方式
            TH0 = 0xf8;TL0 = 0xcc;                //装定时器T0计数初值,定时时间为2ms
            TH1 = 0xdc;TL1 = 0x00;                // 装定时器T1计数初值,定时时间为10ms
            EA=1;ET0=1;ET1=1;                        //开总中断和定时器T0、T1中断
            TR0 = 1;TR1 = 1;                        //启动定时器T0、T1
    }
    /********以下是主函数********/        
    void main(void)
    {
            P0 = 0xff;
            P2 = 0xff;
            timer_init();                                        //调定时器T0、T1初始化函数
            while(1)
            {
                    if(K1==0)                                //若K1键按下
                    {
                            Delay_ms(10);                //延时10ms去抖
                            if(K1==0)
                            {
                                    while(!K1);                //等待K1键释放
                                    beep();                //蜂鸣器响一声
                                    K1_FLAG=1;                //K1键标志位置1,以便进行时钟调整
                            }
                    }
                    if(K1_FLAG==1)KeyProcess();                        //若K1_FLAG为1,则进行走时调整        
                    conv(hour,min,sec);                                                //调走时转换函数                
            }
    }
    • 发布于 2016-12-21
    • 举报
    • 评论 0
    • 0
    • 0

其他答案 数量:3
  • 这个程序很简单,只是我现在帮不了你


    • 发布于2016-12-21
    • 举报
    • 评论 0
    • 0
    • 0

  • 岗位要求:

    1、大专及以上学历,电子信息工程,计算机及其相关专业;
    2、三年以上行业相关工作经验;

    3、 熟练C++/C语言,熟悉ARM / Linux嵌入式开发和交叉编议;

    4、熟悉 windows界面开发;

    5、有良好的编程习惯,英语熟练,很好有沟通能力,团队协作能力,以及抗压能力;

    6、有智能交通、停车场系统、加油站系统等行业系统软件开发经验者优先,能够独立完成LED智能交通软件对接工作者尤佳;

    7、身体健康,开朗乐观,有责任心和荣誉感。

    相关待遇:

    1、5.5天7.5小时工作制,假期跟国家同步。

    2、包吃包住,住宿舒适4—6人间,宿舍有热水器,吃饭每天三餐只需10元。
    3、全勤奖30元/月,有年终奖,每年均有调薪机会。

    4、每月评比优秀员工,奖励200元/次。
    5、员工社保,过节过生日礼品发放,员工活动丰富多彩。
    6、每年端午节有一次全员省内旅游活动,放松您的身心。

    7、完善的晋升机制,岗位有发展前景。

    8、办公环境良好,工作气氛好,管理人性化。

    9、国内外销售均有培训,有平台和展会,上手速度快。

    10、高层尊重体恤员工劳动成果,让您得到足够重视

    • 发布于2016-12-21
    • 举报
    • 评论 0
    • 0
    • 0

  • 嗨,您是問這段Code怎麼改吧?

    蜂鳴器叫可以做,但數碼管閃爍,本來就是逐位掃描方式,要一起閃不太可能,但可以ˊ有逐位數碼管ˊˊ掃描不夠快產生的閃爍現象

    宣告改成

    #include <reg51.h>
    sfr P1M0 =0x92;
    sfr P1M1 =0x91;
    char buf[4] ={0x01,0x02,3,4};
    char hour=0,min=0,sec=0;
    char code TAB[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
    volatile unsigned int count=0;
    char beeper=0;
    然後改主函數,和中斷函數,減速版的數碼管顯示就您自己測了,改delay時間長度即可

    void t1(void) interrupt  3 {
       TL1= (char)(15536&0x00ff);
       TH1= (char)(15536>>8);
       sec++;
       if(sec>59)
       {
         sec=0;
         min++;
       }
       if(min>59)
         min=0;
    }  
    
    void main(void){
     P1M0 =0x0f;
     P1M1 =0x00;
     TMOD=0x10; 
     TH1= (char)(15536>>8);
     TL1= (char)(15536&0x00ff); 
     IE=0x88;
     TR1=1;
     while(1) {
      
      buf[0]=sec%10;   
      buf[1]=sec/10;
      buf[2]=min%10;   
      buf[3]=min/10;
    
      if(min==0 && sec==0)
         beeper==1;
    
      if(beeper==1)
      {
        if(sec<5)
          beep_on(); //打開Beeper所接的GPIO
        else
        {
          beep_off();
          beeper=0;
        }
      }
    
      if(min==10 || min==20 || min==30)
      {
        if(sec<10)
           dir_slow(); //將數碼管函數重做一個 delay加長,達到閃爍
        else
           dir(); //正常顯示
      }
      else
        dir();
     }
    }
    以上希望有幫助到您

    • 发布于2016-12-21
    • 举报
    • 评论 2
    • 0
    • 0
MOP 回复了 MOP :宣告改成volatile char sec=0; 這沒改到 回复
MOP 回复了 MOP :同理volatile char min=0; 回复

相关问题

问题达人换一批

用89c51单片机编写时钟程序