1602時鐘(郭天祥老師板子配套)

根據郭老師1602時鐘的學習視頻進行的完善,是一個可以顯示年月日,時分秒星期的例子。

/*
根據郭老師視頻,寫的可以調節年月日星期時分秒的例子。
在郭老師的學習板中,s13鍵用來進行選定按鍵
s17用來進行加1,s21用來減一。
*/
#include<reg52.h>
#include<string.h>
#include<math.h>

#define uchar unsigned char
#define uint unsigned int


#define DATA P0  //八位並行數據接口


sbit DULA=P2^6; 
sbit WELA=P2^7;  //數碼管的位選和段選關閉
sbit RS=P3^5;      
//sbit RW=P3^6;
sbit E=P3^4;
sbit RDD=P3^7;//將此置爲0,則矩陣鍵盤變爲獨立按鍵
uchar code table1[]="2012-11-14 SUN";
uchar code table2[]="23:59:55";
uchar code week_table[]={0x53,0x55,0x4e,0x4d,0x4f,0x4e,0x54,0x55,0x45,0x57,0x45,0x44,0x54,0x48,0x55,
0x46,0x52,0x49,0x53,0x41,0x54}; //週日到週六的編碼
uchar code month1[]={1,3,5,7,8,10,12};
uchar code month2[]={4,6,9,11};
uint n1;//計算table1長度
uint n2;//計算table2長度
uchar count=0;//定時1秒所用
uchar hour=23,min=59,sec=55;
int year=2012;
uchar year_l=20,year_r=12,month=11,day=14,week=0;
sbit key1=P3^1; //用來選中哪個項目進行加減
sbit key2=P3^2; //用來加1
sbit key3=P3^3; //用來減1
uchar num;
void delay(uint x)
{
uint i;
while(x--){
for(i=0;i<60;i++);
}
}
/*
函數作用:液晶寫控制指令函數
輸入:空
輸出:空
*/
void write_ctrl(uchar ctrl)
{
//RW=0;
RS=0;
E=0;
DATA=ctrl;
delay(5);
E=1;
delay(5);
E=0;
}
/*
函數作用:液晶寫數據函數
輸入:空
返回值:空
*/
void write_data(uchar da)
{
// RW=0;
RS=1;
E=0;
DATA=da;
delay(5);
E=1;
delay(5);
E=0;

}
/*
函數作用:初始化。包括禁止數碼管顯示(鎖存器控制端置低);液晶初始化設置;
液晶初始化顯示設置;定時器初始化
輸入:空
返回值:空
*/
void init()
{
uchar i;
DULA=0;
WELA=0;
RDD=0;
E=0;
write_ctrl(0x06);//光標移動
write_ctrl(0x0c);//不顯示光標
write_ctrl(0x38);//兩行,5*7


n1=strlen(table1);
n2=strlen(table2);
write_ctrl(0x80);
for(i=0;i<n1;i++){
write_data(table1[i]);
delay(1);
}
write_ctrl(0x80+0x40);
for(i=0;i<n2;i++){
write_data(table2[i]);
delay(1);
}
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;//定時50ms
EA=1;
ET0=1;
TR0=1;
}
/*
函數作用:寫時分秒函數,即向指定的地址寫入時、分或是秒。
輸入:第一個參數add是指從哪個地址開始寫,第二個參數da指要寫的數據
返回值:空
*/
void write_sfm(uchar add,uchar da)
{
uchar shi,ge;
shi=da/10;
ge=da%10;
write_ctrl(0x80+0x40+add);//從0x80+0x40+addr這個地址開始寫,即秒的十位
write_data(0x30+shi); //先寫十位
write_data(0x30+ge);//再寫個位
}
/*
函數作用:寫年月日函數,與write_sfm不同的是寫入的地址不一樣
輸入:第一個參數add是指從哪個地方寫,第二個參數da指要寫的數據
返回值:空。
*/
void write_nyr(uchar add,uchar da)
{
uchar shi,ge;
shi=da/10;
ge=da%10;
write_ctrl(0x80+add);//從0x80+addr這個地址開始寫,即十位
write_data(0x30+shi); //先寫十位
write_data(0x30+ge);//再寫個位
}
/*
函數作用:掃描鍵盤函數,檢查是否有按鍵按下
輸入:空
返回值:空
*/
void keyscan()
{
uchar k=0;
if(key1==0){
num=(num+1)%9;
delay(5);//消抖
if(key1==0){
if(num==1){ //第一次摁,則停在秒
while(key1==0);//鬆手檢測
TR0=0;//不再計時
write_ctrl(0x80+0x40+7);//光標移動指定位置,此處爲秒的個位
write_ctrl(0x0f); //光標閃爍

}
if(num==2){//第二次,則停在分
while(key1==0);
TR0=0;
write_ctrl(0x80+0x40+4);
write_ctrl(0x0f);
}
if(num==3){//第三次,停在時
while(key1==0);
TR0=0;
write_ctrl(0x80+0x40+1);
write_ctrl(0x0f);
}
if(num==4){ //停在星期
while(key1==0);
TR0=0;
write_ctrl(0x80+0x0d);
write_ctrl(0x0f);
}
if(num==5){//停在天
while(key1==0);
TR0=0;
write_ctrl(0x80+0x09);
write_ctrl(0x0f);
}
if(num==6){ //停在月
while(key1==0);
TR0=0;
write_ctrl(0x80+0x06);
write_ctrl(0x0f);
}
if(num==7){//停在年,將年分成兩部分,十個位和千百位
while(key1==0);
TR0=0;
write_ctrl(0x80+0x03);
write_ctrl(0x0f);
}
if(num==8){//年的千百位
while(key1==0);
TR0=0;
write_ctrl(0x80+0x01);
write_ctrl(0x0f);
}
if(num==0){ //第四次摁,繼續計數
while(key1==0);
write_ctrl(0x0c);
TR0=1; //重新計時
}
}
}
//檢測key2鍵是否被按下,即進行加1運算
if(num!=0){ //此處要放到和檢測key1的if語句平行的位置
if(num==1){   //秒
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
sec=sec+1;
if(sec==60){
sec=0;
}
write_sfm(6,sec);
write_ctrl(0x80+0x40+7);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==2){ //分
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
min=min+1;
if(min==60){
min=0;
}
write_sfm(3,min);
write_ctrl(0x80+0x40+4);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==3){  //小時
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
hour=hour+1;
if(hour==24){
hour=0;
}
write_sfm(0,hour);
write_ctrl(0x80+0x40+1);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==4){  //星期
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
week=week+1; 
if(week==7){
week=0;
}
write_ctrl(0x80+0x0b);
for(k=0;k<3;k++){
write_data(week_table[week*3+k]); 
} //採用兩層循環,這樣就可以每次week加1,來顯示三個字母。
write_ctrl(0x80+0x0d);
}
}
}
if(num==5){   //天
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
day=day+1;
if(day==32){
day=1;
}
write_nyr(8,day);
write_ctrl(0x80+9);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==6){   //月
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
month=month+1;
if(month==13){
month=1;
}
write_nyr(5,month);
write_ctrl(0x80+6);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==7){ //把年分成了兩半
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
year_r=year_r+1;
if(year_r==100){
year_r=0;
}
write_nyr(2,year_r);
write_ctrl(0x80+3);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==8){
if(key2==0){
delay(5);
if(key2==0){
while(key2==0);
year_l=year_l+1;
if(year_l==100){
year_l=0;
}
write_nyr(0,year_l);
write_ctrl(0x80+1);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
}
//減1操作
if(num!=0){ //此處要放到和檢測key1的if語句平行的位置
if(num==1){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
sec=sec-1;
if(sec==-1){
sec=59;
}
write_sfm(6,sec);
write_ctrl(0x80+0x40+7);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==2){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
min=min-1;
if(min==-1){
min=59;
}
write_sfm(3,min);
write_ctrl(0x80+0x40+4);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==3){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
hour=hour-1;
if(hour==-1){
hour=23;
}
write_sfm(0,hour);
write_ctrl(0x80+0x40+1);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==4){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
week=week-1;
if(week==-1){
week=6;
}
//week=week%7;
write_ctrl(0x80+0x0b);
for(k=0;k<3;k++){
write_data(week_table[week*3+k]);
}
write_ctrl(0x80+0x0d);
}
}
}
if(num==5){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
day=day-1;
if(day==-1){
day=31;
}
write_nyr(8,day);
write_ctrl(0x80+9);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==6){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
month=month-1;
if(month==-1){
month=12;
}
write_nyr(5,month);
write_ctrl(0x80+6);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==7){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
year_r=year_r-1;
if(year_r==-1){
year_r=99;
}
write_nyr(2,year_r);
write_ctrl(0x80+3);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
if(num==8){
if(key3==0){
delay(5);
if(key3==0){
while(key3==0);
year_r=year_r-1;
if(year_r==-1){
year_r=99;
}
write_nyr(2,year_r);
write_ctrl(0x80+3);//因爲寫完以後,光標會向右移一個位置
//所以此句把光標左移
}
}
}
}
}
void main()
{
uchar i;
uchar j;
init();
while(1){
keyscan();
if(count==20){
count=0;
sec++;
if(sec==60){
sec=0;
min++;
if(min==60){
min=0;
hour++;
if(hour==24){
hour=0;
day++;
week=(week+1)%7;
write_ctrl(0x80+0x0b);
for(j=0;j<3;j++){
write_data(week_table[week*3+j]);
//write_ctrl(0x06);
}

//閏年2月28天的計算
if(((year%4==0)&&(year%100!=0))||(year%400==0)){
if(month==2){
if(day==29){
day=1;
month++;
}
else {
write_nyr(8,day);
}
write_nyr(8,day);
write_nyr(5,month);
}
}
if(!(((year%4==0)&&(year%100!=0))||(year%400==0))){
if(month==2){
if(day==30){
day=1;
month++;
}
else {
write_nyr(8,day);
}
write_nyr(8,day);
write_nyr(5,month);
}
}
//月份爲31天的  


for(i=0;i<7;i++){
if(month==month1[i]){
if(day==32){
day=1;
month++;
if(month==13){
month=1;
year_r++;
year++;
if(year_r==100){
year_r=0;
year_l++;
}
write_nyr(0,year_l);
}
write_nyr(2,year_r);
//break;
}
write_nyr(5,month);
}

}
write_nyr(8,day);
//以下爲月份數數是30天的
for(i=0;i<4;i++){
if(month==month1[i]){
if(day==31){
day=1;
month++;
if(month==13){
month=1;
year_r++;
year++;
if(year_r==100){
year_r=0;
year_l++;
}
write_nyr(0,year_l);
}
write_nyr(2,year_r);
//break;
}
write_nyr(5,month);
}

}
write_nyr(8,day);

}
write_sfm(0,hour);//此語句應該放在sec==60,然後清零後面,否則則會出現sec=60的現象
}
write_sfm(3,min);
}
write_sfm(6,sec);
}
}
}
//定時器0
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章