① MCS--51单片机:1.利用定时器、数码管实现秒表(时分秒都要有)。2.实现可调日历。
KEYVAL EQU 30H
KEYTM EQU 31H
KEYSCAN EQU 32H
DAT EQU 33H
SCANLED EQU 39H
CLK EQU 77H
SEC EQU 78H
MIN EQU 79H
HOUR EQU 7AH
PAUSE BIT 00H
DOT BIT 01H
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP T0ISR ;50ms定时
ORG 001BH
LJMP T1ISR ;扫描显示
ORG 0030H
MAIN:
MOV SP,#5FH
MOV TMOD,#11H
MOV TH0,#03CH
MOV TL0,#0B0H
MOV TH1,#0ECH
MOV TL1,#078H
MOV KEYVAL,#0
MOV SCANLED,#0
MOV 33H,#10H
MOV 34H,#10H
MOV 35H,#10H
MOV 36H,#10H
MOV 37H,#10H
MOV 38H,#10H
MOV SEC,#0
MOV MIN,#0
MOV HOUR,#0
MOV CLK,#0
CLR PAUSE
SETB EA
SETB ET1
SETB TR1
LOOP:
LCALL KEYSEL
MOV A,KEYVAL
CJNE A,#0FFH,LOOP1
SJMP LOOP
LOOP1:
CJNE A,#10,LOOP2 ;“ON”启动
SETB TR0
SETB ET0
SETB PAUSE
SJMP LOOP
LOOP2:
CJNE A,#11,LOOP3 ;“=”清零
MOV SEC,#0
MOV MIN,#0
MOV HOUR,#0
LCALL DISCHG
SJMP LOOP
LOOP3:
CJNE A,#15,LOOP4 ;“+”暂停
CLR TR0
CLR ET0
CLR PAUSE
SJMP LOOP
LOOP4:
CJNE A,#14,LOOP5 ;“-”清显示暂停
MOV 33H,#10H
MOV 34H,#10H
MOV 35H,#10H
MOV 36H,#10H
MOV 37H,#10H
MOV 38H,#10H
CLR TR0
CLR ET0
CLR PAUSE
SJMP LOOP
LOOP5:
CJNE A,#10,LOOP6 ;数字键
LOOP6:
JC LOOP7
LJMP LOOP
LOOP7:
JNB PAUSE,LOOP8 ;暂停状态可以输入数字键
LJMP LOOP
LOOP8:
MOV 33H,34H
MOV 34H,35H
MOV 35H,36H
MOV 36H,37H
MOV 37H,38H
MOV 38H,KEYVAL
MOV A,33H
SWAP A
ORL A,34H
LCALL BCDH
MOV HOUR,A
MOV A,35H
SWAP A
ORL A,36H
LCALL BCDH
MOV MIN,A
MOV A,37H
SWAP A
ORL A,38H
LCALL BCDH
MOV SEC,A
LJMP LOOP
;------------------
;BCD转换为十六进制
BCDH:
MOV B,#10H
DIV AB
MOV R7,B
MOV B,#10
MUL AB
ADD A,R7
RET
;------------------
;十六进制转换为BCD
HBCD:
MOV B,#10
DIV AB
SWAP A
ORL A,B
RET
;------------------
KEYSEL:
MOV KEYVAL,#0
MOV KEYSCAN,#0EFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS1
MOV KEYVAL,A
SJMP KEYRTN
KEYS1:
MOV KEYSCAN,#0DFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS2
CLR C
ADD A,#4
MOV KEYVAL,A
SJMP KEYRTN
KEYS2:
MOV KEYSCAN,#0BFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS3
CLR C
ADD A,#8
MOV KEYVAL,A
SJMP KEYRTN
KEYS3:
MOV KEYSCAN,#7FH
LCALL GETKEY
MOV A,KEYTM
JZ KEYRTN
CLR C
ADD A,#12
MOV KEYVAL,A
KEYRTN:
LCALL CHGKEY
RET
;--------------------
GETKEY:
MOV KEYTM,#0
MOV A,KEYSCAN
MOV P3,A
NOP
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY
MOV R2,#10
LCALL DELAY
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY
MOV A,P3
ANL A,#0FH
MOV R7,A
SF:
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JNZ SF
MOV A,R7
CJNE A,#0EH,NK1
MOV KEYTM,#1
SJMP NOKEY
NK1:
CJNE A,#0DH,NK2
MOV KEYTM,#2
SJMP NOKEY
NK2:
CJNE A,#0BH,NK3
MOV KEYTM,#3
SJMP NOKEY
NK3:
CJNE A,#07H,NOKEY
MOV KEYTM,#4
NOKEY: RET
;--------------------
DELAY:
MOV R3,#50
DELAY1:
MOV R4,#100
DJNZ R4,$
DJNZ R3,DELAY1
DJNZ R2,DELAY
RET
;--------------------
T0ISR:
PUSH ACC
CLR TR0
MOV TH0,#3CH
MOV TL0,#0B0H
SETB TR0
INC CLK
MOV A,CLK
CJNE A,#20,T0ISRE
MOV CLK,#0
INC SEC
MOV A,SEC
CJNE A,#60,T0ISRE
MOV SEC,#0
INC MIN
MOV A,MIN
CJNE A,#60,T0ISRE
MOV MIN,#0
INC HOUR
MOV A,HOUR
CJNE A,#24,T0ISRE
MOV SEC,#0
MOV MIN,#0
MOV HOUR,#0
T0ISRE:
LCALL DISCHG
POP ACC
RETI
;--------------------
DISCHG:
MOV A,HOUR
LCALL HBCD
PUSH ACC
ANL A,#0FH
MOV 34H,A
POP ACC
ANL A,#0F0H
SWAP A
MOV 33H,A
MOV A,MIN
LCALL HBCD
PUSH ACC
ANL A,#0FH
MOV 36H,A
POP ACC
ANL A,#0F0H
SWAP A
MOV 35H,A
MOV A,SEC
LCALL HBCD
PUSH ACC
ANL A,#0FH
MOV 38H,A
POP ACC
ANL A,#0F0H
SWAP A
MOV 37H,A
RET
;--------------------
T1ISR:
PUSH ACC
CLR TR1
MOV TH1,#0ECH
MOV TL1,#78H
SETB TR1
MOV DPTR,#LEDTAB
T100:
MOV R0,#DAT
MOV A,SCANLED
ADD A,R0
MOV R0,A
MOV A,SCANLED
JNZ T101
MOV P2,#01H
CLR DOT
SJMP T1DIS
T101:
DEC A
JNZ T102
MOV P2,#02H
SETB DOT
SJMP T1DIS
T102:
DEC A
JNZ T103
MOV P2,#04H
CLR DOT
SJMP T1DIS
T103:
DEC A
JNZ T104
MOV P2,#08H
SETB DOT
SJMP T1DIS
T104:
DEC A
JNZ T105
MOV P2,#10H
CLR DOT
SJMP T1DIS
T105:
MOV P2,#20H
CLR DOT
T1DIS:
MOV A,@R0
MOVC A,@A+DPTR
JNB DOT,T1DIS1
ORL A,#01H
T1DIS1:
CPL A
MOV P0,A
INC SCANLED
MOV A,SCANLED
CJNE A,#6,T1END
MOV SCANLED,#0
T1END:
POP ACC
RETI
;--------------------
CHGKEY:
MOV A,KEYVAL
JZ KV16
DEC A
JNZ KV01
MOV KEYVAL,#7
RET
KV01:
DEC A
JNZ KV02
MOV KEYVAL,#4
RET
KV02:
DEC A
JNZ KV03
MOV KEYVAL,#1
RET
KV03:
DEC A
JNZ KV04
MOV KEYVAL,#10
RET
KV04:
DEC A
JNZ KV05
MOV KEYVAL,#8
RET
KV05:
DEC A
JNZ KV06
MOV KEYVAL,#5
RET
KV06:
DEC A
JNZ KV07
MOV KEYVAL,#2
RET
KV07:
DEC A
JNZ KV08
MOV KEYVAL,#0
RET
KV08:
DEC A
JNZ KV09
MOV KEYVAL,#9
RET
KV09:
DEC A
JNZ KV10
MOV KEYVAL,#6
RET
KV10:
DEC A
JNZ KV11
MOV KEYVAL,#3
RET
KV11:
DEC A
JNZ KV12
MOV KEYVAL,#11
RET
KV12:
DEC A
JNZ KV13
MOV KEYVAL,#12
RET
KV13:
DEC A
JNZ KV14
MOV KEYVAL,#13
RET
KV14:
DEC A
JNZ KV15
MOV KEYVAL,#14
RET
KV15:
DEC A
JNZ KV16
MOV KEYVAL,#15
RET
KV16:
MOV KEYVAL,#0FFH
RET
;--------------------
LEDTAB: DB 0FCH ;"0" 00H
DB 60H ;"1" 01H
DB 0DAH ;"2" 02H
DB 0F2H ;"3" 03H
DB 66H ;"4" 04H
DB 0B6H ;"5" 05H
DB 0BEH ;"6" 06H
DB 0E0H ;"7" 07H
DB 0FEH ;"8" 08H
DB 0F6H ;"9" 09H
DB 0EEH ;"A" 0AH
DB 3EH ;"B" 0BH
DB 9CH ;"C" 0CH
DB 7AH ;"D" 0DH
DB 9EH ;"E" 0EH
DB 8EH ;"F" 0FH
DB 00H ;" " 10H
;--------------------
② 51单片机 制作 日历时钟 用汇编语言 要详细的代码和硬件图示
你好这是基于DS1302日历时钟的单片机汇编程序 51单片机
ORG 0000H
MOV SP,#30H
LOAD EQU P2.0
CLR LOAD
MOV R0,#0FH
MOV R1,#0AH ;亮度
ACALL TRT
MOV R0,#02H
MOV R1,#0BH ;扫描位数
ACALL TRT
MOV R0,#0FFH
MOV R1,#09H ;译码
ACALL TRT
MOV R0,#01H
MOV R1,#0CH
CALL TRT
SETB P1.0
MOV 22H,#00H
;以下为按键扫描输入初值子程序
KEYSET: MOV 73H,#01H ;设温度初值为10度
MOV 74H,#00H
MOV 75H,#00H
CALL DISPLAY
KEY1: CALL KS1 ;调判断有无键按下子程序
JNZ LK1 ;有键按下(A)<>0转消抖延时
AJMP KEY1 ;无键按下返回,等键按下
LK1: CALL DEL10MS ;延时
CALL KS1 ;若有键按下则为真实按下
JNZ KEYI ;键按下(A)<>0转键扫描
AJMP KEY1 ;不是键按下返回
KEYI: JNB ACC.0,KEYR ;加1键未按下,转查减1键
LK2: CALL KS1 ;等待键释放
CALL DEL10MS
JNZ LK2 ;未释放,等待
INC 75H ;末位加1
MOV A,75H
CJNE A,#0AH,PPA
MOV 75H,#00H
INC 74H
MOV A,74H
CJNE A,#0AH,PPA
MOV 74H,#00H
INC 73H
PPA: CALL DISPLAY
AJMP KEY1 ;转再次扫描
KEYR: JNB ACC.1,KEYH ;减1键未按下,转查上限确认键
LK3: CALL KS1
CALL DEL10MS
JNZ LK3
MOV A,75H
CJNE A,#00H,PPC
MOV 75H,#09H
MOV A,74H
CJNE A,#00H,PPD
MOV 74H,#09H
DEC 73H
AJMP PPB
PPD: DEC 74H
AJMP PPB
PPC: DEC 75H
PPB: CALL DISPLAY
AJMP KEY1 ;再次扫描
KEYH: JNB ACC.2,KEYL ;上限键未按下,转查下限确认键
LK4: CALL KS1
CALL DEL10MS
JNZ LK4
MOV A,73H
MOV 70H,A ;保存上限
MOV A,74H
MOV 71H,A
MOV A,75H
MOV 72H,A
AJMP KEY1
;KEYL: JNB ACC.3,KEY1
LK5: CALL KS1
CALL DEL10MS
JNZ LK5
MOV A,73H
MOV 6DH,A ;保存下限
MOV A,74H
MOV 6EH,A
MOV A,75H
MOV 6FH,A
EX_CON: ;CPL P1.3 ;使用仪器测试时用
CALL DS18B20 ;转DS18B20采样子程序
CALL DISPLAY
;以下为后向通道控制部分
CONTROL:MOV A,73H
CJNE A,6DH,NEQA
MOV A,74H
CJNE A,6EH,NEQB
CLR P1.5
CLR P1.6
JMP EX_CON ;样温=下限,返回采样
NEQA: JNC NEQD ;CY=0,即(73H)>(6DH)时转比上限
SETB P1.5
CLR P1.6
JMP EX_CON
NEQB: JNC NEQD
SETB P1.5
CLR P1.6
JMP EX_CON
NEQD: MOV A,73H
CJNE A,70H,NEQE
MOV A,74H
CJNE A,71H,NEQF
CLR P1.5
CLR P1.6
JMP EX_CON ;样温=上限,返回采样
NEQE: JNC NEQH ;CY=0,即(73H)>(70H)时转打开降温开关
CLR P1.5
CLR P1.6
JMP EX_CON
NEQF: JNC NEQH
CLR P1.5
CLR P1.6
JMP EX_CON
NEQH: CLR P1.5
SETB P1.6
JMP EX_CON
KS1: MOV P0,#0FFH
MOV A,P0
CPL A
ANL A,#0FH
RET
DEL10MS:MOV R7,#20
S2: MOV R6,#250
S1: DJNZ R6,S1
DJNZ R7,S2
RET
;以下为显示
DISPLAY:MOV A,73H ;字码
MOV R0,A
MOV R1,#01H ;位置
ACALL TRT
MOV A,74H
MOV R0, A
MOV R1,#02H
ACALL TRT
MOV A,75H
MOV R0,A
MOV R1,#03H
ACALL TRT
RET
;JMP DIS
DS18B20:LCALL RESET ;测试温度探头存在否?
MOV A,#0CCH
LCALL WRITE
MOV A,#44H
LCALL WRITE ;命令字写入探头内
MOV R7,#70D ;延时
CALL DE11
LCALL RESET
MOV A,#0CCH
LCALL WRITE
MOV A,#0BEH
LCALL WRITE
LCALL READ ;读取探头内的温度值
MOV B,A
MOV 21H,A ;保存温度值低位
LCALL READ
MOV 20H,A ;保存温度值高位
LCALL EXCHANG ;温度值B转D并送入显示缓存
RET
RESET:
LA: SETB P1.0 ;复位
NOP
LB: CLR P1.0 ;480US < TS < 960US
MOV R7,#36D
CALL DE11
SETB P1.0 ;60US < T <90US
LC: MOV R7,#6D
CALL DE11
CLR C
ORL C,P1.0
JC LB
LF: MOV R7,#18D ;T > 270
CALL DE11
SETB P1.0
RET
WRITE:
MOV R3,#8
WR1: SETB P1.0
CLR P1.0 ;延时
MOV R4,#2
WR2: DJNZ R4,WR2
RRC A
MOV P1.0,C ;写的数据在线上需延时
MOV R4,#18
WR3: DJNZ R4,WR3
NOP
SETB P1.0
DJNZ R3,WR1
SETB P1.0
RET
READ:
MOV R3,#8
RD1: CLR C
SETB P1.0 ;适当延时
NOP
NOP
CLR P1.0 ;适当延时
NOP
NOP
SETB P1.0 ;延时
MOV R4,#9
RD2: DJNZ R4,RD2
MOV C,P1.0
RRC A
MOV R5,#23
RD3: DJNZ R5,RD3
DJNZ R3,RD1
RET
DELAY: MOV R7,#10
DL2: MOV R6,#200
DL1: MOV R5,#250
DL0: DJNZ R5,DL0
DJNZ R6,DL1
DJNZ R7,DL2
RET
EXCHANG: MOV A,21H
SWAP A
ANL A,#0FH
MOV 24H,A
MOV A,20H
ANL A,#07H
SWAP A
ADD A,24H
MOV B,#10D
DIV AB
MOV 73H,A
MOV 74H,B
MOV A,21H
ANL A,#0FH
mov dptr,#SADDR ;小数部分的转换查表
movc a,@a+dptr
MOV 75H,A
ret
SADDR: DB 00H,1H,02h ; bo_ying address in eeprom 0800h-0A08H
DB 03H,3H,04h ; da_ling address in eeprom 0A10H-0AD3H
DB 04H,05H,06h ;shou_ying address in eeprom 0AE0H-0C25H
DB 06H,7H,08h ; lu_ying address in eeprom 0C30H-0D75H
DB 08H,9H,9h,9H
DELAY15US: ;12MHZ ,15US
DE11: NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,DE11
RET
TRT: CLR P2.0 ;LOAD
MOV R2,#08H
MOV A,R1
T_1: CLR P2.2 ;SETB P2.2 ;CLK
RLC A
MOV P2.1,C ;DATA
CALL TDELAY
SETB P2.2 ;CLR P2.2
DJNZ R2,T_1
CALL TDELAY
MOV R2, #08H
MOV A,R0
TT2: CLR P2.2 ;SETB P2.2
RLC A
MOV P2.1,C
CALL TDELAY
SETB P2.2 ;CLR P2.2
DJNZ R2,TT2
SETB P2.0 ;CLR P2.0
RET
TDELAY: MOV R6,#01H
TMS0: MOV R7,#03H
TMS1: DJNZ R7,TMS1
DJNZ R6,TMS0
RET
③ 跪求 51单片机+12864液晶+1302时钟制成的万年历c程序
顶层文件 万年历.C
#include<reg51.h>
#include "LCD1602.h"
#include "DS1302.h"
#define uchar unsigned char
#define uint unsigned int
sbit speaker=P2^4;
bit key_flag1=0,key_flag2=0;
SYSTEMTIME adjusted;
uchar sec_add=0,min_add=0,hou_add=0,day_add=0,mon_add=0,yea_add=0;
uchar data_alarm[7]={0};
/************键盘控制******************************/
int key_scan() //扫描是否有键按下
{ int i=0;
uint temp;
P1=0xf0;
temp=P1;
if(temp!=0xf0)
i=1;
else
i=0;
return i;
}
uchar key_value() //确定按键的值
{
uint m=0,n=0,temp;
uchar value;
uchar v[4][3]={'2','1','0','5','4','3','8','7','6','b','a','9'} ;
P1=0xfe; temp=P1; if(temp!=0xfe)m=0;
P1=0xfd;temp=P1 ;if(temp!=0xfd)m=1;
P1=0xfb;temp=P1 ;if(temp!=0xfb)m=2;
P1=0xf7;temp=P1 ;if(temp!=0xf7)m=3;
P1=0xef;temp=P1 ;if(temp!=0xef)n=0;
P1=0xdf;temp=P1 ;if(temp!=0xdf)n=1;
P1=0xbf;temp=P1 ;if(temp!=0xbf)n=2;
value=v[m][n];
return value;
}
/***************************设置闹铃函数*******************************/
void naoling(void)
{
uchar i=0,l=0,j;
init1602();
while(key_flag2&&i<12)
if(key_scan()){j=key_value();write_data(j);if(i%2==0)data_alarm[l]=(j-'0')*10;else {data_alarm[l]+=(j-'0');l++;}i++;delay(600);}
write_com(0x01);
}
uchar according(void)
{ uchar k;
if(data_alarm[0]==adjusted.Year&&data_alarm[1]==adjusted.Month&&data_alarm[2]==adjusted.Day&&data_alarm[3]==adjusted.Hour&&data_alarm[4]==adjusted.Minute&&data_alarm[5]==adjusted.Second)
k=1;
else k=0;
return k;
}
void speak(void)
{uint i=50;
while(i)
{speaker=0;
delay(1);
speaker=1;
delay(1);
i--;
}
}
void alarm(void)
{uint i=10;
while(i)
{
speak();
delay(10);
i--;
}
}
/**************************修改时间操作********************************/
void reset(void)
{
sec_add=0;
min_add=0;
hou_add=0;
day_add=0;
mon_add=0;
yea_add=0 ;
}
void adjust(void)
{
if(key_scan()&&key_flag1)
switch(key_value())
{case '0':sec_add++;break;
case '1':min_add++;break;
case '2':hou_add++;break;
case '3':day_add++;break;
case '4':mon_add++;break;
case '5':yea_add++;break;
case 'b':reset();break;
default: break;
}
adjusted.Second+=sec_add;
adjusted.Minute+=min_add;
adjusted.Hour+=hou_add;
adjusted.Day+=day_add;
adjusted.Month+=mon_add;
adjusted.Year+=yea_add;
if(adjusted.Second>59) adjusted.Second=adjusted.Second%60;
if(adjusted.Minute>59) adjusted.Minute=adjusted.Minute%60;
if(adjusted.Hour>23) adjusted.Hour=adjusted.Hour%24;
if(adjusted.Day>31) adjusted.Day=adjusted.Day%31;
if(adjusted.Month>12) adjusted.Month=adjusted.Month%12;
if(adjusted.Year>100) adjusted.Year=adjusted.Year%100;
}
/**************************中断处理函数*********************************/
void changing(void) interrupt 0 using 0 //需要修改时间和日期,或者停止修改
{
if(key_flag1)key_flag1=0;
else key_flag1=1;
}
void alarming(void) interrupt 3 using 0 //需要设置闹铃或者停止设置
{
if(key_flag2)key_flag2=0;
else key_flag2=1;
}
/********************************主函数***********************************/
main()
{uint i;
uchar *l;
uchar p1[]="D:",p2[]="T:";
SYSTEMTIME T;
EA=1;
EX0=1;
IT0=1;
EA=1;
EX1=1;
IT1=1;
init1602();
Initial_DS1302() ;
while(1)
{ write_com(0x80);
write_string(p1,2);
write_com(0xc0);
write_string(p2,2);
DS1302_GetTime(&T) ;
adjusted.Second=T.Second;
adjusted.Minute=T.Minute;
adjusted.Hour=T.Hour;
adjusted.Week=T.Week;
adjusted.Day=T.Day;
adjusted.Month=T.Month;
adjusted.Year=T.Year;
for(i=0;i<9;i++)
{
adjusted.DateString[i]=T.DateString[i];
adjusted.TimeString[i]=T.TimeString[i];
}
adjust();
if(key_flag2)naoling();
if(according())alarm();
DateToStr(&adjusted);
TimeToStr(&adjusted);
write_com(0x82);
write_string(adjusted.DateString,8);
write_com(0xc2);
write_string(adjusted.TimeString,8);
delay(10);
}
(二)头文件1 显示模块 LCD1602.H
#ifndef LCD_CHAR_1602_2009_5_9
#define LCD_CHAR_1602_2009_5_9
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs = P2^0;
sbit lcdrw = P2^1;
sbit lcden = P2^2;
void delay(uint z) // 延时
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com) // 写入指令数据到 lcd
{
lcdrw=0;
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date) // 写入字符显示数据到 lcd
{
lcdrw=0;
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init1602() // 初始化设定
{
lcdrw=0;
lcden=0;
write_com(0x3C);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
void write_string(uchar *pp,uint n)
{
int i;
for(i=0;i<n;i++)
write_data(pp[i]);
}
#endif
(三)头文件2 时钟模块 DS1302.H
#ifndef _REAL_TIMER_DS1302_2009_5_20_
#define _REAL_TIMER_DS1302_2003_5_20_
sbit DS1302_CLK = P2^6; //实时时钟时钟线引脚
sbit DS1302_IO = P2^7; //实时时钟数据线引脚
sbit DS1302_RST = P2^5; //实时时钟复位线引脚
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
typedef struct SYSTEM_TIME
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[9]; //用这两个字符串来放置读取的时间
unsigned char TimeString[9];
}SYSTEMTIME; //定义的时间类型
#define AM(X) X
#define PM(X) (X+12) // 转成24小时制
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C
#define DS1302_RAM(X) (0xC0+(X)*2) //用于计算 DS1302_RAM 地址的宏
/******内部指令**********/
void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0;
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1; //因为在前面已经定义了ACC0 = ACC^0;以便再次利用DS1302_IO = ACC0;
}
}
unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1;
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}
/********************************/
void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 写1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
}
unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); // 地址,命令
ucData = DS1302OutputByte(); // 读1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}
void DS1302_SetProtect(bit flag) //是否写保护
{
if(flag)
Write1302(0x8E,0x10);
else
Write1302(0x8E,0x00);
}
void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数
{
DS1302_SetProtect(0);
Write1302(Address, ((Value/10)<<4 | (Value%10))); //将十进制数转换为BCD码
} //在DS1302中的与日历、时钟相关的寄存器存放的数据必须为BCD码形式
void DS1302_GetTime(SYSTEMTIME *Time)
{
unsigned char ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将BCD码转换为十进制数
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}
unsigned char *DataToBCD(SYSTEMTIME *Time)
{
unsigned char D[8];
D[0]=Time->Second/10<<4+Time->Second%10;
D[1]=Time->Minute/10<<4+Time->Minute%10;
D[2]=Time->Hour/10<<4+Time->Hour%10;
D[3]=Time->Day/10<<4+Time->Day%10;
D[4]=Time->Month/10<<4+Time->Month%10;
D[5]=Time->Week/10<<4+Time->Week%10;
D[6]=Time->Year/10<<4+Time->Year%10;
return D;
}
void DateToStr(SYSTEMTIME *Time)
{
//将十进制数转换为液晶显示的ASCII值
Time->DateString[0] = Time->Year/10 + '0';
Time->DateString[1] = Time->Year%10 + '0';
Time->DateString[2] = '-';
Time->DateString[3] = Time->Month/10 + '0';
Time->DateString[4] = Time->Month%10 + '0';
Time->DateString[5] = '-';
Time->DateString[6] = Time->Day/10 + '0';
Time->DateString[7] = Time->Day%10 + '0';
Time->DateString[8] = '\0';
}
void TimeToStr(SYSTEMTIME *Time)
{
//将十进制数转换为液晶显示的ASCII值
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
Time->TimeString[2] = ':';
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
Time->TimeString[5] = ':';
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0';
Time->DateString[8] = '\0';
}
void Initial_DS1302(void)
{
unsigned char Second;
Second=Read1302(DS1302_SECOND);
if(Second&0x80) //初始化时间
DS1302_SetTime(DS1302_SECOND,0);
}
void DS1302_TimeStop(bit flag) // 是否将时钟停止
{
unsigned char Data;
Data=Read1302(DS1302_SECOND);
DS1302_SetProtect(0);
if(flag)
Write1302(DS1302_SECOND, Data|0x80);
else
Write1302(DS1302_SECOND, Data&0x7F);
}
#endif
④ 求51单片机日历/时钟设计
10分求这么多???
嘿嘿。。。
有点困难哦。。
网上有例程的。
看看。。。
81708034 加我,有不明白的地方我可以告诉你。
⑤ 基于51单片机的电子日历,DS1302接了晶振了,那么单片机还需要接晶振吗
DS1302 接的 32.768K 晶振是为 DS1302 提供标准时钟源的,跟单片机无关。
至于单片机需根据实际情况需要使用或不使用晶振。
例如有些 STC 单片机可使用内置几M的RC震荡器,这种情况可以取消单片机的晶振。
⑥ 用51单片机做日历时钟 【软件仿真】
首先确定方案,既然用51单片机首先先构造一个最小系统,然后再最小系统的基础上构建外围电路,既然是时钟,就要有显示电路,显示你可以用LED或是LCD,如果你要做特别精确地时钟,建议使用时钟芯片,要是不是也别严格可以用单片机的定时器,再下来就可以考虑电子时钟的一些功能,比如时间设定,这就需要按键了,个人的理解啊,
⑦ 51单片机制做日历
看看这个程序嘛,,虽然没有你要得年月日,但是有时间得啊。。。可以借此来点灵感。。我也在做这个东西。。。我还在收集资料啊。。。共同学习。。
;采用8位LED软件译码动态显示程序
;使用AT89C51单片机,12MHZ晶振,P0输出字段码,P2口输出位选码,用共阳
;LED数码管,P1.0为调时位选择按键,P1.1为加1键,P1.2为减1键。
;片内RAM的70H到77H单元为LED数码管的显示缓冲区
;78H,79H,7AH分别为秒、分、小时计数单元
;7BH为50ms计数器,7CH为调时按键计数器
ORG 0000H
LJMP START
ORG 000BH ;定时器/计数器T0中断程序入口
LJMP INTT0
;主程序
START:MOV R0,#70H
MOV R7,#0CH
INIT: MOV @R0,#00H
INC R0
DJNZ R7,INIT
MOV 72H,#10
MOV 75H,#10
MOV TMOD,#01H
MOV TL0,#0B0H
MOV TH0,#03CH
SETB EA
SETB ET0
SETB TR0
START1: LCALL SCAN
LCALL KEYSCAN
SJMP START1
;延时1MS子程序
DL1MS: MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
RET
;延时20MS子程序
DL20MS: ACALL SCAN
ACALL SCAN
ACALL SCAN
RET
;数码管显示程序
SCAN: MOV A,78H ;时间存入显示缓冲区相应位置
MOV B,#0AH
DIV AB
MOV 71H,A
MOV 70H,B
MOV A,79H
MOV B,#0AH
DIV AB
MOV 74H,A
MOV 73H,B
MOV A,7AH
MOV B,#0AH
DIV AB
MOV 77H,A
MOV 76H,B
MOV R1,#70H ;循环扫描显示
MOV R5,#80H
MOV R3,#08H
SCAN1: MOV A,R5
MOV P2,A
MOV A,@R1
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
MOV A,R5
LCALL DL1MS
INC R1
MOV A,R5
RR A
MOV R5,A
DJNZ R3,SCAN1
MOV P2,#00H
MOV P0,#0FFH
RET
TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0BFH
;“0~9”,“-”的共阳极字段码
;定时器/计数器T0中断服务程序
INTT0: PUSH ACC
PUSH PSW
CLR ET0
CLR TR0
MOV TL0,#0B0H
MOV TH0,#03CH
SETB TR0
INC 7BH
MOV A,7BH
CJNE A,#14H,OUTT0
MOV 7BH,#00
INC 78H
MOV A,78H
CJNE A,#3CH,OUTT0
MOV 78H,#00
INC 79H
MOV A,79H
CJNE A,#3CH,OUTT0
MOV 79H,#00
INC 7AH
MOV A,7AH
CJNE A,#18H,OUTT0
MOV 7AH,#00
OUTT0:
SETB ET0
pop psw
pop acc
RETI
;按键处理程序
KEYSCAN: CLR EA
JNB P1.0,KEYSCAN0
JNB P1.1,KEYSCAN1
JNB P1.2,KEYSCAN2
KEYOUT: SETB EA
RET
KEYSCAN0: LCALL DL20MS
JB P1.0,KEYOUT
WAIT0: JNB P1.0,WAIT0
INC 7CH
MOV A,7CH
CLR TR0
CLR ET0
CJNE A,#03H,KEYOUT
MOV 7CH,#00
SETB TR0
SETB ET0
SJMP KEYOUT
KEYSCAN1: LCALL DL20MS
JB P1.1,KEYOUT
WAIT1: JNB P1.1,WAIT1
MOV A,7CH
CJNE A,#02H,KSCAN11
INC 79H
MOV A,79H
CJNE A,#3CH,KEYOUT
MOV 79H,#00
SJMP KEYOUT
KSCAN11: INC 7AH
MOV A,7AH
CJNE A,#18H,KEYOUT
MOV 7AH,#00
SJMP KEYOUT
KEYSCAN2: LCALL DL20MS
JB P1.2,KEYOUT
WAIT2: JNB P1.2,WAIT2
MOV A,7CH
CJNE A,#02H,KSCAN21
DEC 79H
MOV A,79H
CJNE A,#0FFH,KEYOUT
MOV 79H,#3BH
SJMP KEYOUT
KSCAN21: DEC 7AH
MOV A,7AH
CJNE A,#0FFH,KEYOUT
MOV 7AH,#17H
SJMP KEYOUT
END
⑧ C51单片机的万年历程序设计
我这有个数码管显示的程序
以前做的,。。
你可以在我这个程序上修改修改
包括键盘扫描,还有动态显示
。
。
【。。。】
#include
//常量参数
#define TMODW 0x01;
#define SCONW 0x00;
#define xplay 0x04;//显示分频系数
//显示位选
unsigned char data stb;
//键值缓存,0xFF无键命令
unsigned char data keynum;
//显示字型变量
unsigned char data play[8];
//工作参数
unsigned char data l,m;
//字型码
unsigned char code BCDPC[10]=
{0x3F,0x06,0x5B,0x4F,0x66,
0x6D,0x7D,0x07,0x7F,0x6F};
//字位码
unsigned char code STBCODE[8]=
{0x01,0x02,0x04,0x08,
0x10,0x20,0x40,0x80 };
//400Hz xplay分频计数
unsigned char data cttime;
//时钟参数
unsigned char data hr,min,sec,sec100;
//调整时钟参数(时钟“走”)
void ct1()
{sec100++;
if (sec100==100)
{sec100=0;sec++;
if (sec==60)
{sec=0;min++;
if (min==60)
{min=0;hr++;
if (hr==24) hr=0;
}
}
}
}
//时钟参数→LED 显示缓存7段参数转换函数;
void xcplay()
{play[0]=BCDPC[hr/10];
play[1]=BCDPC[hr%10];
play[2]=BCDPC[min/10];
play[3]=BCDPC[min%10];
play[4]=BCDPC[sec/10];
play[5]=BCDPC[sec%10];
play[6]=BCDPC[sec100/10];
play[7]=BCDPC[sec100%10];
}
//显示扫描
void cplay()
{T0=1;//T0-高电平消隐
T1=0;//T1-低电平准备发脉冲前沿
TI=0;//?
P1=0;//?
SBUF=STBCODE[stb];
while (TI==0)
{
};
TI=0;
SBUF=play[stb];
while (TI==0)
{
};
T1=1;
T0=0;
stb=++stb&0x07;
}
extern void cthl0();
//定时器0中断处理程序
void ct0(void) interrupt 1 using 1
{cthl0();
cttime--;
if (cttime==0)
{cttime=xplay;
ct1();//调用时钟“走”函数
xcplay();//调用时钟参数→Led显示缓存转换函数
};
cplay();
}
void w20ms()
{for (l=0;l<41;l++)
{for (m=0;m<81;m++)
{
}
}
}
void tkey()
{P1=0xF0;
keynum=0xFF;
if (P1!=0xF0)
{w20ms();
P1=0xF0;
if (P1!=0xF0)
{P1=0xFE;
switch (P1)
{case 0xEE:keynum=0;break;
case 0xDE:keynum=1;break;
case 0xBE:keynum=2;break;
case 0x7E:keynum=3;break;
}
P1=0xFD;
switch (P1)
{case 0xED:keynum=4;break;
case 0xDD:keynum=5;break;
case 0xBD:keynum=6;break;
case 0x7B:keynum=7;break;
}
P1=0xFB;
switch (P1)
{
case 0xEB:keynum=8;break;
}
};
};
P1=0x00;
}
void command()
{switch (keynum)
{
case 0:{hr=hr+1;
if (hr==24)
hr=0;
}
break;
case 1:{min=min+1;
if (min==60)
min=0;
}
break;
case 2:{sec=sec+1;
if (sec==60)
sec=0;
}
break;
case 3:{sec100=0;
}
break;
case 4:{
while(!(P1=0xED))
{
hr=0;
min=0;
sec=0;
}
}
break;
case 5:{hr=hr-1;
if (hr==00)
hr=24;
}
break;
case 6:{min=min-1;
if (min==00)
min=59;
}
break;
case 7:{sec=sec-1;
if (sec==00)
sec=0;
}
break;
case 0xFF:break;
}
keynum=0xFF;
}
main ()
{ hr=8;
min=5;
sec=8;
sec100=0;
TMOD=TMODW;
SCON=SCONW;
ET0=1;
TR0=1;
EA=1;
cttime=xplay;
while (1)
{w20ms();
tkey();
command();
};
}
⑨ 51单片机做的万年历有必要加看门狗吗
没必要,基本没什么干扰,单片机不会死机的。
但是如果你的系统里设置了某些需要保存的数据,比如定时闹钟什么的,需要保存起来而且掉电不丢失,这时你可能需要一个外置的EEPROM,而看门狗芯片往往也有EEPROM功能,这时可以加一个,一举两得。