① 如何做一個單片機電子時鍾
這個很簡單啊,兩種思路:1,用單片機定時器來做,優點是外圍電路簡單,只需要一個單片機最小系統,和一個顯示模塊(1602液晶比較好);缺點是:定時不是很准,跑的時間長了會有誤差,而且主要是程序,要寫很多,不過程序不是很難。2,用時鍾晶元,一般都用DS1302,還需要單片機最小系統和顯示模塊,優點是:定時准確,誤差很小,在有備用電池的情況下,即使單片機掉電,也可以維持很長時間,程序相對簡單。缺點是:外圍電路比前者相對復雜一點。如果想做個實際的東西拿來用,建議使用第二種方法,如果是想鍛煉自己的編程能力的話,選第一種吧。祝成功!
② 單片機實現電子時鍾
ORG 0000H ;程序執行開始地址
LJMP START ;跳到標號START執行
ORG 0003H ;外中斷0中斷程序入口
LJMP OUTINTT0 ;外中斷0中斷返回
ORG 000BH ;定時器T0中斷程序入口
LJMP INTT0 ;跳至INTTO執行
ORG 0013H ;外中斷1中斷程序入口
RETI;外中斷1中斷返回
ORG 001BH ;定時器T1中斷程序入口
LJMP INTT1 ;跳至INTT1執行;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 主 程 序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
START:
MOV R0,#70H ;清70H-7AH共11個內存單元
MOV R7,#0BH ;
CLEARDISP:
MOV @R0,#00H ;
INC R0 ;
DJNZ R7,CLEARDISP ;
MOV 70H,#07H;
MOV 71H,#05H;
MOV 76H,#09H;
MOV 77H,#05H;
MOV 78H,#05H;
MOV 79H,#00H;
MOV 20H,#00H ;清20H(標志用)
MOV 7AH,#0AH ;放入"熄滅符"數據
MOV 7BH,#00H ;清報時寄存器
MOV TMOD,#11H ;設T0、T1為16位定時器
MOV TL0,#0B0H ;50MS定時初值(T0計時用)
MOV TH0,#3CH ;50MS定時初值
MOV TL1,#0B0H ;50MS定時初值(T1閃爍定時用)
MOV TH1,#3CH ;50MS定時初值
SETB PT1;定時器T1為高優先順序
SETB EA ;總中斷開放
SETB ET0 ;允許T0中斷
SETB TR0 ;開啟T0定時器
SETB EX0 ;開啟外部中斷0
MOV R4,#14H ;1秒定時用初值(50MS×20)
MOV R2,#06H ;0.3秒的閃動初值(50MS*6)
START1:
LCALL DISPLAY;調用顯示子程序
LCALL BELL;
LCALL DISCLOSE;
SJMP START1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 計時程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T0中斷服務程序
INTT0:
PUSH ACC ;累加器入棧保護
PUSH PSW ;狀態字入棧保護
CLR ET0 ;關T0中斷允許
CLR TR0 ;關閉定時器T0
MOV TL0,#0B0H ;重裝初值(低8位修正值)
MOV TH0,#3CH ;重裝初值(高8位修正值)
SETB TR0 ;開啟定時器T0
DJNZ R4, OUTT0 ;20次中斷未到中斷退出
ADDSS:
MOV R4,#14H ;20次中斷到(1秒)重賦初值
MOV R0,#71H ;指向秒計時單元(70H-71H)
ACALL DBchange ;調用數據處理程序(加1並存入顯示單元)
MOV A,R3 ;秒數據放入A(R3為2位十進制數組合)
CLR C ;清進位標志
CJNE A,#60H,ADDMM ;
ADDMM:
JC OUTT0 ;小於60秒時中斷退出
LCALL CLR0 ;大於或等於60秒時對秒計時單元清0
MOV R0,#77H ;指向分計時單元(76H-77H)
ACALL DBchange ;
MOV A,R3 ;分數據放入A
CLR C ;清進位標志
CJNE A,#60H,ADDHH ;
ADDHH:
JC OUTT0 ;小於60分時中斷退出
ACALL CLR0 ;大於或等於60分時分計時單元清0
MOV R0,#79H ;指向小時計時單元(78H-79H)
ACALL DBchange ;
MOV A,R3 ;時數據放入A
CLR C ;清進位標志
MOV 7BH,#01H
CJNE A,#24H,HOUR ;
HOUR:
JC OUTT0 ;小於24小時中斷退出
ACALL CLR0 ;大於或等於24小時小時計時單元清0
OUTT0:
MOV 72H,76H ;中斷退出時將分、時計時單元數據移
MOV 73H,77H ;入對應顯示單元
MOV 74H,78H ;
MOV 75H,79H ;
POP PSW ;恢復狀態字(出棧)
POP ACC ;恢復累加器
SETB ET0 ;開放T0中斷
RETI ;中斷返回;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 閃動調時 程 序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T1中斷服務程序,用作時間調整時調整單元閃爍指示
INTT1:
PUSH ACC ;中斷現場保護
PUSH PSW ;
MOV TL1, #0B0H ;裝定時器T1定時初值
MOV TH1, #3CH ;
DJNZ R2,INTT1OUT ;0.3秒未到退出中斷(50MS中斷6次)
MOV R2,#06H ;重裝0.3秒定時用初值
CPL 02H ;0.3秒定時到對閃爍標志取反
JB 02H,FLASH1 ;02H位為1時顯示單元"熄滅"
MOV 72H,76H ;02H位為0時正常顯示
MOV 73H,77H ;
MOV 74H,78H ;
MOV 75H,79H ;
INTT1OUT:
POP PSW ;恢復現場
POP ACC ;
RETI ;中斷退出
FLASH1:
JB 01H,FLASH2 ;01H位為1時,轉小時熄滅控制
MOV 72H,7AH ;01H位為0時,"熄滅符"數據放入分
MOV 73H,7AH ;顯示單元(72H-73H),將不顯示分數據
MOV 74H,78H ;
MOV 75H,79H ;
AJMP INTT1OUT ;轉中斷退出
FLASH2:
MOV 72H,76H ;01H位為1時,"熄滅符"數據放入小時
MOV 73H,77H ;顯示單元(74H-75H),小時數據將不顯示
MOV 74H,7AH ;
MOV 75H,7AH ;
AJMP INTT1OUT ;轉中斷退出
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 數據處理程序,把6個數碼管顯示內容存入相應的地址;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
DBchange:
MOV A,@R0 ;取當前計時單元數據到A
DEC R0 ;指向前一地址
SWAP A ;A中數據高四位與低四位交換
ORL A,@R0 ;前一地址中數據放入A中低四位
ADD A,#01H ;A加1操作
DA A ;十進制調整
MOV R3,A ;移入R3寄存器
ANL A,#0FH ;高四位變0
MOV @R0,A ;放回前一地址單元
MOV A,R3 ;取回R3中暫存數據
INC R0 ;指向當前地址單元
SWAP A ;A中數據高四位與低四位交換
ANL A,#0FH ;高四位變0
MOV @R0,A ;數據放入當削地址單元中
RET ;子程序返回
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 清零程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;對計時單元復零用
CLR0:
CLR A ;清累加器
MOV @R0,A ;清當前地址單元
DEC R0 ;指向前一地址
MOV @R0,A ;前一地址單元清0
RET ;子程序返回
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 時鍾調整中斷程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;當調時按鍵按下時進入此程序
OUTINTT0:
PUSH ACC;
PUSH PSW;
CLR ET0 ;關定時器T0中斷
CLR TR0 ;關閉定時器T0
CLR EX0 ;關閉外部中斷0
MOV R2,#06H ;進入調時狀態,賦閃爍定時初值
SETB ET1 ;允許T1中斷
SETB TR1 ;開啟定時器T1
SET2: JNB P1.0,SET1 ;P1.0口為0(鍵未釋放),等待
SETB 00H ;鍵釋放,分調整閃爍標志置1
SET4:
JB P1.0,SET3 ;p1.0沒有按下時進入分調整程序
LJMP SETHH ;p1.0按下轉調小時狀態
SET3:
LCALL DISPLAY ;等待調分按鍵時時鍾顯示用
JB P1.1,SET4;等待p1.1按下
LCALL DL1S; MOV R0,#77H;按下時加1分鍾操作
LCALL DBchange ;調用加1子程序
MOV A,R3 ;取調整單元數據
CLR C ;清進位標志
CJNE A,#60H,HHH ;調整單元數據與60比較
HHH:
JC SET4 ;調整單元數據小於60轉SET4循環
LCALL CLR0 ;調整單元數據大於或等於60時清0
CLR C ;清進位標志
lJMP SET4 SETHH:
CLR 00H ;分閃爍標志清除(進入調小時狀態)
SETHH1:
JNB P1.0,SET5 ;等待鍵釋放
SETB 01H ;小時調整標志置1
SET6:
JNB P1.0,SETOUT ;P1.0再次按下時退出時間調整
LCALL DISPLAY;
JB P1.1,SET6;等待按鍵按下
LCALL DL1S;
MOV R0,#79H ;按下P1.1時加1小時操作
LCALL DBchange ;調加1子程序
MOV A,R3 ;
CLR C ;
CJNE A,#24H,HOUU ;計時單元數據與24比較
HOUU:
JC SET6;小於24轉SET6循環
LCALL CLR0 ;大於或等於24時清0操作
AJMP SET6;跳轉到SET6循環
SETOUT:
JNB P1.0,SETOUT1 ;調時退出程序。等待鍵釋放
LCALL DISPLAY ;延時削抖
JNB P1.0,SETOUT ;是抖動,返回SETOUT再等待
OUTRETEND:
CLR 01H ;清調小時標志
CLR 00H ;清調分標志
CLR 02H ;清閃爍標志
CLR TR1 ;關閉定時器T1
CLR ET1 ;關定時器T1中斷
SETB TR0 ;開啟定時器T0
SETB ET0 ;開定時器T0中斷(計時開始)
SETB EX0;開啟外部中斷0
POP PSW;
POP ACC;
RETI ;反回主程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SET1:
LCALL DISPLAY ;鍵釋放等待時調用顯示程序(調分)
LJMP SET2 ;防止鍵按下時無時鍾顯示
SET5:
LCALL DISPLAY ;鍵釋放等待時調用顯示程序(調小時)
LJMP SETHH1 ;防止鍵按下時無時鍾顯示
SETOUT1:
LCALL DISPLAY ;退出時鍾調整時鍵釋放等待
LJMP SETOUT ;防止鍵按下時無時鍾顯示
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 顯示程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 顯示數據在70H-75H單元內,用六位LED共陽數碼管顯示,P0口輸出段碼數據,P2口作
; 掃描控制,每個LED數碼管亮1MS時間再逐位循環。
DISPLAY:
MOV R1,#70H ;指向顯示數據首址
MOV R5,#01H ;掃描控制字初值
PLAY:
MOV A,R5 ;掃描字放入A
MOV P2,A ;從P2口輸出
MOV A,@R1 ;取顯示數據到A
MOV DPTR,#TAB ;取段碼表地址
MOVC A,@A+DPTR ;查顯示數據對應段碼
MOV P0,A ;段碼放入P0口
LCALL DL1MS ;顯示1MS
INC R1 ;指向下一地址
MOV A,R5 ;掃描控制字放入A
JB ACC.5,ENDOUT ;ACC.5=1時一次顯示結束
RL A ;A中數據循環左移
MOV R5,A ;放回R5內
LJMP PLAY ;跳回PLAY循環
ENDOUT:
MOV P0,#00H ;P0口復位
RET ;子程序返回
TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,00H
;共陰段碼表 "0""1""2" "3""4""5""6""7" "8""9""不亮"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;整點報時;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BELL:
MOV A,7BH;
CLR C;
MOV 7BH,#00H ;
CJNE A,#01H,BELLEND MOV A,79H;
SWAP A;
ORL A,78H;
MOV 7CH ,ABELLRING:
CLR P1.7;
LCALL DL05S;
SETB P1.7;
LCALL DL05S;
DJNZ 7CH,BELLRING; MOV A ,#00H;
MOV 7BH,#00H ;BELLEND:RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;省電模式
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DISCLOSE:
JB P1.3,OUTDISCLOSE;
CLOSE1: MOV P2,#0FFH;
JNB P1.3,CLOSE1;
JB P1.3,CLOSE1;
CLOSE2: JNB P1.3,CLOSE2;
MOV P2,R5;
OUTDISCLOSE:RET;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 延時程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;1MS延時程序,LED顯示程序用
DL1MS: MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
RET
;20MS延時程序,採用調用顯示子程序以改善LED的顯示閃爍現象
DS20MS: ACALL DISPLAY
ACALL DISPLAY
ACALL DISPLAY
RET
;延時程序,用作按鍵時間的長短判斷
DL1S: LCALL DL05S
LCALL DL05S
RET
DL05S: MOV R3,#20H ;8毫秒*32=0.196秒
DL05S1: LCALL DISPLAY
DJNZ R3,DL05S1
RET
END ;程序結束 但是做這個是自己做的,是可以調時間,不要的話可以把那個部分刪除。
③ 如何用51單片機製作簡易電子鍾
我自己做的一個課程設計,程序運行已經成功了:
匯編程序如下:
ORG0000H
AJMPmain
ORG000BH;定時器0的中斷向量地址
AJMPTIME0;跳轉到真正的定時器程序處
ORG30H
main:
movdptr,#k1;
start:
MOVP0,#00H;中斷預處理程序
MOVP1,#00H
MOVP3,#00H;關所有燈
MOVR0,#00H;軟體計數器預清0
MOVR7,#00H
MOVR6,#00H
MOVTMOD,#00000001B;定時/計數器0工作於方式1
MOVTH0,#3CH
MOVTL0,#0B0H;即數15536
SETBEA;開總中斷允許
SETBET0;開定時/計數器0允許
SETBTR0;定時/計數器0開始運行
LOOP:;判斷時鍾進位程序
MOVA,R1
CJNEA,#60,LOOP1;R1等於60嗎?
MOVR1,#0
INCR2;R1等於60那麼R2加一,R1清0
MOVA,R2
CJNEA,#60,LOOP1;R2等於60嗎?
MOVR2,#0
INCR3;R2等於60那麼R3加一,R2清0
MOVA,R3
CJNEA,#24,LOOP1;R3等於24嗎?
MOVR3,#0
;R3等於24那麼R3清0
LOOP1:
mova,r2;如果分鍾顯示為0,報警
cjnea,#01H,LOOP2
mova,r1
cjnea,#00H,LOOP3
clrp2.0
LOOP3:
mova,r1;如果秒鍾顯示為1,取消報警
cjnea,#05H,LOOP2
setbp2.0
LOOP2:;顯示數據處理
MOVA,R1;取來8位二進制數
MOVB,#100
DIVAB;除以100
MOVA,B;取回余數
MOVB,#10
DIVAB;再除以10
MOVR4,A;商是十位數,存放到R4
MOVR5,B;余數是個位,存放到R5
MOV42H,R4
mOV41H,R5
;R1的BCD碼放入41-42H單元
MOVA,R2;取來8位二進制數
MOVB,#100
DIVAB;除以100
MOVA,B;取回余數
MOVB,#10
DIVAB;再除以10
MOVR4,A;商是十位數,存放到R4
MOVR5,B;余數是個位,存放到R5
MOV44H,R4
MOV43H,R5
;R2的BCD碼放入43-44H單元
MOVA,R3;取來8位二進制數
MOVB,#100
DIVAB;除以100
MOVA,B;取回余數
MOVB,#10
DIVAB;再除以10
MOVR4,A;商是十位數,存放到R4
MOVR5,B;余數是個位,存放到R5
MOV46H,R4
mov45H,R5
;R3的BCD碼放入45-46H單元
L1:
mova,41h
movca,@a+dptr
mov51h,a
mova,42h
movca,@a+dptr
mov52h,a
mova,43h
movca,@a+dptr
mov53h,a
mova,44h
movca,@a+dptr
mov54h,a
mova,45h
movca,@a+dptr
mov55h,a
mova,46h
movca,@a+dptr
mov56h,a;將顯示代碼送入51H--56H
display:;顯示程序
movp0,#0ffH;一
movp0,51H
movP1,#0feH
acalldelay1S
movp1,#0ffH
movp0,#0ffH;二
movp0,52h
movP1,#0fdH
acalldelay1S
movp1,#0ffH
movp0,#0ffH;三
movp0,53h
movP1,#0fbH
acalldelay1S
movp1,#0ffH
movp0,#0ffH;四
movp0,54h
movP1,#0f7H
acalldelay1S
movp1,#0ffH
movp0,#0ffH;五
movp0,55h
movP1,#0efH
acalldelay1S
movp1,#0ffH
movp0,#0ffH;六
movp0,56h
movP1,#0dfH
acalldelay1S
movp1,#0ffH
;將51H-56H數據顯示,
AJMPLOOP;工作處理程序
TIME0:;定時器0的中斷處理程序
INCR7
MOVA,R7
CJNEA,#20,T_RET;R7單元中的值到了20了嗎?
T_L1:
INCR1;到了20那麼R1+1
MOVR7,#0;清軟體計數器
T_RET:;二十分之一秒時的程序
incr6
mova,r6
cjner6,#3,T_over;調節時間的延遲時間
movr6,#0
jbp2.1,T_over1
mova,r2
adda,#1
cjnea,#60,T_tiao1
mova,#0
T_tiao1:
movr2,a
T_over1:
jbp2.2,T_over
mova,r3
adda,#1
cjnea,#24,T_tiao2
mova,#0
T_tiao2:
movr3,a
T_over:
MOVTH0,#3CH
MOVTL0,#0B0H;如果沒到一秒重置定時常數
reti
delay1s:MOV31H,#100
D1:MOV32H,#30
D2:DJNZ32H,D2
DJNZ31H,D1
RET
delay2s:MOV33H,#255
D3:MOV34H,#255
D4:DJNZ34H,D4
DJNZ33H,D3
RET
K1:db3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh
④ 單片機電子時鍾
PCF8583的電路圖和程序我這里有,可以HI我
加上數碼管和鍵盤就可以用了。
⑤ 51單片機電子時鍾
才1毛錢
⑥ 51單片機電子鍾
看看這個簡單的模擬實例,供參考
⑦ 求c51單片機電子鍾程序(c語言)
#include <reg51.h>
#define uchar unsigned char //定義unsigned int為uint
#define uint unsigned int //定義unsigned uchar為uchar
sbit LCD_RS = P2^0 ;
sbit LCD_RW = P2^1 ;
sbit LCD_EN = P2^2 ;
sbit D_SDA = P2^6; //定義74HC164數據線為P2.6埠
sbit D_SCL = P2^7; //定義74HC164數據線為P2.7埠
sbit CLK = P1^3; /*實時時鍾時鍾線引腳 */
sbit IO = P1^4; /*實時時鍾數據線引腳 */
sbit RST = P1^5; /*實時時鍾復位線引腳 */
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
uchar time[8] = {0x50,0x30,0x19,0x30,0x12,0x06,0x06};
//========= 延時函數 ============
//延時時間以1ms為單位
//s決定延時時間長短
void delay_ms(uint s)
{
uint x;
for(s;s>0;s--)
{
x = 200;
while(x--);
}
}
//========= 送出一個位元組給74HC164(實現串並轉換) ==========
void send_out(unsigned char out)//傳送一個位元組8位
{
uchar i;
D_SCL = 0;
for (i=8;i>=1;i--)
{
D_SDA = out&0x80; //送數據到數據口
D_SCL = 1; //時鍾線置1
D_SCL = 0; //送一時鍾
out<<=1; //左移
}
}
//========= 寫命令函數 ==========
void lcd_wcmd(uchar cmd)
{
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
send_out(cmd);
LCD_EN = 1;
LCD_EN = 0 ;
}
//========= 寫數據函數 ==========
void lcd_wdat(uchar dat)
{
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
send_out(dat);
LCD_EN = 1;
LCD_EN = 0;
}
//========= LCD初始化函數 ==========
void lcd_init()
{
lcd_wcmd(0x38);
delay_ms(1);
lcd_wcmd(0x0c); //顯示開,關游標
delay_ms(1);
lcd_wcmd(0x06); //向右移動游標
delay_ms(1);
lcd_wcmd(0x01); //清除LCD顯示屏
delay_ms(1);
}
//========== 往DS1302寫入1Byte數據 (內部函數) =============
void w_byte(uchar dat)
{
uchar i;
for(i=8; i>0; i--)
{
IO = dat & 0x01;
CLK = 1;
CLK = 0;
dat = dat >> 1;
}
}
//======== 從DS1302讀取1Byte數據 (內部函數) ===================
uchar r_byte(void)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >> 1;
ACC7 = IO;
CLK = 1;
CLK = 0;
}
return(ACC);
}
//========== 指定地址往DS1302寫入1Byte數據 (內部函數) =============
void write_byte(uchar addr, uchar dat)
{
RST = 0;
CLK = 0;
RST = 1;
w_byte(addr);
w_byte(dat);
CLK = 1;
RST = 0;
}
//========== 指定地址往DS1302讀1Byte數據 (內部函數) =============
uchar read_byte(uchar addr)
{
uchar ucData;
RST = 0;
CLK = 0;
RST = 1;
w_byte(addr);
ucData = r_byte();
CLK = 1;
RST = 0;
return(ucData);
}
//============ 設置ds1302日期和時間 =============
void write_ds1302(uchar *p)
{
uchar i;
uchar addr = 0x80;
write_byte(0x8e,0x00); // 控制命令,WP=0,寫操作
for(i =7; i>0; i--)
{
write_byte(addr,*p); // 秒 分 時 日 月 星期 年
p++;
addr +=2;
}
write_byte(0x8e,0x80); // 控制命令,WP=1,防寫
}
//============ 讀ds1302當前日期和時間 =============
void read_ds1302(uchar *p)
{
uchar i;
uchar addr = 0x81;
for (i=0; i<7; i++)
{
*p = read_byte(addr); //格式為: 秒 分 時 日 月 星期 年
addr += 2;
p++;
}
}
//============ 顯示函數 ===================
void lcd_disp()
{
uchar addr = 4;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[2]>>4)&0x0f)+0x30); //顯示小時
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[2]&0x0f)+0x30);
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(':'); //顯示":"
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[1]>>4)&0x0f)+0x30); //顯示分
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[1]&0x0f)+0x30);
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(':'); //顯示":"
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[0]>>4)&0x0f)+0x30); //顯示秒
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[0]&0x0f)+0x30);
addr = 2;
lcd_wcmd(0xc0 + addr); //在第二行顯示年月日和星期
lcd_wdat('2'); //顯示2
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat('0'); //顯示0
addr++;
lcd_wdat(((time[6]>>4)&0x0f)+0x30); //年
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[6]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(((time[4]>>4)&0x0f)+0x30); //顯示月
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[4]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(((time[3]>>4)&0x0f)+0x30); //顯示日
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[3]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[5]&0x0f)+0x30); //顯示星期
}
//=========== 主函數 ===============
void main()
{
lcd_init(); // 初始化LCD
write_ds1302(time);
while(1)
{
read_ds1302(time); //讀DS1302數據
lcd_disp(); //LCD顯示
delay_ms(500); //延時0.5秒
}
}
這是一個電子時鍾,在LCD1602上顯示,時鍾晶元是DS1302
⑧ 基於單片機的電子時鍾
首先,硬體的選取:
1,單片機,其控制系統不算復雜,使用簡單的8位機即可,然後就是時鍾的選擇,本設計基於其實時性要求不高,所以時鍾盡量選擇低一點,可以用3M、6M的時鍾,因為時鍾選擇越高其單片機的功耗就越大,甚至出現超頻現象(不過現在的單片機時鍾一般都能達到50M了)!
2,顯示部分,根據本常式的要求,可以選用6個8位數碼管進行顯示。
3,驅動電路,數碼管驅動晶元有很多,常見的有串列通信的如74LS164、74HC595、SM1617等常用LED串列驅動晶元。
4,時鍾晶元的選擇,單片機上面有定時器,但是實現長時間的定時必定不準確,誤差很大,還得經常對時,所以建議你選用一款時鍾晶元,常用的DS1302等。
5,用戶界面,你就用幾個按鍵實現用戶操作就行了。
軟體:首先顯示部分的變成,在網上有很多常式,你只需要簡單的移植就可以使用了,時鍾晶元DS1302典型的IIC匯流排驅動模式,你可以使用單片機中IIC外設來訪問,按鍵部分使用掃描和外部中斷都可!
自己動手豐衣足食,寫了這么多,希望對你有用,加油
⑨ 51單片機實現電子時鍾
可以用中斷或者專門給調試這個子程序,調試時執行子程序,調試完跳出