⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcdclock.c

📁 2004液晶屏与89c52组成的电子钟
💻 C
字号:
/*****************************************************************
20*4LCD液晶屏与DS12c887时钟芯片电子钟v1.10
广州机务段韶关监控所检修组雪狼湖研发
2006/12/19 09:25修改
*****************************************************************/
#include <REG52.h> 
#include <intrins.h>
#include <absacc.h>
/*****************定义LCD寄存器***************************************/
#define LCD_RL  XBYTE[0x1e00]//读指令寄存器
#define LCD_WL  XBYTE[0x1c00]//写指令寄存器
#define LCD_RD  XBYTE[0x1f00]//读数据寄存器
#define LCD_WD  XBYTE[0x1d00]//写数据寄存器
/********************************************************************/
#define  LINE1   1
#define  LINE2   2
#define  LINE3   3
#define  LINE4   4
#define  CLEARSCREEN  LCD_en_command(0x01)//清屏
/*******************************************************************/
#define REG_A  XBYTE[0x800a]//DS12887A寄存器A 
#define REG_B  XBYTE[0x800b]//DS12887A寄存器B
unsigned char code at[8]={9,8,7,6,4,2,0,50};// 年、月、日、星期、时、分、秒、世纪
unsigned char xdata *calendar_address=0x8000;//DS12887片选
unsigned char calendar_time[8];
unsigned char key_s,key_v=0,sect1,sect2;
/*******************************************************************/

void LCD_en_command(unsigned char command);//设置LCD工作状态函数
void LCD_en_dat(unsigned char temp);//写数据函数
void LCD_set_xy( unsigned char x, unsigned char y );//设置LCD显示地址函数
void LCD_write_char( unsigned x,unsigned char y,unsigned char dat);//写字符函数
void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s);//写字符串函数
void LCD_init(void);//初如化LCD函数
void WaitIdle(void);//检测LCD忙则等待函数
/*****************************************************************************/
void Read_calendar(void);//读取系统时间
void Start_calendar(void);//启动时钟
void Display_calendar(void);//显示时间
void Set_calendar(void);//设置系统时间
/*****************************************************************************/
void delayms(unsigned char i);//延时程序
bit scan_key(void);//按键扫描,读取按键状态到key_s
void proc_key(void);//按键主程序
void scan_main_key(void);//按键判断
bit key(void);//返回是否按下键
void set_date();//修改时间日期
/******************************************************************************/
void start_stopt2(bit x);//启动停止定时器2
/******************************************************************************/
void main(void)
{
 LCD_init();
 Start_calendar();
 while(1)    
  {
 Read_calendar();
 Display_calendar();
 scan_main_key();
  }
}

/*********************************************************************/
void LCD_en_command(unsigned char command)//写命令函数
{
WaitIdle();
LCD_WL=command;
}

void LCD_en_dat(unsigned char dat)//写数据函数
{
 WaitIdle();
 LCD_WD=dat;
}

void LCD_set_xy( unsigned char x, unsigned char y )  //设置地址函数
{
 unsigned char address;
 switch(y){
 case 1:
  address = 0x80 + x;break;
 case 2:
  address = 0xc0 + x;break;
 case 3:
  address = 0x94 + x;break;
 case 4:
  address = 0xd4 + x;break;
  }
 LCD_en_command(address); 

}

void LCD_write_char( unsigned x,unsigned char y,unsigned char dat)//写字符函数
{
 LCD_set_xy( x, y ); 
 LCD_en_dat(dat);
}

void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s)//写字符串函数
{
    LCD_set_xy( X, Y ); //写地址 
    while (*s)  // 写显示字符
    {
 LCD_en_dat(*s);   
 s ++;
    }
}

void LCD_init(void)//初始化子函数
{ 
 CLEARSCREEN;//清屏
 LCD_en_command(0x38);//设置8位串数据格式
 LCD_en_command(0x0c);//开显示器
 CLEARSCREEN;//清屏
}

