#include<reg51.h>
#include<stdio.h>
//定义定时器0 的重装值
#define RELOAD_HIGH 0x3C
#define RELOAD_LOW 0xD2
//定义按键弹跳时间
#define DB_VAL
//定义设置模式的最大时间间隔
#define TIMEOUT 200
//定义光标位置常数
#define HOME 0
#define HOUR 1
#define MIN 2
#define SEC 3
//定义光标状态常数
#define OFF 0
#define ON 1
//定义显示命令常数
#define DISP_BUSY 0x80
#define DISP_FUNC 0x38
#define DISP_ENTRY 0x06
#define DISP_CNTL 0x08
#define DISP_ON 0x04
#define DISP_CURSOR 0x02
#define DISP_CLEAR 0x01
#define DISP_HOME 0x02
#define DISP_POS 0x80
#define DISP_LINE2 0x40
sbit SET=P3^4; //设置按键输入
sbit SELECT=P3^5; //选择按键输入
sbit ENABLE=P3^1; //显示使能输出
sbit REGSEL=P3^7; //显示寄存器选择输出
sbit RDWR=P3^6; //显示模式输出
sfr DISPDATA=0x90; //显示8 位数据总线
typedef struct { //定义存储每日时间的结构
unsigned char hour,min,sec;
}timestruct;
bit set_mode=0; //进入设置模式时置位
disp_updata=0; //需要刷新显示时置位
unsigned char set_mode_to=0; //为每次按键操作的时间间隔计时
switch_debounce=0; //按键跳动计时
cur_field=HOME; //设置模式的当前位置选择
timestruct curtime; //存放当前的时间
timeholder; //存放显示时间
unsigned char code fieldpos[3]={
DISP_LINE2|0x01,
DISP_LINE2|0x04,
DISP_LINE2|0x07,
};
#define T_HOURT 16
#define T_HOUR 17
#define T_MINT 19
#define T_MIN 20
#define T_SECT 22
#define T_SEC 23
char code bcdmap[60][2]={
"“00"”,"”0"1”,"”0"2”",”0"3”",”"04”",”"05"”,"”06"”,"”07"”,"”0"8”",”09”,
"“10"”,"”1"1”,”12”,”13”,”14”,”15”,”16”,”17”,”18”,”19”,
“20”,”21”,”22”,”23”,”24”,”25”,”26”,”27”,”28”,”29”,
“30”,”31”,”32”,”33”,”34”,”35”,”36”,”37”,”38”,”39”,
“40”,“41”,”42”,”43”,”44”,”45”,”46”,”47”,”48”,”49”,
“50”,”51”,”52”,”53”,”54”,”55”,”56”,”57”,”58”,”59”,
};
//函数声明
void disp_cmd(unsigned char);
void disp_init(void);
unsigned char disp_read(void);
void disp_time(void);
void disp_write(unsigned char);
void incr_field(void);
void second_tick(void);
void set_cursor(bit,unsigned char);
/*****************************************************
功能:主函数
描述:程序入口函数,初始化8051,开中断,进入空闲模式每次中断之后查询标
志位是否刷新显示
参数无
返回无
*****************************************************/
void main(void)
{
disp_init(); //显示初始化
TMOD=0x11; //设置定时器模式
TCON=0x15;
IE=0x82;
for(;;){广州周立功单片机发展
if (disp_updata){
disp_time( );
} //显示新时间
PCON=0x01;
}
}
/**************************************************
功能disp_cmd
描述向lcd 驱动器写入命令并等待命令被执行
参数命令
返回无
*************************************************/
void disp_cmd(unsigned char cmd){
DISPDATA=cmd; //锁住命令
REGSEL=0; //选择命令寄存器
RDWR=0; //选择写模式
ENABLE=1;
ENABLE=0;
TH1=0; //定时85ms
TL1=0;
TF1=0;
TR1=1;
while(!TF1&&disp_read()&DISP_BUSY); //等待命令被执行
TR1=0;
}
/****************************************************
功能:disp_init
描述:初始化显示
参数:无
返回:无
****************************************************/
void disp_init(void){
TH1=0;
TL1=0;
TF1=0;
TR1=1;
while (!TF1&&disp_read()&DISP_BUSY);
TR1=0;
disp_cmd(DISP_FUNC); //设置显示格式
disp_cmd(DISP_ENTRY); //每输入一个字符,显示地址加1
disp_cmd(DISP_CNTL|DISP_ON); //打开显示,关闭光标
disp_cmd(DISP_CLEAR); //清除显示广州周立功单片机发展
}
/*******************************************************
功能:disp_read
描述:读显示状态寄存器
参数:无
返回:从状态寄存器中读回的数据
*********************************************************/
unsigned char disp_read(void){
unsigned char value;
DISPDATA=0XFF;
REGSEL=0; //选择命令寄存器
RDWR=1; //选择读模式
ENABLE=1; //使能LCD 输出
value=DISPDATA; //读数据
ENABLE=0;
retrun(value);
}
/**********************************************************
功能:disp_time
描述:取显示数据进行格式化
参数:无
返回:无
******************************************************/
void disp_time(void){
static char time_str[32]= “TIME OF DAY IS:XX:XX:XX ”;
unsigned char I;
time_str[T_HOURT]=bcdmap[timeholder.hour][0];
time_str[T_HOUR]=bcdmap[timeholder.hour][1];
time_str[T_MINT]=bcdmap[timeholder.min][0];
time_str[T_MIN]=bcdmap[timeholder.min][1];
time_str[T_SECT]=bcdmap[timeholder.sec][0];
time_str[T_SEC]=bcdmap[timeholder.sec][1];
putchar(0xFF);
for(i=0;i<32;i++){
putchar(time_str[i]);
}
disp_updata=0;
}
/***************************************************
功能:disp_write
广州周立功单片机发展有限公司 Tel 020 38730916 38730917 38730976 38730977 Fax:38730925
54
描述:写入一个字节数据
参数:要写入的字节
返回:无
****************************************************/
void disp_write(unsigned char value){
DISPDATA=value;
REGSEL=1;
RDWR=0;
ENABLE=1;
ENABLE=0;
}
/*************************************************
功能:incr_field
描述:增加数值
参数:无
返回:无
**********************************************/
void incr_field(void){
if (cur_field= =SEC){
curtime.sec++;
if(curtime.sec>59){
curtime.sec=0;
}
}
if (cur_field= =MIN){
curtime.min++;
if(curtime.min>59){
curtime.min=0;
}
}
if (cur_field= =HOUR){
curtime.hour++;
if(curtime.hour>23){
curtime.hour=0;
}
}
}
/***********************************************************
功能:putchar
描述:替代标准putchar 函数,输出字符
参数:要显示的字符
返回:刚刚被写的字符
************************************************************/
广州周立功单片机发
char putchar(char c){
static unsigned char flag=0;
if(!flag||c= =255){
disp_cmd(DISP_HOME);
flag=0;
if(c= =255){
return c;
}
}
if(flag= =16){
disp_cmd(DISP_POS|DISP_LINE2);
}
disp_write(c);
while(disp_read( )&DISP_BUSY);
flag++;
if (flag>=32){flag=0};
return(c);
}
/*************************************************************
功能:second_tick
描述:每秒钟执行一次函数功能,时间更新
参数:无
返回:无
*************************************************************/
void second_tick(void){
curtime.sec++; //秒种加1
if (curtime.sec>59){ //检测是否超出范围
curtime.sec=0;
crutime.min++; //分钟加1
if (curtime.min>59){ //检测是否超出范围
curtime.min=0;
curtime.hour++; //小时数加1
if(curtime.hour>23){ //检测是否超出范围
curtime.hour=0;
}
}
}
if(!disp_updata){ //确信timeholder 没有被显示
timeholder=curtime; //装入新时间
disp_updata=1; //更新显示
}
}
广州周立功单片机
/***************************************************
功能;set_cursor
描述:显示或关闭光标,并把光标移到特定的位置
参数:new_mode 位,隐藏光标时置位
field 显示光标的位置
返回:无
***************************************************/
void set_cursor(bit new_mode,unsigned char field){
unsigned char mask;
mask=DISP_CNTL|DISP_ON;
if(new_mode){
mask|=DISP_CURSOR;
}
disp_cmd(mask);
if (field= =HOME){
mask=DISP_HOME;
}else{
mask=DISP_POS|fieldpos[field-1];
}
disp_cmd(mask);
}
/*******************************************************
功能: system_tick
描述:定时器0 的中断服务程序,每50ms 重装一次定时器
参数:无
返回:无
*******************************************************/
void system_tick(void) interrupt1{
static unsigned char second_cnt=20;
TR0=0;
TH0=RELOAD_HIGH; //设定重装值
TL0=RELOAD_LOW;
TR0=1; //开始定时
if(switch_debounce){ //按键抖动
switch_debounce--;
}
if (!switch_debounce){
if(!SET){ //如果设置按钮被按下
switch_debounce=DB_VAL; //设置消抖时间
if(!set_mode&&!disp_updata){ //如果不是设置模式
set_mode=1; //进入设置模式
set_mode_to=TIMEOUT; //设置空闲时间
cur_field=HOUR; //选择光标起始位置
广州周立功单片机发
set_cursor(ON,HOUR); //使能光标
}else{
cur_field++; //光标位置前进
if(cur_field>SEC){ //光标是否超出范围
set_mode=0; //退出设置模式
set_mode_to=0;
set_cursor(OFF,HOME); //禁能光标
}else{
set_cursor(ON,cur_field); //光标移到下一个位置
set_mode_to=TIMEOUT;
}
}
}
if(set_mode&&!SELECT){ //如果按下选择按钮
set_mode_to=TIMEOUT;
incr_field( ); //所选择处数值增加
disp_time( ); //显示时间
}
}
if(!set_mode){ //设置模式停止时钟
second_cnt- -; //计数值减1
if(!second_cnt){ //如果经过1 秒
second_cnt=20; //设置计数值
second_tick( );
}
}
} |