ME300實例-LED數(shù)碼管顯示電子鐘(匯編、C語言)
演示圖片:
源程序
;*??描述:???????????????????????????????????????????????????????????????????????*
;*?????????簡易電子時鐘,數(shù)碼管顯示??????????????????????????????????????????????*
;*?????????K1---時調(diào)整??????????????????????????????????????????????????????????*
;*?????????K2---分調(diào)整??????????????????????????????????????????????????????????*
;*??????????????????????????????????????????????????????????????????????????????*
;*??????????????????????????????????????????????????????????????????????????????*
CODE_SEG?SEGMENT?CODE?
DATA_SEG?SEGMENT?DATA?
STACK_SEG?SEGMENT?IDATA
K1?BIT?P1.4
K2?BIT?P1.5
?RSEG??DATA_SEG
KEY_S:??DS???1
KEY_V:????DS???1
DIS_DIGIT:????DS???1
SEC:?????DS???1
DIS_INDEX:???DS????1
HOUR:????DS????1
MIN:?????DS????1
SEC100:????DS????1
DIS_BUF:????DS????8
????????
BUF_HOUR_H?EQU?DIS_BUF??;?小時十位
BUF_HOUR_L?EQU?DIS_BUF+1?;?小時個位
BUF_MIN_H?EQU?DIS_BUF+3?;?分十位
BUF_MIN_L?EQU?DIS_BUF+4?;?分個位
BUF_SEC_H?EQU?DIS_BUF+6?;?秒十位
BUF_SEC_L?EQU?DIS_BUF+7?;?秒個位
?RSEG?STACK_SEG
STACK:?DS?20?
?
;=======================================================
CSEG?AT?0000H
?JMP?MAIN
?
CSEG?AT?0000BH
?LJMP?TIMER0?
CSEG?AT?0001BH
?LJMP?TIMER1
;===================================================
?RSEG??CODE_SEG
MAIN:
?USING?0
?
?MOV?SP,?#(STACK-1)??;
?
?
?MOV???P0,#0FFH
?MOV???P2,#0FFH
?MOV???TMOD,#011H??;?定時器0,?1工作模式1,?16位定時方式
?MOV???TH0,#0FCH
?MOV???TL0,#017H
?MOV???TH1,#0DCH
?CLR???A
?MOV???TL1,A
?
?MOV???HOUR,#12??;?
?CLR?A???;?
?MOV???MIN,A
?MOV???SEC,A
?MOV???SEC100,A
?
?MOV???A,HOUR
?MOV???B,#10
?DIV???AB
?MOV???DPTR,#DIS_CODE
?MOVC??A,@A+DPTR
?MOV???BUF_HOUR_H,A??;?時十位
?MOV???A,HOUR
?MOV???B,#10
?DIV???AB
?MOV???A,B
?MOVC??A,@A+DPTR
?MOV???BUF_HOUR_L,A??;?時個位
?MOV???A,MIN
?MOV???B,#10
?DIV???AB
?MOVC??A,@A+DPTR
?MOV???BUF_MIN_H,A??;?分十位
?MOV???A,MIN
?MOV???B,#10
?DIV???AB
?MOV???A,B
?MOVC??A,@A+DPTR
?MOV???BUF_MIN_L,A??;?分個位
?MOV???A,SEC
?MOV???B,#10
?DIV???AB
?MOVC??A,@A+DPTR
?MOV???BUF_SEC_H,A??;?秒十位
?MOV???A,SEC
?MOV???B,#10
?DIV???AB
?MOV???A,B
?MOVC??A,@A+DPTR
?MOV???BUF_SEC_L,A??;?秒個位
?
?MOV???BUF_HOUR_H+02H,#0BFH
?MOV???BUF_HOUR_H+05H,#0BFH
?
?MOV???DIS_DIGIT,#0FEH
?CLR?A
?MOV???DIS_INDEX,A
?
?MOV???IE,#08AH??;?使能timer0,1?中斷
?
?SETB?TR0
?SETB?TR1
?
?MOV???KEY_V,#03H
?
MAIN_LP:
?LCALL?SCAN_KEY??;?鍵掃描
?JZ???MAIN_LP???;?無鍵返回
?
?MOV?R7,#10???;?延時10ms
?LCALL?DELAYMS???;?延時去抖動
?LCALL?SCAN_KEY??;?再次掃描
?JZ?MAIN_LP???;?無鍵返回
?
?MOV???KEY_V,KEY_S??;?保存鍵值
?LCALL?PROC_KEY??;?鍵處理
?SJMP?MAIN_LP???;?調(diào)回主循環(huán)
;=======================================================
SCAN_KEY:
;?掃鍵掃描子程序
;?保存按鍵狀態(tài)到key_s
;?返回:?A?---?按鍵是否按下(BOOL)
?CLR?A
?
?MOV???C,K1???;?讀按鍵K1
?MOV?ACC.0,C
?MOV?C,K2???;?讀按鍵K2
?MOV?ACC.1,C
?
?MOV?KEY_S,A???;??保存按鍵狀態(tài)到key_s
?XRL???A,KEY_V
?RET???
;========================================================
PROC_KEY:
;?鍵處理子程序
;?傳入參數(shù):?KEY_V?---?按鍵值
;?返回值:?無
?CLR???EA
?
?MOV???A,KEY_V
?JNB?ACC.0,PROC_K1
?JNB?ACC.1,PROC_K2
?SJMP?END_PROC_KEY
?
PROC_K1:????;?按鍵k1處理
?LCALL?INC_HOUR??;?小時加1
?SJMP??END_PROC_KEY
PROC_K2:????;?按鍵K2處理
?INC???MIN???;?分鐘加1
?
?MOV???A,MIN???;?
?SETB??C
?SUBB??A,#59?
?JC????K2_UPDATE_MIN??;?如果分鐘等于60,則分清0,小時加1
?
?CLR???A???;?
?MOV???MIN,A
K2_UPDATE_MIN:????;?更新分顯示緩沖區(qū)
?MOV???A,MIN
?MOV???B,#10
?DIV???AB???;?A?=?MIN?/?10?
?MOV???DPTR,#DIS_CODE
?MOVC??A,@A+DPTR
?MOV???BUF_MIN_H,A??;?更新分十位
?
?MOV???A,MIN
?MOV???B,#10
?DIV???AB
?MOV???A,B???;?A?=?MIN?%?10
?MOVC??A,@A+DPTR
?MOV???BUF_MIN_L,A??;?更新分個位?
?
END_PROC_KEY:
?SETB??EA
?RET???
;========================================================
?USING?0
TIMER0:
;?定時器0中斷服程序,?用于數(shù)碼管的動態(tài)掃描
;?DIS_INDEX?---?顯示索引,?用于標識當前顯示的數(shù)碼管和緩沖區(qū)的偏移量
;?DIS_DIGIT?---?位選通值,?傳送到P2口用于選通當前數(shù)碼管的數(shù)值,?如等于0xfe時,
;??選通P2.0口數(shù)碼管
;?DIS_BUF???---?顯于緩沖區(qū)基地址??
?PUSH??ACC
?PUSH??PSW
?PUSH??AR0
?
?MOV???TH0,#0FCH
?MOV???TL0,#017H
?
?MOV???P2,#0FFH??;?先關閉所有數(shù)碼管
?
?MOV???A,#DIS_BUF??;?獲得顯示緩沖區(qū)基地址
?ADD???A,DIS_INDEX??;?獲得偏移量
?MOV???R0,A???;?R0?=?基地址?+?偏移量
?MOV???A,@R0???;?獲得顯示代碼
?MOV???P0,A???;?顯示代碼傳送到P0口
?
?MOV???P2,DIS_DIGIT
?MOV?A,DIS_DIGIT??;?位選通值左移,?下次中斷時選通下一位數(shù)碼管
?RL?A
?MOV?DIS_DIGIT,A
?
?INC?DIS_INDEX??;?DIS_INDEX加1,?下次中斷時顯示下一位
?ANL?DIS_INDEX,#0x07??;?當DIS_INDEX等于8(0000?1000)時,?清0
?POP???AR0
?POP???PSW
?POP???ACC
?
?RETI??
;==================================================
?USING?0
TIMER1:
;?定時器1中斷服務程序,?產(chǎn)生時基信號10ms
;?
;
?PUSH?PSW
?PUSH??ACC
?PUSH??B
?PUSH??DPH
?PUSH??DPL
?
?MOV???TH1,#0DCH
?
?INC???SEC100
?
?MOV???A,SEC100
?CLR???C
?SUBB??A,#100???;?是否中斷100次(達到1s)
?JC????END_TIMER1??;?1S
?
?MOV???SEC100,#00H??;?達到1s?
?LCALL?INC_SEC???;?秒加1?
?
END_TIMER1:
?POP???DPL
?POP???DPH
?POP???B
?POP???ACC
?POP?PSW
?
?RETI?????;?
;========================================================
INC_SEC:
?INC???SEC
?
?MOV???A,SEC
?SETB??C
?SUBB??A,#59???;?
?JC????UPDATE_SEC
?
?CLR???A
?MOV???SEC,A
?LCALL?INC_MIN
?
UPDATE_SEC:
?MOV???A,SEC
?MOV???B,#10
?DIV???AB???;?A?=?SEC?/?10
?MOV???DPTR,#DIS_CODE
?MOVC??A,@A+DPTR??;?
?MOV???BUF_SEC_H,A??;?
?
?MOV???A,SEC
?MOV???B,#10
?DIV???AB
?MOV???A,B???;?A?=?SEC?%?10
?MOVC??A,@A+DPTR
?MOV???BUF_SEC_L,A
?RET???
;========================================================
INC_MIN:
?INC???MIN???;?分鐘加1
?
?MOV???A,MIN???;?
?SETB??C
?SUBB??A,#59?
?JC????UPDATE_MIN??;?如果分鐘等于60,則分清0,小時加1
?
?CLR???A???;?
?MOV???MIN,A
?LCALL?INC_HOUR??;?小時加1
?
UPDATE_MIN:????;?更新分顯示緩沖區(qū)
?MOV???A,MIN
?MOV???B,#10
?DIV???AB???;?A?=?MIN?/?10?
?MOV???DPTR,#DIS_CODE
?MOVC??A,@A+DPTR
?MOV???BUF_MIN_H,A??;?更新分十位
?
?MOV???A,MIN
?MOV???B,#10
?DIV???AB
?MOV???A,B???;?A?=?MIN?%?10
?MOVC??A,@A+DPTR
?MOV???BUF_MIN_L,A??;?更新分個位
?
?RET???
;===========================================================
INC_HOUR:
?INC???HOUR???;?小時加1?
?MOV???A,HOUR
?SETB??C
?SUBB??A,#24
?JC????UPDATE_HOUR??;?如果小時等于24,則小時清0
?
?CLR???A
?MOV???HOUR,A???;?小時清0?
?
UPDATE_HOUR:
?MOV???A,HOUR
?SETB??C
?SUBB??A,#9
?JC????UPDATE_HOUR1??;?如果小時小于10,則十位0不顯示
?
?MOV???A,HOUR
?MOV???B,#10
?DIV???AB
?MOV???DPTR,#DIS_CODE
?MOVC??A,@A+DPTR??;?
?MOV???BUF_HOUR_H,A
?SJMP??UPDATE_HOUR2
?
UPDATE_HOUR1:
?MOV???BUF_HOUR_H,#0FFH
?
UPDATE_HOUR2:
?MOV???A,HOUR
?MOV???B,#10
?DIV???AB
?MOV???A,B
?MOV???DPTR,#DIS_CODE
?MOVC??A,@A+DPTR
?MOV???BUF_HOUR_L,A
?RET???
;=================================================
DELAYMS:
;?延時子程序
;?傳入?yún)?shù):R7?---?延時值(MS)?
;?返回值:無
?MOV?A,R7
?JZ?END_DLYMS?
DLY_LP1:
?MOV?R6,#185
DLY_LP2:
?NOP
?NOP
?NOP
?DJNZ?R6,DLY_LP2
?DJNZ?R7,DLY_LP1
END_DLYMS:
?RET?
?
;?END?OF?DELAYMS??
;======================================================
DIS_CODE:
?DB?0C0H
?DB?0F9H
?DB?0A4H
?DB?0B0H
?DB?099H
?DB?092H
?DB?082H
?DB?0F8H
?DB?080H
?DB?090H
?DB?0FFH
?END
=========================
源程序(C語言)
*??描述:???????????????????????????????????????????????????????????????????????*
*?????????????????簡易電子時鐘,LED數(shù)碼管顯示??????????????????????????????????*
*?????????????????K1---時調(diào)整??????????????????????????????????????????????????*
*?????????????????K2---分調(diào)整??????????????????????????????????????????????????*
*??????????????????????????????????????????????????????????????????????????????*
*?????????????????上電時初始化顯示:??12-00-00??????????????????????????????????*
*??????????????????????????????????????????????????????????????????????????????*
*???????????*????****??????????****????****??????????****????****??????????????*
*???????????*????????*????????*????*??*????*????????*????*??*????*?????????????*
*???????????*????????*????????*????*??*????*????????*????*??*????*?????????????*
*???????????*????****??******?*????*??*????*?******?*????*??*????*?????????????*
*???????????*???*?????????????*????*??*????*????????*????*??*????*?????????????*
*???????????*???*?????????????*????*??*????*????????*????*??*????*?????????????*
*???????????*????****??????????****????****??????????****????****??????????????*
*??????????????????????????????????????????????????????????????????????????????*
*??????????????????????????????????????????????????????????????????????????????*
#include?
#include?
unsigned?char?data?dis_digit;
unsigned?char?key_s,?key_v;
unsigned?char?code?dis_code[11]={0xc0,0xf9,0xa4,0xb0,?//?0,?1,?2,?3
????0x99,0x92,0x82,0xf8,0x80,0x90,?0xff};//?4,?5,?6,?7,?8,?9,?off?
unsigned?char?data?dis_buf[8];
unsigned?char?data?dis_index;
unsigned?char?hour,min,sec;
unsigned?char?sec100;?
sbit?K1?=?P1^4;
sbit?K2?=?P1^5;
bit?scan_key();
void?proc_key();
void?inc_sec();
void?inc_min();
void?inc_hour();
void?display();
void?delayms(unsigned?char?ms);
void?main(void)
{
?P0?=?0xff;
?P2?=?0xff;
?TMOD?=?0x11;??//?定時器0,?1工作模式1,?16位定時方式
?TH1?=?0xdc;
?TL1?=?0;
?TH0?=?0xFC;
?TL0?=?0x17;
?
?hour?=?12;
?min?=?00;
?sec?=?00;
?sec100?=?0;
?
?dis_buf[0]?=?dis_code[hour?/?10];??//?時十位
?dis_buf[1]?=?dis_code[hour?%?10];??//?時個位
?dis_buf[3]?=?dis_code[min?/?10];??//?分十位
?dis_buf[4]?=?dis_code[min?%?10];??//?分個位
?dis_buf[6]?=?dis_code[sec?/?10];??//?秒十位
?dis_buf[7]?=?dis_code[sec?%?10];??//?秒個位
?dis_buf[2]?=?0xbf;??????//?顯示"-"
?dis_buf[5]?=?0xbf;??????//?顯示"-"
???
?dis_digit?=?0xfe;
?dis_index?=?0;
?
?TCON?=?0x01;
?IE?=?0x8a;????//?使能timer0,1?中斷
?
?TR0?=?1;
?TR1?=?1;
?key_v?=?0x03;
?while(1)
?{
??if(scan_key())
??{
???delayms(10);
???if(scan_key())
???{
????key_v?=?key_s;
????proc_key();
???}
??}
??
?}
}
bit?scan_key()
{
?key_s?=?0x00;
?key_s?|=?K2;
?key_s?<<=?1;
?key_s?|=?K1;
?return(key_s?^?key_v);?
}
void?proc_key()
{
?EA?=?0;
?if((key_v?&?0x01)?==?0)??//?K1
?{
??inc_hour();
?}
?else?if((key_v?&?0x02)?==?0)?//?K2
?{
??min++;
??if(min?>?59)
??{
???min?=?0;
??}
??dis_buf[3]?=?dis_code[min?/?10];??//?分十位
??dis_buf[4]?=?dis_code[min?%?10];??//?分個位
?}
?EA?=?1;
}
void?timer0()?interrupt?1
//?定時器0中斷服務程序,?用于數(shù)碼管的動態(tài)掃描
//?dis_index?---?顯示索引,?用于標識當前顯示的數(shù)碼管和緩沖區(qū)的偏移量
//?dis_digit?---?位選通值,?傳送到P2口用于選通當前數(shù)碼管的數(shù)值,?如等于0xfe時,
//????選通P2.0口數(shù)碼管
//?dis_buf???---?顯于緩沖區(qū)基地址?
{
?TH0?=?0xFC;
?TL0?=?0x17;
?
?P2?=?0xff;???????//?先關閉所有數(shù)碼管
?P0?=?dis_buf[dis_index];???//?顯示代碼傳送到P0口
?P2?=?dis_digit;??????//?
?dis_digit?=?_crol_(dis_digit,1);?//?位選通值左移,?下次中斷時選通下一位數(shù)碼管
?dis_index++;??????//?
?????
?dis_index?&=?0x07;???//?8個數(shù)碼管全部掃描完一遍之后,再回到第一個開始下一次掃描
}?
void?timer1()?interrupt?3
{
?TH1?=?0xdc;
?
?sec100++;
?
?if(sec100?>=?100)
?{
??sec100?=?0;
??inc_sec();
?}
}
void?inc_sec()
{
?sec++;
?if(sec?>?59)
?{
??sec?=?0;
??inc_min();
?}
?dis_buf[6]?=?dis_code[sec?/?10];??//?秒十位
?dis_buf[7]?=?dis_code[sec?%?10];??//?秒個位?
}
void?inc_min()
{
?min++;
?if(min?>?59)
?{
??min?=?0;
??inc_hour();
?}
?dis_buf[3]?=?dis_code[min?/?10];??//?分十位
?dis_buf[4]?=?dis_code[min?%?10];??//?分個位
}
void?inc_hour()
{
?hour++;
?if(hour?>?23)
?{
??hour?=?0;
?}
?if(hour?>?9)
??dis_buf[0]?=?dis_code[hour?/?10];??//?時十位
?else
??dis_buf[0]?=?0xff;?????//?當小時的十位為0時不顯示
?dis_buf[1]?=?dis_code[hour?%?10];??//?時個位
}
void?delayms(unsigned?char?ms)?
//?延時子程序
{??????
?unsigned?char?i;
?while(ms--)
?{
??for(i?=?0;?i?120;?i++);
?}
}
評論
查看更多