$MOD51 RS equ 0b5h ;labelling RS of LCD RW equ 0b6h ;labelling RW of LCD EN equ 0b7h ;labelling Enable of LCD up equ 0a7h ;labelling UP key down equ 0a6h ;labelling DOWN key enter equ 0a5h ;labelling ENTER key alarm_key equ 0a4h ;labelling ALARM key buzzer equ 0b3h ;labelling Buzzer count equ 10h disp_data equ 11h lcdcom equ 12h disp_var1 equ 13h disp_var0 equ 14h secs equ 15h ;sec, min, hour RAM location mins equ 16h hour equ 17h ampm equ 18h temp_secs equ 19h ;RAM variable to track 1second temp_mins equ 1ah temp_hour equ 1bh temp_ampm equ 1ch alarm_secs equ 1dh ;Alarm sec, min, hour RAM location alarm_mins equ 1eh alarm_hour equ 1fh alarm_ampm equ 20h time1sec equ 21h TMP_3 equ 22h TMP_2 equ 23h TMP_1 equ 24h TMP_0 equ 25h tt3 equ 26h ;dec_to_hex input ,dividiend and quotient tt2 equ 27h tt1 equ 28h tt0 equ 29h out7 equ 2ah ;don't change their location out6 equ 2bh out5 equ 2ch out4 equ 2dh out3 equ 2eh out2 equ 2fh out1 equ 30h out0 equ 31h hex1 equ 32h hex0 equ 33h counter1 equ 34h alarm_status equ 35h ;Alarm flag, alarm_match equ 3ch ;Alarm match flag org 0000h ;Start of the progrma ljmp program_start org 001bh ;T1 timer interrupt vector ljmp intr_service org 0040h program_start: mov sp,#50h ;Initializing stack pointer clr buzzer ;stop buzzer mov count,#00h lcall lcd_initialize ;calling initialize lcd routine lcall delay14m mov counter1,#00h lcall cursoroff lcall welcome_msg ;calling welcome message routine lcall cursoron mov time1sec,#64h lcall clear_lcd mov dptr,#0620h ;message "Enter Clock Time" display on LCD lcall display_text lcall enter_time ;routine to enter TIME lcall copy_time ;copy entered time as current time setb alarm_key mov alarm_status,#00h ;Alarm flag, default deactivated mov alarm_match,#00h ;alarm match flag, default not matched lcall clear_lcd mov dptr,#0610h ;message "Time:01:00:00PM" displayed on LCD lcall display_text lcall display_time lcall cursoroff lcall load_timer ;routine to initialize T1 timer mov IE,#10001000b ;Initialize T1 interrupt for timer overflow here: sjmp here ;******************************************************************************************** welcome_msg: ;routine display welcome message on LCD nop flash1: mov dptr,#0600h ;message "Digital Clock" displayed on LCD lcall display_text lcall delay14m mov lcdcom,#0c0h ;command to move cursor to next line on same LCD screen lcall command_LCD mov dptr,#0640h ; message "With alarm" displayed on LCD lcall display_text lcall delay140m lcall delay140m lcall delay140m lcall clear_lcd lcall cursoroff lcall delay140m lcall delay140m lcall delay140m lcall delay140m inc counter1 mov a,counter1 cjne a,#03h,flash1 ret ;********************************************************************************************* load_timer: ;routine to initialize T1 timer to generate 10msec delay clr tr1 clr tf1 mov tmod,#10h ;setting T1 as 16-bit timer next_pulse: mov th1,#0dch ;value to get 10msec delay in T1 timer mov tl1,#00h clr tf1 setb tr1 ;start T1 timer ret ;******************************************************************************************* intr_service: ;T1 Timer service routine clr tf1 clr tr1 ;stop T1 timer dec time1sec mov a, time1sec cjne a,#00h,not1sec mov time1sec,#64h ;RAM variable to track 1second, 64h(100d)*10msec=1sec lcall update_time ;routine update time lcall display_time ;routine display updated time on LCD lcall check_alarm ;routine check alarm not1sec: jb alarm_key,no_alarmkey lcall delay140m lcall delay140m mov a,alarm_status cjne a,#00h,alarm_on mov alarm_status,#01h ;Alarm flag ON indicating alarm activated lcall enter_alarm sjmp no_alarmkey alarm_on: mov alarm_status,#00h mov alarm_match,#00h no_alarmkey: mov th1,#0dch ;value to get 10msec delay mov tl1,#00h clr tf1 setb tr1 ;start T1 timer intr_over: reti ;return from service routine ;********************************************************************************************* enter_alarm: ;routine to enter ALARM time lcall cursoron mov lcdcom,#80h lcall command_LCD mov dptr,#0630h ;message "Enter alarm time" displayed on LCD lcall display_text lcall enter_time ;routine to enter TIME lcall copy_alarm ;copy entered time as ALARM time lcall clear_lcd mov dptr,#0610h ;message "Time12:00:00PM" displayed on LCD lcall display_text lcall display_time lcall cursoroff ret ;************************************************************************************************* check_alarm: ;routine ALARM function mov lcdcom,#0c0h lcall command_LCD mov a,alarm_status cjne a,#01h,no_alarm mov dptr,#0650h ;message "Alarm active" displayed on LCD lcall display_text mov a,alarm_match cjne a,#00h,buzzer_on mov a,hour cjne a,alarm_hour,notmatch mov a,mins cjne a,alarm_mins,notmatch mov a,secs cjne a,alarm_secs,notmatch mov a,ampm cjne a,alarm_ampm,notmatch mov alarm_match,#01h ;alram match with clock time notmatch: ret buzzer_on: setb buzzer ;alarm Buzzer on ret no_alarm: clr buzzer mov alarm_match,#00h ;no alram no match with clock time mov dptr,#0660h ;" " lcall display_text ret ;************************************************************************************************** copy_time: ;routine copy entered time to current time variables mov hour,temp_hour mov mins,temp_mins mov secs,temp_secs mov ampm,temp_ampm ret ;************************************************************************************************** copy_alarm: ;routine copy entered time to alarm time variables mov alarm_hour,temp_hour mov alarm_mins,temp_mins mov alarm_secs,temp_secs mov alarm_ampm,temp_ampm ret ;*************************************************************************************************** update_time: ;routine to update current time inc secs mov a,secs cjne a,#60d,secnotover mov secs,#00d inc mins mov a,mins cjne a,#60d,minsnotover mov mins,#00d inc hour mov a,hour cjne a,#12d,not12 mov a,ampm cjne a,#00h,its_pm2 mov a,#01h mov ampm,a sjmp update_over its_pm2: mov a,#00h mov ampm,a sjmp update_over not12: cjne a,#13d,hournotover mov hour,#01d secnotover: sjmp update_over minsnotover: sjmp update_over hournotover: sjmp update_over update_over: ret ;********************************************************************************************* enter_time: ;routine to enter TIME in 12 hour format mov lcdcom,#0c0h lcall command_LCD mov dptr,#0610h ;message "Time:01:00:00" AM displayed on LCD lcall display_text mov temp_hour,#01h mov lcdcom,#0c5h ;entring hour lcall command_LCD mov disp_var1,#30h mov disp_var0,#31h mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD inc_hour: mov lcdcom,#0c6h lcall command_LCD lcall chk_keys cjne a,#01h,dec_hour inc temp_hour mov a,temp_hour cjne a,#13d,x111h ;limit to 12 hour mov temp_hour,#01h x111h: mov a,temp_hour lcall chk_timedisp mov lcdcom,#0c5h lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD sjmp inc_hour dec_hour: cjne a,#02h,end_hour dec temp_hour mov a,temp_hour cjne a,#00h,x121h mov temp_hour,#12d x121h: mov a,temp_hour lcall chk_timedisp mov lcdcom,#0c5h lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD sjmp inc_hour end_hour: cjne a,#03h,inc_hour ;*********************************************************end of hour entry***************************** mov temp_mins,#00h mov lcdcom,#0c8h ;entring mins lcall command_LCD mov disp_var1,#30h mov disp_var0,#30h mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD inc_mins: mov lcdcom,#0c9h lcall command_LCD lcall chk_keys cjne a,#01h,dec_mins inc temp_mins mov a,temp_mins cjne a,#60d,x111m ;limit of 60 mins mov temp_mins,#00h x111m: mov a,temp_mins lcall chk_timedisp mov lcdcom,#0c8h lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD sjmp inc_mins dec_mins: cjne a,#02h,end_mins dec temp_mins mov a,temp_mins cjne a,#0ffh,x121m mov temp_mins,#59d x121m: mov a,temp_mins lcall chk_timedisp mov lcdcom,#0c8h lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD sjmp inc_mins end_mins: cjne a,#03h,inc_mins ;******************end of minutes entry****************************************************** mov temp_secs,#00h mov lcdcom,#0cbh ;entring secs lcall command_LCD mov disp_var1,#30h mov disp_var0,#30h mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD inc_secs: mov lcdcom,#0cch lcall command_LCD lcall chk_keys cjne a,#01h,dec_secs inc temp_secs mov a,temp_secs cjne a,#60d,x111s ;limit of 60 secs mov temp_secs,#00h x111s: mov a,temp_secs lcall chk_timedisp mov lcdcom,#0cbh lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD sjmp inc_secs dec_secs: cjne a,#02h,end_secs dec temp_secs mov a,temp_secs cjne a,#0ffh,x121s mov temp_secs,#59d x121s: mov a,temp_secs lcall chk_timedisp mov lcdcom,#0cbh lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD sjmp inc_secs end_secs: cjne a,#03h,inc_secs ;*****************************end of seconds entry********************************************************* mov temp_ampm,#00h inc_am_pm: mov lcdcom,#0ceh ;entrying am_pm lcall command_LCD mov a,temp_ampm its_am: cjne a,#00h,its_pm mov disp_data,#'A' lcall data_LCD sjmp x131 its_pm: mov disp_data,#'P' lcall data_LCD x131: lcall chk_keys cjne a,#01h,dec_am_pm inc temp_ampm mov a,temp_ampm cjne a,#02h,x111am mov temp_ampm,#00h x111am: sjmp inc_am_pm dec_am_pm: cjne a,#02h,end_am_pm dec temp_ampm mov a,temp_ampm cjne a,#0ffh,x121am mov temp_ampm,#01h x121am: sjmp inc_am_pm end_am_pm: cjne a,#03h,inc_am_pm ret ;******************************************************************************************************** display_time: ;routine to display updated time on the LCD mov a,hour lcall chk_timedisp mov lcdcom,#85h lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD mov a,mins lcall chk_timedisp mov lcdcom,#88h lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD mov a,secs lcall chk_timedisp mov lcdcom,#8bh lcall command_LCD mov disp_data,disp_var1 lcall data_LCD mov disp_data,disp_var0 lcall data_LCD mov lcdcom,#8eh lcall command_LCD mov a,ampm cjne a,#00h,its_pm1 mov disp_data,#'A' lcall data_LCD sjmp xc112 its_pm1: mov disp_data,#'P' lcall data_LCD xc112: mov disp_data,#'M' lcall data_LCD ret ;********************************************************************************************** chk_timedisp: mov b,#0ah div ab orl a,#30h orl b,#30h mov disp_var1,a mov disp_var0,b ret ;********************************************************************************************* chk_keys: ;rountine to find which button is pressed mov p2,#0ffh nop mov a,#00h key_again: jb up,xdown mov a,#01h ;if UP pressed Acc=01h sjmp key_over xdown: jb down,xenter mov a,#02h ;if DOWN pressed Acc=02h sjmp key_over xenter: jb enter,key_again mov a,#03h ;if ENTER pressed Acc=03h key_over: lcall delay140m ;debounce delay lcall delay140m ret ;************************************************************************************************** ;************************************************************************************************** ;************************MATH ROUTINES********************************************************* ;*************************************************************************************************** hex_to_dec: ;routine to convert 32 bit hex number to 8 digit ASCII decimal number mov out7,#00h mov out6,#00h mov out5,#00h mov out4,#00h mov out3,#00h mov out2,#00h mov out1,#00h mov out0,#00h mov hex1,#00h mov hex0,#0ah mov a,tt2 cjne a,#00h,xbn56 mov a,tt1 cjne a,#00h,xbn57 lcall division_16 mov out0,r6 lcall division_16 mov out1,r6 mov out2,tt0 sjmp over56 xbn57: lcall division_16 mov out0,r6 lcall division_16 mov out1,r6 lcall division_16 mov out2,r6 lcall division_16 mov out3,r6 mov out4,tt0 sjmp over56 xbn56: lcall division_16 mov out0,r6 lcall division_16 mov out1,r6 lcall division_16 mov out2,r6 lcall division_16 mov out3,r6 lcall division_16 mov out4,r6 lcall division_16 mov out5,r6 lcall division_16 mov out6,r6 mov out7,tt0 over56: orl out7,#30h orl out6,#30h orl out5,#30h orl out4,#30h orl out3,#30h orl out2,#30h orl out1,#30h orl out0,#30h ret ;********************************************************************************************************** division_16: ;routine to divide 3 bit divided by 16 bit divisor to provide 16 bit Quotent and reminder MOV R7,#0 ;msb rem MOV R6,#0 ;lsb rem ;zero out partial remainder MOV TMP_0,#0 MOV TMP_1,#0 MOV TMP_2,#0 MOV TMP_3,#0 MOV R1,hex1 ;load divisor MOV R0,hex0 MOV R5,#32 ;loop count Div_loop: LCALL Shift_D ;shift the dividend and return MSB in C MOV A,R6 ;shift carry into LSB of partial remainder RLC A MOV R6,A MOV A,R7 RLC A MOV R7,A CLR C MOV A,R7 ;subtract R1 from R7 to see if R1 < R7 SUBB A,R1 ; A = R7 - R1, carry set if R7 < R1 JC Cant_sub JNZ Can_sub ;jump if R7>R1 CLR C MOV A,R6 SUBB A,R0 ; A = R6 - R0, carry set if R6 < R0 JC Cant_sub Can_sub: CLR C MOV A,R6 SUBB A,R0 ; A = R6 - R0 MOV R6,A MOV A,R7 SUBB A,R1 ; A = R7 - R1 - Borrow MOV R7,A SETB C ; shift a 1 into the quotient ljmp Quot Cant_sub: CLR C Quot: LCALL Shift_Q ; Test for competion DJNZ R5,Div_loop ; Now we are all done, move the TMP values back into OP MOV tt0,TMP_0 MOV tt1,TMP_1 MOV tt2,TMP_2 MOV tt3,TMP_3 RET Shift_D: CLR C MOV A,tt0 RLC A MOV tt0,A MOV A,tt1 RLC A MOV tt1,A MOV A,tt2 RLC A MOV tt2,A MOV A,tt3 RLC A MOV tt3,A RET Shift_Q: MOV A,TMP_0 RLC A MOV TMP_0,A MOV A,TMP_1 RLC A MOV TMP_1,A MOV A,TMP_2 RLC A MOV TMP_2,A MOV A,TMP_3 RLC A MOV TMP_3,A RET ;************************************************************************************************** ;************************************************************************************************** ;************************LCD ROUTINES*********************************************************** ;*************************************************************************************************** display_text: ;routine to display 16 characters stored in ROM on LCD mov count,#0fh nextchar: mov a,#00h movc a,@a+dptr mov disp_data,a lcall data_LCD inc dptr mov a,count cjne a,#00h,next1 ljmp here11 next1: dec count ljmp nextchar here11: ret ;*********************Initialize LCD****************************************************************** lcd_initialize: ;routine to initialize LCD mov lcdcom,#38h lcall command_LCD lcall delay40u mov lcdcom,#01h lcall command_LCD lcall delay14m mov lcdcom,#0Eh lcall command_LCD lcall delay40u mov lcdcom,#06h lcall command_LCD lcall delay40u ret ;**************************************************************************************************** cursoroff: ;routine to switch cursor of LCD off mov lcdcom,#0ch lcall command_LCD ret ;***************************************************************************************************** cursoron: ;routine to switch cursor of LCD ON mov lcdcom,#0Eh lcall command_LCD ret ;****************************************************************************************************** clear_lcd: ;routine to clear LCD mov lcdcom,#01h lcall command_LCD lcall delay14m mov lcdcom,#80h lcall command_LCD ret ;***************************************************************************************************** command_LCD: ;routine to send command to LCD clr RS clr RW lcall delay10u setb EN lcall delay10u mov p1,lcdcom lcall delay10u clr EN lcall delay10u setb RW lcall delay40u ret ;****************************************************************************************************** data_LCD: ;routine to ASCII data to LCD display setb RS clr RW lcall delay10u setb EN lcall delay10u mov p1,disp_data clr EN lcall delay40u nop ret ;******************************************************************************************************** ;***********************sofware delays generated by nested loops*********************************************** ;******************************************************************************************************** delay1sec: ;Delay of 1second mov r3,#07h here1_1s: mov r4,#0ffh here2_1s: mov r5,#0ffh here3_1s: djnz r5,here3_1s djnz r4,here2_1s djnz r3,here1_1s ret ;******************************************************************************************************* delay140m: ;Delay of 140msec mov r3,#01h here1_140m: mov r4,#0ffh here2_140m: mov r5,#0ffh here3_140m: djnz r5,here3_140m djnz r4,here2_140m djnz r3,here1_140m ret ;******************************************************************************************************* delay14m: ;Delay of 14msec mov r3,#1ch here1_14m: mov r4,#0e6h here2_14m: djnz r4,here2_14m djnz r3,here1_14m ret ;****************************************************************************************************** delay40u: ;Delay of 40usec mov r4,#11h here40u: djnz r4,here40u ret ;****************************************************************************************************** delay10u: ;Delay of 10usec mov r4,#03h here10u: djnz r4,here10u ret ;****************************************************************************************************** org 0600h db ' Digital Clock ' org 0610h db 'Time:01:00:00 AM' org 0620h db 'Enter Clock Time' org 0630h db 'Enter Alarm Time' org 0640h db ' With Alarm ' org 0650h db 'Alarm active ' org 0660h db ' ' end ;END of program