void WaitIdle(void)//检测LCD忙则等待
{ 
unsigned char tmp;
_nop_();
while(1)
  { tmp=LCD_RL;
    tmp&=0x80;
    if(tmp==0)
    break;
  }
}
/**************************************************************/
void Display_calendar(void)//显示时间
{LCD_write_string(0x04,LINE1,"GZJWD_SG_JKS");
 LCD_write_char(0x05,LINE2,(calendar_time[7]/10)|0x30);//世纪十位
 LCD_write_char(0x06,LINE2,(calendar_time[7]%10)|0x30);//世纪个位
 LCD_write_char(0x07,LINE2,(calendar_time[0]/10)|0x30);//年十位
 LCD_write_char(0x08,LINE2,(calendar_time[0]%10)|0x30);//年个位
 LCD_write_string(0x09,LINE2,"/");
 LCD_write_char(0x0a,LINE2,(calendar_time[1]/10)|0x30);//月十位
 LCD_write_char(0x0b,LINE2,(calendar_time[1]%10)|0x30);//月个位
 LCD_write_string(0x0c,LINE2,"/");
 LCD_write_char(0x0d,LINE2,(calendar_time[2]/10)|0x30);//日十位
 LCD_write_char(0x0e,LINE2,(calendar_time[2]%10)|0x30);//日个位
 if(calendar_time[3]==1)
 {
  LCD_write_string(0x07,LINE3,"Mon_");
  LCD_write_char(0x0b,LINE3,(calendar_time[3]%10)|0x30);//星期
 }
 if(calendar_time[3]==2)
 {
  LCD_write_string(0x07,LINE3,"Tue_");
  LCD_write_char(0x0b,LINE3,(calendar_time[3]%10)|0x30);//星期
 }
 if(calendar_time[3]==3)
 {
  LCD_write_string(0x07,LINE3,"Wen_");
  LCD_write_char(0x0b,LINE3,(calendar_time[3]%10)|0x30);//星期
 }
 if(calendar_time[3]==4)
 {
  LCD_write_string(0x07,LINE3,"Thu_");
  LCD_write_char(0x0b,LINE3,(calendar_time[3]%10)|0x30);//星期
 }
 if(calendar_time[3]==5)
 {
  LCD_write_string(0x07,LINE3,"Fri_");
  LCD_write_char(0x0b,LINE3,(calendar_time[3]%10)|0x30);//星期
 }
 if(calendar_time[3]==6)
 {
  LCD_write_string(0x07,LINE3,"Sat_");
  LCD_write_char(0x0b,LINE3,(calendar_time[3]%10)|0x30);//星期
 }
 if(calendar_time[3]==7)
 {
  LCD_write_string(0x07,LINE3,"Sun_");
  LCD_write_char(0x0b,LINE3,(calendar_time[3]%10)|0x30);//星期
 }
 LCD_write_char(0x06,LINE4,(calendar_time[4]/10)|0x30);//小时十位
 LCD_write_char(0x07,LINE4,(calendar_time[4]%10)|0x30);//小时个位
 LCD_write_string(0x08,LINE4,":"); 
 LCD_write_char(0x09,LINE4,(calendar_time[5]/10)|0x30);//分钟十位
 LCD_write_char(0x0a,LINE4,(calendar_time[5]%10)|0x30);//分钟个位
 LCD_write_string(0x0b,LINE4,":"); 
 LCD_write_char(0x0c,LINE4,(calendar_time[6]/10)|0x30);//秒十位
 LCD_write_char(0x0d,LINE4,(calendar_time[6]%10)|0x30);//秒个位
}

void Set_calendar(void) //设置系统时间
{
 unsigned char i;
 REG_B=0x80; 
 for(i=0;i<8;i++)
 *(calendar_address+at[i])=calendar_time[i];
 Start_calendar();
}

void Start_calendar(void) //启动时钟
{
  REG_A=0x20;//晶体振荡器开启并保存时钟运行
  REG_B=0x06;//24小时制,hex输出
}

void Read_calendar(void) //读取系统时间
{
 unsigned char temp,i;
  REG_B=0x06;//24小时制,hex输出
  do{ temp=REG_A;} 
  while(temp&0x80);
  for(i=0;i<8;i++)
  calendar_time[i]=*(calendar_address+at[i]);    
}

