标题:
20*4LCD液晶屏与DS12c887时钟芯片电子钟v1.10
[打印本页]
作者:
daniu
时间:
2014-12-26 21:07
标题:
20*4LCD液晶屏与DS12c887时钟芯片电子钟v1.10
/*****************************************************************
20*4LCD液晶屏与DS12c887时钟芯片电子钟v1.10
*****************************************************************/
#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;
}
复制代码
作者:
daniu
时间:
2014-12-26 21:09
/*****************************************************************
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;
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1