1 #include<reg52.h>//單片機頭文件 2 #define uchar unsigned char//宏定義,用uchar表示unsigned char,叫無符號字符型數據類型,取值范圍為:0到255。 3 #define uint unsigned int//宏定義,用uint表示unsigned int,叫無符號整數型數據類型,取值范圍為:0到65535。 4 sbit RS=P0^7;//位定義LCD1602字符型液晶顯示器的數據/命令選擇引腳 5 sbit RW=P0^6;//位定義LCD1602字符型液晶顯示器的讀寫引腳 6 sbit EN=P0^5; //位定義LCD1602字符型液晶顯示器的使能引腳 7 sbit S1=P3^5;//移位按鍵S1 8 sbit S2=P3^4;//增加按鍵S2 9 sbit S3=P3^3;//減少按鍵S3 10 sbit S4=P3^2;//啟停按鍵S4 11 uchar count,S1num,S4num;//count為定時器0中斷次數變量,S1num為移位按鍵S1按鍵按下次數變量,S4num為啟停按鍵S4按下次數變量。 12 uchar shi,fen,miao;//未做時間修改的計時時鍾、分鍾、秒鍾變量 13 uchar secondge,secondshi; //秒鍾個位、十位的變量 14 uchar minutange,minutanshi;//分鍾個位、十位的變量 15 uchar hourge,hourshi;//時鍾個位、十位的變量 16 uchar table0[]="2019-11-11";//LCD1602第一行初始顯示 17 uchar table1[]="00:00:00";//LCD1602第二行初始顯示 18 void Delay(uint z)//延時程序 19 { 20 uint x,y; 21 for(x=z;x>0;x--) 22 for(y=110;y>0;y--); 23 } 24 void WriteCommand(uchar command)//LCD1602字符型液晶顯示器寫指令函數 25 { 26 RS=0;//LCD1602字符型液晶顯示器指令寄存器低電平 27 RW=0;//LCD1602字符型液晶顯示器寫指令操作低電平 28 P2=command;//LCD1602字符型液晶顯示器寫指令函數寫指令到單片機P2組端口,再輸送到LCD1602字符型液晶顯示器指令寄存器中執行。 29 Delay(5);//實際單片機演示,可以去掉延時。Proteus 仿真,需要保留延時。 30 EN=1;//LCD1602字符型液晶顯示器使能端高電平 31 Delay(5);//實際單片機演示,可以去掉延時。Proteus 仿真,需要保留延時。 32 EN=0;//LCD1602字符型液晶顯示器使能端低電平 33 } 34 void WriteData(uchar information)//LCD1602字符型液晶顯示器寫數據函數 35 { 36 RS=1;//LCD1602字符型液晶顯示器數據寄存器高電平 37 RW=0;//LCD1602字符型液晶顯示器寫數據操作低電平 38 P2=information;//LCD1602字符型液晶顯示器寫數據函數寫數據到單片機P2組端口,再輸送到LCD1602字符型液晶顯示器上顯示。 39 Delay(5);//實際單片機演示,可以去掉延時。Proteus 仿真,需要保留延時。 40 EN=1;//LCD1602字符型液晶顯示器使能端高電平 41 Delay(5);//實際單片機演示,可以去掉延時。Proteus 仿真,需要保留延時。 42 EN=0;//LCD1602字符型液晶顯示器使能端低電平 43 } 44 void LCD1602Init()//LCD1602初始化函數 45 { 46 WriteCommand(0x38);//設置LCD1602字符型液晶顯示器16x2顯示,5*7或5*8點陣,8位數據並口,簡稱顯模。 47 WriteCommand(0x08);//設置LCD1602字符型液晶顯示器顯示開,簡稱亮屏。 48 WriteCommand(0x01);//設置清除LCD1602字符型液晶顯示器屏上所有內容,並讓光標復位到LCD1602字符型液晶顯示器屏左上角,簡稱清屏。 49 WriteCommand(0x06);//設置開光標(或字符)地址指針自增1,光標右移動一個字符位,整屏顯示不移動。 50 WriteCommand(0x0c);//設置開LCD1602字符型液晶顯示器顯示,關光標,關光標(字符)閃爍。 51 } 52 void Timer0Init()//定時器0初始化函數 53 { 54 TMOD=0x01;//設定定時器0工作模式為模式1 55 TH0=(65536-50000)/256;//TH0裝初值 56 TL0=(65536-50000)%256;//TL0裝初值 57 EA=1;//開啟定時器總中斷 58 ET0=1;//開啟定時器0中斷開關 59 TR0=1;//啟動定時器0 60 } 61 void LCD1602Display()//LCD1602字符型液晶顯示器顯示函數 62 { 63 uchar j;//j表示數組元素個數變量 64 WriteCommand(0x80+0x00);//LCD1602字符型液晶顯示器第一行第一個位置顯示 65 for(j=0;j<10;j++)//有10個字符,要循環10次。 66 { 67 WriteData(table0[j]);//顯示字符串 68 Delay(5); 69 } 70 WriteCommand(0x80+0x40);//LCD1602字符型液晶顯示器第二行第一個位置顯示 71 for(j=0;j<8;j++)//有8個字符,要循環8次。 72 { 73 WriteData(table1[j]);//顯示字符串 74 Delay(5); 75 } 76 } 77 void LCD1602DisplayTime(uchar address,uchar num)//LCD1602顯示時間兩位數分解函數 78 { 79 uchar shi,ge;//十位、個位的變量 80 shi=num/10;//十位數 81 ge=num%10;//個位數 82 WriteCommand(0x80+0x40+address);//LCD1602字符型液晶顯示器第二行某個顯示位 83 WriteData(0x30+shi);//0x30表示字符庫的數字0,整個代碼表示十位可顯示0到9的數字。 84 WriteData(0x30+ge);//0x30表示字符庫的數字0,整個代碼表示個位可顯示0到9的數字。 85 } 86 void LCD1602DisplayGeDigitResolve(uchar address,uchar num)//LCD1602字符型液晶顯示器顯示修改時間個位數分解函數 87 { 88 uchar ge;//個位的變量 89 ge=num%10;//個位數 90 WriteCommand(0x80+0x40+address);//LCD1602字符型液晶顯示器第二行某個顯示位 91 WriteData(0x30+ge);//0x30表示字符庫的數字0,整個代碼表示個位可顯示0到9的數字。 92 } 93 void LCD1602DisplayShiDigitResolve(uchar address,uchar num)//LCD1602字符型液晶顯示器修改時間十位數分解函數 94 { 95 uchar shi;//十位變量 96 shi=num%10;//十位數 97 WriteCommand(0x80+0x40+address);//LCD1602字符型液晶顯示器第二行某個顯示位 98 WriteData(0x30+shi);//0x30表示字符庫的數字0,整個代碼表示十位可顯示0到9的數字。 99 } 100 void KeyScan()//按鍵掃描函數 101 { 102 if(S1==0)//判斷移位按鍵S1是否按下 103 { 104 Delay(5); 105 if(S1==0)//再次判斷移位按鍵S1是否按下 106 { 107 S1num++;//移位按鍵S1按鍵次數變量先賦值再自加 108 while(!S1);//等待移位按鍵S1彈起 109 switch(S1num) 110 { 111 case 1: 112 TR0=0;//關定時器0 113 S4num=0;//啟停按鍵S4按下次數清零 114 secondge=miao%10;//關掉定時器0定時后,把秒鍾計時時間數值取余賦給秒鍾個位顯示位。 115 secondshi=miao/10;//關掉定時器0定時后,把秒鍾計時時間數值取除賦給秒鍾十位顯示位。 116 WriteCommand(0x80+0x40+0x07);//LCD1602字符型液晶顯示器第二行第8個位置的顯示位 117 WriteCommand(0x0f);//開LCD1602字符型液晶顯示器顯示,開光標,開光標(或字符)閃爍。 118 break; 119 case 2: 120 secondshi=secondshi;//關掉定時器0定時后,把秒鍾計時時間數值取除后得到的值再賦給秒鍾十位顯示位。 121 WriteCommand(0x80+0x40+0x06);//LCD1602字符型液晶顯示器第二行第7個位置的顯示位 122 WriteCommand(0x0f);//開LCD1602字符型液晶顯示器顯示,開光標,開光標(或字符)閃爍。 123 break; 124 case 3: 125 minutange=fen%10;//關掉定時器0定時后,把分鍾計時時間數值取余賦給分鍾個位顯示位。 126 minutanshi=fen/10;//關掉定時器0定時后,把分鍾計時時間數值取除賦給分鍾十位顯示位。 127 WriteCommand(0x80+0x40+0x04);//LCD1602字符型液晶顯示器第二行第5個位置的顯示位 128 WriteCommand(0x0f);//開LCD1602字符型液晶顯示器顯示,開光標,開光標(或字符)閃爍。 129 break; 130 case 4: 131 minutanshi=minutanshi;//關掉定時器0定時后,把分鍾計時時間數值取除后得到的值再賦給分鍾十位顯示位。 132 WriteCommand(0x80+0x40+0x03);//LCD1602字符型液晶顯示器第二行第4個位置的顯示位 133 WriteCommand(0x0f);//開LCD1602字符型液晶顯示器顯示,開光標,開光標(或字符)閃爍。 134 break; 135 case 5: 136 hourge=shi%10;//關掉定時器0定時后,把時鍾計時時間數值取余賦給時鍾個位顯示位。 137 hourshi=shi/10;//關掉定時器0定時后,把時鍾計時時間數值取除賦給時鍾十位顯示位。 138 WriteCommand(0x80+0x40+0x01);//LCD1602字符型液晶顯示器第二行第2個位置的顯示位 139 WriteCommand(0x0f);//開LCD1602字符型液晶顯示器顯示,開光標,開光標(或字符)閃爍。 140 break; 141 case 6: 142 hourshi=hourshi;//關掉定時器0定時后,把時鍾計時時間數值取除后得到的值再賦給時鍾十位顯示位。 143 WriteCommand(0x80+0x40+0x00);//LCD1602字符型液晶顯示器第二行第1個位置的顯示位 144 WriteCommand(0x0f);//開LCD1602字符型液晶顯示器顯示,開光標,開光標(或字符)閃爍。 145 break; 146 case 7: 147 WriteCommand(0x80+0x40+0x07);//LCD1602字符型液晶顯示器第二行第8個位置的顯示位 148 WriteCommand(0x0c);//開LCD1602字符型液晶顯示器顯示,開光標,開光標(或字符)閃爍。 149 TR0=1;//打開定時器0 150 S1num=0;//移位按鍵S1按鍵按下次數清零 151 break; 152 default: 153 S1num=0;//移位按鍵S1按鍵按下次數清零 154 break; 155 } 156 } 157 } 158 if(S1num!=0)//判斷移位按鍵S1按鍵按下次數變量是否為0 159 { 160 if(S2==0)//判斷增加按鍵S2是否按下 161 { 162 if(S2==0)//判斷增加按鍵S2是否按下 163 { 164 Delay(5); 165 if(S2==0)//再次判斷增加按鍵S2是否按下 166 { 167 while(!S2);//等待增加按鍵S2彈起 168 switch(S1num)//移位按鍵S1按鍵按下次數變量選擇位 169 { 170 case 1://移位按鍵S1按鍵第一次按下 171 secondge++;//秒鍾個位數先賦值再加加 172 if(secondge==10)//判斷秒鍾個位數設定值是否達到10 173 secondge=0;//秒鍾個位數歸零 174 LCD1602DisplayGeDigitResolve(0x07,secondge);//LCD1602字符型液晶顯示器第二行第8個位置的秒鍾個位顯示位的顯示數 175 WriteCommand(0x80+0x40+0x07);//寫入LCD1602字符型液晶顯示器第二行第8個位置的秒鍾個位顯示位 176 miao=secondshi*10+secondge;//移位修改秒鍾個位顯示位的數值后,需要通過秒鍾十位顯示位的數值加上秒鍾個位顯示位的數值之和賦給秒鍾變量,才能在修改秒鍾個位或十位顯示位的數值后重新計時。(原因:秒鍾個位或十位顯示位的數值是在秒鍾的數值上分解得來,當秒鍾個位或十位顯示位的數值發生變化后,秒鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 177 break; 178 case 2://移位按鍵S1按鍵第二次按下 179 secondshi++;//秒鍾十位數先賦值再加加 180 if(secondshi==6)//判斷秒鍾十位數設定值是否達到6 181 secondshi=0;//秒鍾十位數歸零 182 LCD1602DisplayShiDigitResolve(0x06,secondshi);//LCD1602字符型液晶顯示器第二行第7個位置的秒鍾十位顯示位的顯示數 183 WriteCommand(0x80+0x40+0x06);//寫入LCD1602字符型液晶顯示器第二行第7個位置的秒鍾十位顯示位 184 miao=secondshi*10+secondge;//移位修改秒鍾十位顯示位的數值后,需要通過秒鍾十位顯示位的數值加上秒鍾個位顯示位的數值之和賦給秒鍾變量,才能在修改秒鍾個位或十位顯示位的數值后重新計時。(原因:秒鍾個位或十位顯示位的數值是在秒鍾的數值上分解得來,當秒鍾個位或十位顯示位的數值發生變化后,秒鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 185 break; 186 case 3://移位按鍵S1按鍵第三次按下 187 minutange++;//分鍾個位數先賦值再加加 188 if(minutange==10)//判斷分鍾個位數設定值是否達到10 189 minutange=0;//分鍾個位數歸零 190 LCD1602DisplayGeDigitResolve(0x04,minutange);//LCD1602字符型液晶顯示器第二行第5個位置的分鍾個位顯示位的顯示數 191 WriteCommand(0x80+0x40+0x04);//寫入LCD1602字符型液晶顯示器第二行第5個位置的分鍾個位顯示位 192 fen=minutanshi*10+minutange;//移位修改分鍾個位顯示位的數值后,需要通過分鍾十位顯示位的數值加上分鍾個位顯示位的數值之和賦給分鍾變量,才能在修改分鍾個位或十位顯示位的數值后重新計時。(原因:分鍾個位或十位顯示位的數值是在分鍾的數值上分解得來,當分鍾個位或十位顯示位的數值發生變化后,分鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 193 break; 194 case 4://移位按鍵S1按鍵第四次按下 195 minutanshi++;//分鍾十位數先賦值再加加 196 if(minutanshi==6)//判斷分鍾十位數設定值是否達到6 197 minutanshi=0;//分鍾十位數歸零 198 LCD1602DisplayShiDigitResolve(0x03,minutanshi);//LCD1602字符型液晶顯示器第二行第4個位置的分鍾十位顯示位的顯示數 199 WriteCommand(0x80+0x40+0x03);//寫入LCD1602字符型液晶顯示器第二行第7個位置的分鍾十位顯示位 200 fen=minutanshi*10+minutange;//移位修改分鍾十位顯示位的數值后,需要通過分鍾十位顯示位的數值加上分鍾個位顯示位的數值之和賦給分鍾變量,才能在修改分鍾個位或十位顯示位的數值后重新計時。(原因:分鍾個位或十位顯示位的數值是在分鍾的數值上分解得來,當分鍾個位或十位顯示位的數值發生變化后,分鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 201 break; 202 case 5://移位按鍵S1按鍵第五次按下 203 hourge++;//時鍾個位數先賦值再加加 204 if(hourge==4)//判斷時鍾個位數設定值是否達到4 205 hourge=0;//時鍾個位數歸零 206 LCD1602DisplayGeDigitResolve(0x01,hourge);//LCD1602字符型液晶顯示器第二行第2個位置的時鍾個位顯示位的顯示數 207 WriteCommand(0x80+0x40+0x01);//寫入LCD1602字符型液晶顯示器第二行第2個位置的時鍾個位顯示位 208 shi=hourshi*10+hourge;//移位修改時鍾個位顯示位的數值后,需要通過時鍾十位顯示位的數值加上時鍾個位顯示位的數值之和賦給時鍾變量,才能在修改時鍾個位或十位顯示位的數值后重新計時。(原因:時鍾個位或十位顯示位的數值是在時鍾的數值上分解得來,當時鍾個位或十位顯示位的數值發生變化后,時鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 209 break; 210 case 6://移位按鍵S1按鍵第六次按下 211 hourshi++;//時鍾十位數先賦值再加加 212 if(hourshi==3)//判斷時鍾十位數設定值是否達到3 213 hourshi=0;//時鍾十位數歸零 214 LCD1602DisplayShiDigitResolve(0x00,hourshi);//LCD1602字符型液晶顯示器第二行第1個位置的時鍾十位顯示位的顯示數 215 WriteCommand(0x80+0x40+0x00);//寫入LCD1602第二行第1個位置的時鍾十位顯示位 216 shi=hourshi*10+hourge;//移位修改時鍾十位顯示位的數值后,需要通過時鍾十位顯示位的數值加上時鍾個位顯示位的數值之和賦給時鍾變量,才能在修改時鍾個位或十位顯示位的數值后重新計時。(原因:時鍾個位或十位顯示位的數值是在時鍾的數值上分解得來,當時鍾個位或十位顯示位的數值發生變化后,時鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 217 break; 218 default: 219 S1num=0;//移位按鍵S1按鍵按下次數清零 220 break; 221 } 222 } 223 } 224 if(S3==0)//判斷減少按鍵S3是否按下 225 { 226 Delay(5); 227 if(S3==0)//再次判斷減少按鍵S3是否按下 228 { 229 while(!S3);//等待減少按鍵S3彈起 230 switch(S1num)//移位按鍵S1按鍵按下次數變量選擇位 231 { 232 case 1://移位按鍵S1按鍵第一次按下 233 secondge--;//秒鍾個位數先賦值再減減 234 if(secondge==-1)//判斷秒鍾個位數設定值是否達到-1 235 secondge=9;//秒鍾個位數歸9 236 LCD1602DisplayGeDigitResolve(0x07,secondge);//LCD1602字符型液晶顯示器第二行第8個位置的秒鍾個位顯示位的顯示數 237 WriteCommand(0x80+0x40+0x07);//寫入LCD1602字符型液晶顯示器第二行第8個位置的秒鍾個位顯示位 238 miao=secondshi*10+secondge;//移位修改秒鍾個位顯示位的數值后,需要通過秒鍾十位顯示位的數值加上秒鍾個位顯示位的數值之和賦給秒鍾變量,才能在修改秒鍾個位或十位顯示位的數值后重新計時。(原因:秒鍾個位或十位顯示位的數值是在秒鍾的數值上分解得來,當秒鍾個位或十位顯示位的數值發生變化后,秒鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 239 break; 240 case 2://移位按鍵S1按鍵第二次按下 241 secondshi--;//秒鍾十位數先賦值再減減 242 if(secondshi==-1)//判斷秒鍾十位數設定值是否達到-1 243 secondshi=5;//秒鍾十位數歸5 244 LCD1602DisplayShiDigitResolve(0x06,secondshi);//LCD1602字符型液晶顯示器第二行第7個位置的秒鍾十位顯示位的顯示數 245 WriteCommand(0x80+0x40+0x06);//寫入LCD1602字符型液晶顯示器第二行第7個位置的秒鍾十位顯示位 246 miao=secondshi*10+secondge;//移位修改秒鍾十位顯示位的數值后,需要通過秒鍾十位顯示位的數值加上秒鍾個位顯示位的數值之和賦給秒鍾變量,才能在修改秒鍾個位或十位顯示位的數值后重新計時。(原因:秒鍾個位或十位顯示位的數值是在秒鍾的數值上分解得來,當秒鍾個位或十位顯示位的數值發生變化后,秒鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 247 break; 248 case 3://移位按鍵S1按鍵第三次按下 249 minutange--;//分鍾個位數先賦值再減減 250 if(minutange==-1)//判斷分鍾個位數設定值是否達到-1 251 minutange=9;//分鍾個位數歸9 252 LCD1602DisplayGeDigitResolve(0x04,minutange);//LCD1602字符型液晶顯示器第二行第5個位置的分鍾個位顯示位的顯示數 253 WriteCommand(0x80+0x40+0x04);//寫入LCD1602字符型液晶顯示器第二行第5個位置的分鍾個位顯示位 254 fen=minutanshi*10+minutange;//移位修改分鍾個位顯示位的數值后,需要通過分鍾十位顯示位的數值加上分鍾個位顯示位的數值之和賦給分鍾變量,才能在修改分鍾個位或十位顯示位的數值后重新計時。(原因:分鍾個位或十位顯示位的數值是在分鍾的數值上分解得來,當分鍾個位或十位顯示位的數值發生變化后,分鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 255 break; 256 case 4://移位按鍵S1按鍵第四次按下 257 minutanshi--;//分鍾十位數先賦值再減減 258 if(minutanshi==-1)//判斷分鍾十位數設定值是否達到6 259 minutanshi=5;//分鍾十位數歸5 260 LCD1602DisplayShiDigitResolve(0x03,minutanshi);//LCD1602字符型液晶顯示器第二行第4個位置的分鍾十位顯示位的顯示數 261 WriteCommand(0x80+0x40+0x03);//寫入LCD1602字符型液晶顯示器第二行第7個位置的分鍾十位顯示位 262 fen=minutanshi*10+minutange;//移位修改分鍾十位顯示位的數值后,需要通過分鍾十位顯示位的數值加上分鍾個位顯示位的數值之和賦給分鍾變量,才能在修改分鍾個位或十位顯示位的數值后重新計時。(原因:分鍾個位或十位顯示位的數值是在分鍾的數值上分解得來,當分鍾個位或十位顯示位的數值發生變化后,分鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 263 break; 264 case 5://移位按鍵S1按鍵第五次按下 265 hourge--;//時鍾個位數先賦值再減減 266 if(hourge==-1)//判斷時鍾個位數設定值是否達到-1 267 hourge=3;//時鍾個位數歸3 268 LCD1602DisplayGeDigitResolve(0x01,hourge);//LCD1602字符型液晶顯示器第二行第2個位置的時鍾個位顯示位的顯示數 269 WriteCommand(0x80+0x40+0x01);//寫入LCD1602字符型液晶顯示器第二行第2個位置的時鍾個位顯示位 270 shi=hourshi*10+hourge;//移位修改時鍾個位顯示位的數值后,需要通過時鍾十位顯示位的數值加上時鍾個位顯示位的數值之和賦給時鍾變量,才能在修改時鍾個位或十位顯示位的數值后重新計時。(原因:時鍾個位或十位顯示位的數值是在時鍾的數值上分解得來,當時鍾個位或十位顯示位的數值發生變化后,時鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 271 break; 272 case 6://移位按鍵S1按鍵第六次按下 273 hourshi--;//時鍾十位數先賦值再減減 274 if(hourshi==-1)//判斷時鍾十位數設定值是否達到-1 275 hourshi=2;//時鍾十位數歸2 276 LCD1602DisplayShiDigitResolve(0x00,hourshi);//LCD1602字符型液晶顯示器第二行第1個位置的時鍾十位顯示位的顯示數 277 WriteCommand(0x80+0x40+0x00);//寫入LCD1602字符型液晶顯示器第二行第1個位置的時鍾十位顯示位 278 shi=hourshi*10+hourge;//移位修改時鍾十位顯示位的數值后,需要通過時鍾十位顯示位的數值加上時鍾個位顯示位的數值之和賦給時鍾變量,才能在修改時鍾個位或十位顯示位的數值后重新計時。(原因:時鍾個位或十位顯示位的數值是在時鍾的數值上分解得來,當時鍾個位或十位顯示位的數值發生變化后,時鍾的數值也要變化,否則不能在原基礎上修改后重新計時,只能返回原基礎上計時。) 279 break; 280 default: 281 S1num=0;//移位按鍵S1按鍵按下次數清零 282 break; 283 } 284 } 285 } 286 } 287 if(S4==0)//判斷啟停按鍵S4是否按下 288 { 289 Delay(5); 290 if(S4==0)//再次判斷啟停按鍵S4是否按下 291 { 292 S4num++;//啟停按鍵S4按下次數先賦值再加加 293 while(!S4);//等待啟停按鍵S4彈起 294 if(S4num==1)//判斷啟停按鍵S4是否第一次按下過。實現直接停止。 295 { 296 TR0=0;//關定時器0 297 } 298 if(S1num>=1&&S4num==1)//判斷移位按鍵S1按鍵和啟停按鍵S4是否按下過。實現移位停止后,可移位修改時間數值或不修改時間數值,然后再啟動。 299 { 300 TR0=1;//開定時器0 301 WriteCommand(0x0c);//開LCD1602顯示,關光標,關光標(或字符)閃爍。 302 S4num=0;//啟停按鍵S4按下次數變量清零 303 S1num=0;//移位按鍵S1按鍵按下次數變量清零 304 } 305 if(S4num==2)//判斷移位按鍵S4按鍵是否第二次按下過 306 { 307 TR0=1;//開定時器0 308 S4num=0;//啟停按鍵S4按下次數變量清零 309 } 310 } 311 } 312 } 313 void Timer0() interrupt 1//定時器0中斷函數 314 { 315 TH0=(65536-50000)/256;//TH0重新裝值 316 TL0=(65536-50000)%256;//TL0重新裝值 317 count++;//定時器0中斷次數先賦值再加 318 if(count==18)//判斷定時器0中斷次數是否為18次 319 { 320 count=0;//定時器0中斷次數歸零 321 miao++;//秒鍾先賦值再加 322 if(miao==60)//判斷秒鍾是否達到60秒 323 { 324 miao=0;//秒鍾歸零 325 fen++;//分鍾先賦值再加 326 if(fen==60)//判斷分鍾是否達到60分 327 { 328 fen=0;//分鍾歸零 329 shi++;//時鍾先賦值再加 330 if(shi==24)//判斷時鍾是否達到24時 331 { 332 shi=0;//時鍾歸零 333 } 334 LCD1602DisplayTime(0x00,shi);//時鍾顯示兩位數分解函數 335 } 336 LCD1602DisplayTime(0x03,fen);//分鍾顯示兩位數分解函數 337 } 338 LCD1602DisplayTime(0x06,miao);//秒鍾顯示兩位數分解函數 339 } 340 } 341 void main()//主函數 342 { 343 LCD1602Init();//LCD1602字符型液晶顯示器初始化函數 344 Timer0Init();//定時器0初始化函數 345 LCD1602Display();//LCD1602字符型液晶顯示器顯示函數 346 while(1) 347 { 348 KeyScan();//按鍵掃描函數 349 } 350 }