void set_int12887(void)//初始化时钟
{
unsigned char i;
unsigned char calendar[]={06,12,19,2,16,30,30,20};
for(i=0;i<8;i++)
calendar_time[i]=calendar[i];
Set_calendar();
}
/*************************************************************************/
void scan_main_key(void)//按键判断
{
if(scan_key())    //调用按键扫描,读取按键的状态,如果有按键变化,则delay 10ms去抖动
    { delayms(10) ;//去抖动
       if(scan_key())//再扫描,如果仍然有键,才进入按键处理
          {key_v = key_s ;//保存按键状态
           proc_key() ;//按键处理
          }
     }
}

bit key(void)//返回是否按下键
{
if(scan_key())    //调用按键扫描,读取按键的状态,如果有按键变化,则delay 10ms去抖动
    { delayms(10) ;//去抖动
       if(scan_key())//再扫描,如果仍然有键,才进入按键处理
          {key_v = key_s ;//保存按键状态
           return 1;//确定有键按下返回1
          }
     }
}

bit scan_key(void)//按键扫描,读取按键状态到key_s
{
 key_s =(~P1)&0x1F;
 return(key_s ^ key_v) ; //如果新旧状态不一样,则返回1,表示有按键变化。否则返回0
}

void proc_key(void)//按键主程序
{
 switch(key_v)
   {
 case 0x01:// ok键
  set_date();
  break;
 case 0x02:// <-键
  break;
 case 0x04:// ->键
  break;
 case 0x08:// + 键
  break;
 case 0x10:// - 键
  break;
 case 0x18:
  set_int12887();
  break;
 default:
  break;
   }
}

void delayms(unsigned char i)//延时程序
{
unsigned char j;
for(;i>0;i--)
for(j=0;j++;j<250);
}

void set_date(void)
{unsigned char address[]={0xc8,0xcb,0xce,0x9f,0xdb,0xde,0xe1};
 unsigned char i=4;
  while(1)
  {
  LCD_en_command(address[i]); //写地址 
  LCD_en_command(0x0f);//开显示器,光标闪烁
  if(key())
   {if(key_v==0x08)   //按下+键
    calendar_time[i]++;
    if(key_v==0x10)  //按下-键
	calendar_time[i]--;

	if(calendar_time[0]==100)
	{calendar_time[0]=0;calendar_time[7]++;}
	if(calendar_time[0]==255)
	{calendar_time[0]=99;calendar_time[7]--;}
	if(calendar_time[1]==13)
	calendar_time[1]=1;
	if(calendar_time[1]==0)
	calendar_time[1]=12;
	if(calendar_time[2]==32)
	calendar_time[2]=1;
	if(calendar_time[2]==0)
	calendar_time[2]=31;
	if(calendar_time[4]==24)
	calendar_time[4]=0;
   if(calendar_time[4]==255)
	calendar_time[4]=23;
	if(calendar_time[5]==60)
	calendar_time[5]=0;
	if(calendar_time[5]==255)
	calendar_time[5]=59;
	if(calendar_time[6]==60)
	calendar_time[6]=0;
	if(calendar_time[6]==255)
	calendar_time[6]=59;
	if(calendar_time[3]==8)
	calendar_time[3]=1;
	if(calendar_time[3]==0)
	calendar_time[3]=7;

   if(key_v==0x04)//按下->键
   i++;
	if(key_v==0x02)//按下<-键
	i--;
	if(i==255)i=6;
	if(i==7)i=0;
    if(key_v==0x01)//按下确认键
	  {Set_calendar();//设置日期
	   LCD_en_command(0x0c);//开显示器,取消光标闪烁
	   break;
	  }
	  Display_calendar();//显示时间
    }
   }
}

/**************************************************************************************/
timer2() interrupt 5//溢出一次50ms
{
  static unsigned char t;
  TF2=0;//清溢出标志
  t++;
  if(t==20)//20约一秒
  {t=0;sect1++;}
}
void start_stopt2(bit x)//启动停止定时器2
{
 RCAP2H=0x50;
 RCAP2L=0x00;
 TR2=x;
 ET2=x;
 EA=x;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -