找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2841|回复: 2
打印 上一主题 下一主题
收起左侧

LCD1602 AT89s52单片机定时闹钟_我编程及制作(代码完整,C51编译通过)

[复制链接]
跳转到指定楼层
楼主
仿真截图1_设置定时时间:
            

仿真截图2_正在计时:

//源程序名:a_clock.c

#include<reg52.h>   
#include<stdlib.h>   
#include<intrins.h>  //包含_nop_()函数定义的头文件


unsigned char code digit[ ]={"0123456789"}; //LCD1602初始化字符
unsigned char code str_1[ ]={"Set delay time:"};
unsigned char code str_2[ ]={"  Count time:  "};
unsigned char count;   //Timer0计数溢出中断次数
unsigned char s,m,h;   //即时的(秒,分,时)变量
unsigned char ss,mm,hh;//预设定时(秒,分,时)变量
unsigned char i;       //循环变量
sbit RS=P2^0;    //LCD寄存器选择位,将RS位定义为P2.0引脚
sbit RW=P2^1;    //LCD读写选择位,将RW位定义为P2.1引脚
sbit E=P2^2;     //LCD使能信号位,将E位定义为P2.2引脚
sbit BF=P0^7;    //LCD忙碌标志位,
sbit run=P1^0;   //启动计时按钮检测
unsigned char runing=0; //0非计时运行,1计时运行
sbit h_up=P1^1;   //h+ 按钮检测
sbit h_dn=P1^2;   //h- 按钮检测
sbit set=P1^3;    //pause钮检测
sbit m_up=P1^4;   //分钟+按钮检测
sbit m_dn=P1^5;   //分钟减按钮检测
sbit alarm=P2^7;        ////引脚用于触发音乐IC模块播放音乐

// 延时ms函数////////////////////////
void delayms(unsigned char ms)
{                                                
        unsigned char i;
        while(ms--)
        {
                for(i = 0; i < 120; i++);
        }
}
/////////////////////////////////////


//函数:判断LCD状态,result=1忙碌;result=0就绪
unsigned char BusyTest(void)
  {
    bit result;
        RS=0;    //RS低电平,RW高电平,可读状态
    RW=1;
    E=1;        //允许读写
    _nop_();   
    _nop_();
    _nop_();
    _nop_();   
    result=BF;  //rultes ← LCD状态标志
    E=0;        //恢复低电平
    return result;
  }        /////////////////////////////////////////

//函数:将模式设置指令或显示地址写入LCD ////
void WriteInstruction (unsigned char dictate)
{   
    while(BusyTest()==1); //如果忙就等待
         RS=0;       //RS和R/W同时为低电平时,可以写入指令
         RW=0;   
         E=0;        //准备E从0到1发生正跳变,作为写指令
         _nop_();
         _nop_();    //空操作两个机器周期,给硬件反应时间
         P0=dictate; //将数据送入P0口,即写入指令或地址
         _nop_();
         _nop_();
         _nop_();
         _nop_();   
         E=1;       //E置高电平
         _nop_();
         _nop_();
         _nop_();
         _nop_();   
          E=0;   //当E由高电平跳变成低电平时,LCD开始执行命令
} //////////////////////////////////////////


//函数:指定字符显示的实际地址///////////////
void WriteAddress(unsigned char x)
{
  WriteInstruction(x|0x80); //显示位置地址码
} //////////////////////////////////////////


//函数:将数据字符的ASCII码写入LCD///////////
void WriteData(unsigned char y)
{
    while(BusyTest()==1);  
          RS=1;          //RS为高电平,RW为低电平时,可以写入数据
          RW=0;
          E=0;          //E置低电平(根据表8-6,写指令时,E为高脉冲,
                    //就是让E从0到1发生正跳变,所以应先置"0"
          P0=y;         //将数据送入P0口,即将数据写入液晶模块
          _nop_();
          _nop_();
           _nop_();
     _nop_();       //空操作四个机器周期,给硬件反应时间
          E=1;          //E置高电平
          _nop_();
          _nop_();
          _nop_();
         _nop_();        //空操作四个机器周期,给硬件反应时间
         E=0;      //当E由高电平跳变成低电平时,液晶模块开始执行命令
} /////////////////////////////////////////

//函数:LCD显示模式初始化设置 //////////////
void LcdInitiate(void)
{
     delayms(15);               
   WriteInstruction(0x38);  //显示模式设置:16×2显示,5×7点阵,8位数据接口
     delayms(5);            
   WriteInstruction(0x38);
     delayms(5);
   WriteInstruction(0x38);  //连续三次,确保初始化成功
     delayms(5);
   WriteInstruction(0x0c);  //显示模式设置:显示开,无光标,光标不闪烁
         delayms(5);
   WriteInstruction(0x06);  //显示模式设置:光标右移,字符不移
          delayms(5);
   WriteInstruction(0x01);  //清屏幕指令,将以前的显示内容清除
         delayms(5);
} /////////////////////////////////////////

//函数:显示小时 //////////////////////////                        
void DisplayHour(h)
{
   unsigned char i,j;
        i=h/10;                //取整运算,求得十位数字
        j=h%10;                //取余运算,求得各位数字
   WriteAddress(0x44);   //写显示地址,将十位数字显示在第2行第5列
        WriteData(digit[ i]);  //将十位数字的字符常量写入LCD
        WriteData(digit[j]);  //将个位数字的字符常量写入LCD

} //////////////////////////////////////////////

//函数:显示分钟 ///////////////////////////////                        
void DisplayMinute(m)
{
  unsigned char i,j;
   i=m/10;                //取整运算,求得十位数字
        j=m%10;               //取余运算,求得各位数字
   WriteAddress(0x47);    //写地址,将十位数字显示在第2行第8列
        WriteData(digit[ i]);  //将十位数字的字符常量写入LCD
        WriteData(digit[j]);  //将个位数字的字符常量写入LCD

} //////////////////////////////////////////////

//函数:显示秒 /////////////////////////////////                       
void DisplaySecond(s)
{
   unsigned char i,j;
          i=s/10;               //取整运算,求得十位数字
        j=s%10;               //取余运算,求得各位数字
   WriteAddress(0x4a);    //写地址,将十位数字显示在第2行第11列
        WriteData(digit[ i]);  //将十位数字的字符常量写入LCD
        WriteData(digit[j]);  //将个位数字的字符常量写入LCD
} //////////////////////////////////////////////

[ i][ i][ i] //函数:显示str_1   ///////////////////////[ i][ i][ i]void Display_str_1()  
  {
  WriteAddress(0x01);           //写地址,从第1行第2列开始显示
   i=0;                     //从字符数组的第1个元素开始显示
   while(str_1[ i]!='\0')   //若未到字串结束标志'\0',则显示
    {
     WriteData(str_1[ i]);   //将第i个字符数组元素写入LCD
     i++;                  //数组元素指针+1
    }
   }//////////////////////////////////////////////

[ i][ i][ i][ i][ i]函数:显示str_2 //////////////////////////////
[ i][ i][ i][ i][ i]void Display_str_2()//
  {
   WriteAddress(0x01);           //写地址,从第1行第2列开始显示
   i=0;                     //从字符数组的第1个元素开始显示
   while(str_2[ i]!='\0')   //若未到字串结束标志'\0',则显示
    {
     WriteData(str_2[ i]);   //将第i个字符数组元素写入LCD
     i++;                  //数组元素指针+1
    }
   }//////////////////////////////////////////////


void Display_symbol()        //函数:显示分隔符号////////
  {
   WriteAddress(0x46);     //写地址,第1分号显示在第2行第7列
   WriteData(':');        
   WriteAddress(0x49);     //写地址,第2个分号显示在第2行第10列
   WriteData(':');        
  }        ////////////////////////////////////////////

//主函数///////////////////////////////////////////////
void main(void)
{

  LcdInitiate();  //调用LCD初始化函数
  Display_symbol();
  Display_str_1();

  hh =0;
  mm =0;
  ss =0;
  s=0;                    //秒
  m=0;                    //分钟
  h=0;                    //小时
  TMOD=0x01;              //使用定时器T0的模式1
  TH0=(65536-46083)/256;  //定时器T0的高8位设置初值
  TL0=(65536-46083)%256;  //定时器T0的低8位设置初值
  EA=1;                   //开总中断
  ET0=1;                  //定时器T0中断允许

  while(1)         
   {                                              //while_A

    if (run ==0)                          //按下run按钮
     {                                                  //if_run
      delayms(20);                      //消除按键抖动
          if (run ==0 )                     
       {                                          // if_run-1         
        runing =1;                          // 处于计时运行状态
               Display_str_2();
            TR0=1;                  //启动定时器T0
            count=0;                //Time0计数溢出中断次数
        while(set !=0)
             {                                                // while_B
                  DisplayHour(h);            //显示小时即时值
              delayms(5);           
              DisplayMinute(m);     //显示分钟时值
              delayms(5);
              DisplaySecond(s);     //显示秒时值        
          delayms(5);
              if (h >=hh & m>= mm  )   //当计时达设定值
               {                                                 //if_finish
                TR0=0;         //停止Time0计时
                  //ET0=0;        //关Time0中断
                   DisplayHour(hh);            //显示小时
                delayms(5);           
                DisplayMinute(mm);     //显示分钟
                delayms(5);
                DisplaySecond(ss);     //显示秒        
            delayms(5);   
                alarm = ~alarm;            //P2.7脚由高电平亦低电平,触发音乐IC模块
         
               } // end         if_finish
             } // end  while_B
                 runing =0 ;                         //非计时运行标志
             Display_str_1();
             DisplayHour(hh);             //显示小时设定值
             delayms(5);           
             DisplayMinute(mm);     //显示分钟设定值
             delayms(5);
             DisplaySecond(ss);     //显示秒设定值        
         delayms(5);  
        
           } // end if_run-1
         } // end if_run


  if (h_up==0 )
   {                          
            delayms(20);  //消除按键抖动
         if (h_up==0 &hh<24)
          {                          
           hh++;
           DisplayHour(hh);
       delayms(500);
      }        
   } //end if_2        

  if (h_dn==0 )
   {                        
     delayms(20);
     if (h_dn==0 && hh>0)
      {                        
       hh--;
       DisplayHour(hh);
       delayms(500);           
      }        
        }

  if (m_up==0 )
   {                        
          delayms(20);
    if (m_up==0 && mm<60 )
     {               
      mm++;
          DisplayMinute(mm);
      delayms(500);
     }         
   }  

  if (m_dn==0 )
   {                        
    delayms(20);
    if (m_dn==0 && mm>0)
     {                        
      mm--;
      DisplayMinute(mm);
      delayms(500);           
     }
   }

  }// end  while_A

} // end main() /////////////////////////


//函数:定时器T0的中断服务 ////////////////
void Time0(void ) interrupt 1 using 1
{
   if (runing ==1)
    {
         count++;          //计数溢出中断次数累计
           }
              
        if(count==20)  //计满20次即1秒
         {
      count=0;  //中断累计次数清0                        
          s++;    //秒加1                                 
         }

        if(s==60)   //计满60秒
         {
          s=0;     //秒清0
          m++;     //分钟加1
     }

        if(m==60)    //计满60分钟
         {
          m=0;   //分钟清0
          h++;    //小时加1
           }

        if(h==24)  //计满24小时
         {
          h=0;   //小时清0
         }



         TH0=(65536-46083)/256;  
        TL0=(65536-46083)%256;  
} ///////////////////////////////////////


编程工具:keil Uv4
仿真工具:Proteus8.7
alarm_clock.zip (103.19 KB, 下载次数: 56)    完整的工程文件夹在此压缩包中

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:858964 发表于 2023-10-5 17:17 | 只看该作者

以下是实物外观,  6个橙黄色按钮用于设置定时时间,外壳拆取自别的报废仪器。


回复

使用道具 举报

板凳
ID:1097263 发表于 2023-11-27 15:59 | 只看该作者
好东西,谢谢坛主分享。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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