Prepaid Energy Meter (AT89S52) : How To Program A New Card
Prepaid Energy Meter (AT89S52) : How To Program A New Card
A scheme of Electricity billing system called "PREPAID ENERGY METER WITH TARIFF INDICATOR" can facilitate in improved cash flow management in energy utilities and can reduces problem associated with billing consumer living in isolated area and reduces deployment of manpower for taking meter readings. Every consumer can buy a memory card (is nothing but an EEPROM IC) with a password stored inside it using a MC program. The memory card is available at various ranges (ie. Rs 50, Rs 100, Rs 200 etc).In our project we have given the name for memory card as smart card. When the consumer insert a smart card into the card reader which is connected kit.Then the card reader will read the stored information and delete the information from the EEPROM IC(smart card) using the MC program. So that the smart card cannot be reused by others. Suppose if a consumer buy a card for Rs.50/- he / she can insert this amount through the card reader so that prepaid energy meter with tariff indicator kit will be activated. According to the power consumption the amount will be reduced. When the amount is over, the relay will automatically shutdown the whole system. In our project we also have a provision to give an alarm sound to consumer before the whole amount is reduced. You can also find the Card programmer circuit and program from the download. So that you can easily create your own cards. Here's the procedure to create the cards. How to program a new card. For making a unit price card for Rs 2.50 1. Insert the card into the Programmer 2. Dial 1*0250# The format is 1 for unit price * for start process - Higher digit of the unit price
- lower digot of the unit price - Higher digit of the unit paise - lower digot of the unit paise 3. The red led will blink for every key press 4. If the programming done sucessfully then the Green led will long Blink finally. 5. If it fails then the RED led will give a long blink For making a Recharge card for Rs 400 1. Insert the card into the Programmer 2. Dial 2*0400# 3. The red led will blink for every key press 4. If the programming done sucessfully then the Green led will long Blink finally. 5. If it fails then the RED led will give a long blink
Card Diagram..
Programming Command:
INCLUDE REG_51.PDF RB0 RB1 EQU EQU 000H ; Select Register Bank 0 008H ; Select Register Bank 1 ...poke to PSW to use
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%% SDA1 EQU SCL1 EQU P2.1 P2.0 ;SDA=PIN5 ;SCL=PIN6
WTCMD EQU 10100110B ;WRITE DATA COMMAND Note 3RDCMD EQU 10100111B ;READ DATA COMMAND Note 3 WTCMD1 EQU 10100000B ;WRITE DATA COMMAND Note 3RDCMD1 EQU 10100001B ;READ DATA COMMAND Note 3 RELAY BUZZER EQU EQU P2.7 P2.4
; ***LCD CONTROL*** LCD_RS EQU P0.0 LCD_E ;LCD REGISTER SELECT LINE
EQU P0.1 ;LCD ENABLE LINE ;PORT 1 IS USED FOR DATA ;USED FOR DATA
LCD_DB6 EQU P0.4 ;FOR DATA LCD_DB7 EQU P0.5 ;FOR DATA
; ***SYSTEM INSTRUCTIONS***
; 4-BIT DATA,2 LINES,5X7 MATRIX LCD ; INCREMENT CURSOR DON'T SHIFT DISPLAY
; This is internal data memory ; Bit adressable memory DS BIT BIT BIT 1 FLAGS1.0 FLAGS1.1 FLAGS1.2
FLAGS1:
BCDCARRY CARRY TBIT TBIT1 READING: AMOUNT: COUNTER: TEMP: PRICE: DS BALANCE: DS DS DS DS
BIT FLAGS1.3 DS 3 2 1 2 1 1 3 1 1 2
DS 1
; ---------==========----------==========---------=========--------; Main routine. Program execution starts here. ; ---------==========----------==========---------=========--------ORG 00H ; Reset
AJMP MAIN
ORG 0003H PUSH PSW PUSH ACC MOV PSW,#RB1 CALL INC_COUNTER POP ACC POP PSW RETI ; ---------==========----------==========---------=========--------MAIN: MOV SP,#50H MOV PSW,#RB0 MOV IE,#10000001B CALL RESETLCD4 ; Select register bank 0 ; Select register bank 0
CALL TITLE1 CLR BUZZER SETB RELAY CLR TBIT1 MOV BUZZ_COUNT,#00H
CALL READ_COUNTER MOV A,COUNTER CJNE A,#0FFH,BYPASS CALL RESET_READING CALL RESET_AMT CALL RESET_COUNTER CALL RESET_PRICE CALL RESET_BALANCE ;RELAY ON/OFF BYTE CALL SYSTEM_RESET CALL DELAYYS BYPASS:
MAINS:
MOV A,BALANCE CJNE A,#00H,FG1 CLR RELAY CALL RECHAGRE CALL DELAYY SETB BUZZER AJMP MAINS
FG1:
SETB RELAY MOV A,BUZZ_COUNT CJNE A,#00H,AZX1 CLR BUZZER AJMP AZX2 ;CHK TO SWITCH OFF THE BUZZER
AZX1: AZX2:
DEC BUZZ_COUNT
MOV R1,#READING BYTES(RAM) MOV R4,#05H EEPROM MOV R6,#2 CALL READ_EEPROM CALL DISP_READING MOV TEMP,READING CALL SEP_DISP
;GET DATA IN
;DATA ADDRESS IN
;NUMBER OF BYTES
CALL DELAYY
MOV R1,#AMOUNT BYTES(RAM) MOV R4,#0AH EEPROM MOV R6,#3 CALL READ_EEPROM CALL AMT_READING MOV TEMP,AMOUNT CALL SEP_DISP MOV TEMP,AMOUNT+1 CALL SEP_DISP MOV R4,#'.' CALL WRLCDDATA CALL MDELAY MOV TEMP,AMOUNT+2 CALL SEP_DISP
;GET DATA IN
;DATA ADDRESS IN
;NUMBER OF BYTES
CALL DELAYY
MOV R1,#COUNTER BYTES(RAM) MOV R4,#0EH EEPROM MOV R6,#2 CALL READ_EEPROM CALL COUNT_READING ; ; MOV TEMP,COUNTER CALL SEP_DISP MOV TEMP,COUNTER+1 CALL SEP_DISP
;GET DATA IN
;DATA ADDRESS IN
;NUMBER OF BYTES
CALL DELAYY MOV R1,#PRICE BYTES(RAM) MOV R4,#10H EEPROM MOV R6,#2 CALL READ_EEPROM ;NUMBER OF BYTES ;DATA ADDRESS IN ;GET DATA IN
CALL READ_PRICE CALL UNIT_PRICE MOV A,PRICE ADD A,#30h MOV R4,A
CALL WRLCDDATA CALL MDELAY MOV R4,#'.' CALL WRLCDDATA CALL MDELAY MOV TEMP,PRICE+1 CALL SEP_DISP
CALL DELAYY AJMP MAINS ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 ; ; INCREMENT COUNTER BY 1 IF COUNT=3200 THEN INCREMENT READING
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 INC_COUNTER: MOV A,COUNTER+1 ADD A,#01 DA A MOV COUNTER+1,A CJNE A,#01H,REPPA1 AJMP DCV2
REPPA1:
REPPA2:
REPPA3:
REPPA4:
REPPA: MOV COUNTER,#00H MOV COUNTER+1,#01H MOV R1,#COUNTER MOV R4,#0EH MOV R6,#2 CALL STORE_EEPROM CALL DELAY AJMP DVB1 ;store COUNT ;Starting Address IN EEPROM ;STORE 2 BYTES
DCV2:
MOV R1,#COUNTER MOV R4,#0EH MOV R6,#2 CALL STORE_EEPROM CALL DELAY RET
DVB1: MOV A,READING+1 ADD A,#01 DA A MOV READING+1,A JNC DCS1 MOV A,READING ADD A,#01 DA A MOV READING,A DCS1: MOV R1,#READING MOV R4,#05H MOV R6,#2 CALL STORE_EEPROM CALL DELAY
;INCREMENT READING BY 1
MOV A,AMOUNT+2 FROM TOTAL0 CLR C SUBB A,PRICE+1 CALL BCD_CONV MOV AMOUNT+2,A MOV A,AMOUNT+1 FROM TOTAL1 SUBB A,PRICE CALL BCD_CONV
;SUBTRACT AMT0
;SUBTRACT AMT1
MOV AMOUNT+1,A MOV A,AMOUNT FROM TOTAL2 SUBB A,#00h CALL BCD_CONV MOV AMOUNT,A ;SUBTRACT AMT2
MOV R1,#AMOUNT MOV R4,#0AH MOV R6,#3 CALL STORE_EEPROM CALL DELAY
MOV A,AMOUNT+1 CJNE A,#40H,FCX1 MOV BUZZ_COUNT,#02H SETB BUZZER FCX1: CJNE A,#38H,FAX1 MOV BUZZ_COUNT,#02H SETB BUZZER FAX1: CJNE A,#41H,FAAX1 MOV BUZZ_COUNT,#02H SETB BUZZER FAAX1: CJNE A,#20H,FCX2
MOV BUZZ_COUNT,#03H SETB BUZZER FCX2: CJNE A,#19H,FAX2 MOV BUZZ_COUNT,#03H SETB BUZZER FAX2: CJNE A,#21H,FAAX2 MOV BUZZ_COUNT,#03H SETB BUZZER FAAX2: CJNE A,#10H,FCX3 MOV BUZZ_COUNT,#04H SETB BUZZER FCX3: CJNE A,#11H,FCX4 MOV BUZZ_COUNT,#04H SETB BUZZER FCX4: CJNE A,#09H,FAX4 MOV BUZZ_COUNT,#04H SETB BUZZER FAX4:
;SUBTRACT AMT0
MOV A,AMOUNT+1 FROM TOTAL1 SUBB A,PRICE MOV A,AMOUNT CLR TBIT JNC POP1
;SUBTRACT AMT1
SETB TBIT POP1: CJNE A,#00H,BACK JNB TBIT, BACK MOV BALANCE,#00H MOV R1,#BALANCE MOV R4,#15H MOV R6,#1 CALL STORE_EEPROM CALL DELAY CLR RELAY SETB BUZZER BACK: RET ;store COUNT ;Starting Address IN EEPROM ;STORE 2 BYTES
SETB CARRY LOP2: JNB AC,LOP1 SETB BCDCARRY CLR C SUBB A,#06H LOP1: JNB CARRY,LOP3 CLR C SUBB A,#60H LOP3: CLR C JNB CARRY,LOP4 SETB C LOP4: RET
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
READ_BALANCE: MOV R1,#BALANCE BYTES(RAM) MOV R4,#15H EEPROM MOV R6,#1 CALL READ_EEPROM RET ;NUMBER OF BYTES ;DATA ADDRESS IN ;GET DATA IN
READ_COUNTER: MOV R1,#COUNTER BYTES(RAM) MOV R4,#0EH EEPROM MOV R6,#2 CALL READ_EEPROM RET READ_PRICE: MOV R1,#PRICE BYTES(RAM) MOV R4,#10H EEPROM MOV R6,#2 CALL READ_EEPROM RET ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 SEP_DISP1: MOV A,AMOUNT ANL A,#0F0H SWAP A CJNE A,#00H,DAP1 MOV A,AMOUNT ANL A,#0FH AJMP DAP3 ;NUMBER OF BYTES ;DATA ADDRESS IN ;GET DATA IN ;NUMBER OF BYTES ;DATA ADDRESS IN ;GET DATA IN
DAP1:
CALL WRLCDDATA CALL MDELAY DAP2: MOV A,AMOUNT ANL A,#0FH ADD A,#30H MOV R4,A CALL WRLCDDATA CALL MDELAY DAP4: MOV A,AMOUNT+1 ANL A,#0F0H SWAP A ADD A,#30H MOV R4,A CALL WRLCDDATA CALL MDELAY DAP5: MOV A,AMOUNT+1 ANL A,#0FH ADD A,#30H MOV R4,A CALL WRLCDDATA CALL MDELAY MOV R4,#'.'
CALL WRLCDDATA CALL MDELAY MOV A,AMOUNT+2 ANL A,#0F0H SWAP A ADD A,#30H MOV R4,A CALL WRLCDDATA CALL MDELAY MOV A,AMOUNT+2 ANL A,#0FH ADD A,#30H MOV R4,A CALL WRLCDDATA CALL MDELAY RET
DAP3:
CJNE A,#00H,DAP2 MOV A,AMOUNT+1 ANL A,#0F0H SWAP A CJNE A,#00H,DAP4 AJMP DAP5
;CHK 2 DIGIT
;CHK 3 DIGIT
SEP_DISP: MOV A,TEMP ANL A,#0F0H SWAP A ADD A,#30H MOV R4,A CALL WRLCDDATA CALL MDELAY MOV A,TEMP ANL A,#0FH ADD A,#30H MOV R4,A CALL WRLCDDATA CALL MDELAY RET ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 AMT_RECHARGE: MOV READ_BYTE,#01H MOV READ_BYTE+1,#00H MOV READ_BYTE+2,#10H MOV R1,#READ_BYTE MOV R6,#3 MOV A,#WTCMD1 ;store COUNT ;STORE 2 BYTES ;LOAD WRITE COMMAND
CALL OUTS MOV A,#20H CALL OUT BXLP: MOV A,@R1 CALL OUT INC R1 DJNZ R6,BXLP CALL STOP CALL DELAY RET STORE_UNIT_PRICE: MOV READ_BYTE,#00H MOV READ_BYTE+1,#01H MOV READ_BYTE+2,#00H MOV R1,#READ_BYTE MOV R6,#3 MOV A,#WTCMD1 CALL OUTS MOV A,#20H CALL OUT BALP: MOV A,@R1 CALL OUT INC R1 DJNZ R6,BALP ;GET DATA ;GET DATA
;SEND IT ;INCREMENT DATA POINTER ;LOOP TILL DONE ;SEND STOP CONDITION
;store COUNT ;STORE 2 BYTES ;LOAD WRITE COMMAND ;SEND IT ;GET LOW BYTE ADDRESS ;SEND IT
RESET_BALANCE: MOV BALANCE,#0FFH MOV R1,#BALANCE MOV R4,#15H MOV R6,#1 CALL STORE_EEPROM CALL DELAY RET RESET_PRICE: MOV PRICE,#01H MOV PRICE+1,#80H MOV R1,#PRICE MOV R4,#10H MOV R6,#2 CALL STORE_EEPROM CALL DELAY RET ;store COUNT ;Starting Address IN EEPROM ;STORE 2 BYTES ;store COUNT ;Starting Address IN EEPROM ;STORE 2 BYTES
MOV COUNTER+1,#03H MOV R1,#COUNTER MOV R4,#0EH MOV R6,#2 CALL STORE_EEPROM CALL DELAY RET ;store COUNT ;Starting Address IN EEPROM ;STORE 2 BYTES
RESET_AMT: MOV AMOUNT,#00H ; MOV AMOUNT+1,#05H MOV AMOUNT+2,#00H MOV R1,#AMOUNT MOV R4,#0AH MOV R6,#3 CALL STORE_EEPROM CALL DELAY RET RESET_READING: MOV READING,#00H MOV READING+1,#13H MOV R1,#READING MOV R4,#05H MOV R6,#2 ;store READING ;Starting Address IN EEPROM ;STORE 2 BYTES ;store READING ;Starting Address IN EEPROM ;STORE 2 BYTES
CALL STORE_EEPROM CALL DELAY RET ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DELAYY: MOV F1,#0FH SEP3: MOV F2,#0fFH SEP2: MOV F3,#0FFH SEP1: DJNZ F3,SEP1 DJNZ F2,SEP2 CALL CARD_READ MOV A,READ_BYTE CJNE A,#0FFH,DSP1 CLR TBIT1 DSP3A:DJNZ F1,SEP3 RET
DSP1: JB TBIT1,DSP3A CALL TITLE3 CALL DELAYS CALL DELAYS CALL CARD_READ MOV A,READ_BYTE CJNE A,#00H,DSP2
CALL TITLE4
MOV PRICE,READ_BYTE+1 MOV PRICE+1,READ_BYTE+2 MOV R1,#PRICE MOV R4,#10H MOV R6,#2 CALL STORE_EEPROM CALL DELAYS SETB TBIT1 AJMP RESETX_CHIP ;store COUNT ;Starting Address IN EEPROM ;STORE 2 BYTES
DSP2: CJNE A,#01H,DSP3 CALL TITLE5 ; ; ; ; MOV R1,#AMOUNT MOV R4,#0AH MOV R6,#03h CALL READ_EEPROM ; NEW RECHARGE ;GET DATA IN BYTES(RAM) ;DATA ADDRESS IN EEPROM ;NUMBER OF BYTES
MOV A,AMOUNT ADD A,READ_BYTE+1 DA A MOV AMOUNT,A MOV A,AMOUNT+1 ADDC A,READ_BYTE+2
DA A MOV AMOUNT+1,A MOV R1,#AMOUNT MOV R4,#0AH MOV R6,#03h CALL STORE_EEPROM CALL DELAYS SETB TBIT1 CALL RESET_BALANCE RESETX_CHIP: ;store READING ;Starting Address IN EEPROM ;STORE 2 BYTES
MOV READ_BYTE,#0AAH MOV READ_BYTE+1,#0FFH MOV READ_BYTE+2,#0FFH MOV R1,#READ_BYTE MOV R6,#3 MOV A,#WTCMD1 CALL OUTS MOV A,#20H CALL OUT BBLP: MOV A,@R1 CALL OUT INC R1 DJNZ R6,BBLP ;GET DATA ;SEND IT
;ERASE AMOUNT
;store COUNT ;STORE 2 BYTES ;LOAD WRITE COMMAND ;SEND IT ;GET LOW BYTE ADDRESS ;SEND IT
DSP3: CJNE A,#0AAH,DSP4 CALL TITLE6 CALL DELAYS SETB TBIT1 DSP4: RET ; NEW RECHARGE
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DELAY: MOV R6,#0FFH RE1: RE: MOV R7,#0FFH NOP DJNZ R7,RE DJNZ R6,RE1 RET ;********************************************************** CARD_READ: MOV R1,#READ_BYTE BYTES(RAM) MOV R6,#3 MOV A,#WTCMD1 ADDRESS CALL OUTS ;SEND IT ;NUMBER OF BYTES ;LOAD WRITE COMMAND TO SEND ;GET DATA IN
MOV A,#20H CALL OUT MOV A,#RDCMD1 CALL OUTS BXDLP: CALL IN MOV @R1,a INC R1 DJNZ R6,AXLP CALL STOP RET AXLP: CLR SDA1 ;NOT DONE, ISSUE ACK SETB SCL1 NOP ;NOTE 1 NOP NOP NOP ;NOTE 2 NOP CLR SCL1
;GET LOW BYTE ADDRESS ;SEND IT ;LOAD READ COMMAND ;SEND IT ;READ DATA ;STORE DATA ;INCREMENT DATA POINTER ;DECREMENT LOOP COUNTER ;IF DONE, ISSUE STOP CONDITION ;DONE, EXIT ROUTINE
JMP BXDLP ;CONTINUE WITH READS ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%% ; READ DATA FROM EEPROM
MOV A,#WTCMD ADDRESS CALL OUTS MOV A,R4 CALL OUT MOV A,#RDCMD CALL OUTS BRDLP: CALL IN MOV @R1,a INC R1 DJNZ R6,AKLP CALL STOP RET AKLP: CLR SDA1 ;NOT DONE, ISSUE ACK SETB SCL1 NOP ;NOTE 1 NOP NOP NOP ;NOTE 2 NOP CLR SCL1
;SEND IT ;GET LOW BYTE ADDRESS ;SEND IT ;LOAD READ COMMAND ;SEND IT ;READ DATA ;STORE DATA ;INCREMENT DATA POINTER ;DECREMENT LOOP COUNTER ;IF DONE, ISSUE STOP CONDITION ;DONE, EXIT ROUTINE
JMP BRDLP ;CONTINUE WITH READS ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%% ; STORE DATA IN EEPROM
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%% STORE_EEPROM: MOV A,#WTCMD CALL OUTS MOV A,R4 CALL OUT BTLP: MOV A,@R1 CALL OUT INC R1 DJNZ R6,BTLP CALL STOP RET ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%% ;GET DATA ;SEND IT ;INCREMENT DATA POINTER ;LOOP TILL DONE ;SEND STOP CONDITION ;LOAD WRITE COMMAND ;SEND IT ;GET LOW BYTE ADDRESS ;SEND IT
DB 1H,84H,'PREPAID',0C2H,'ENERGY METER',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DISP_READING: MOV DPTR,#MSAG2 CALL LCD_MSG RET MSAG2: DB 1H,82H,'METER READING',0C6H,00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AMT_READING: MOV DPTR,#MSAG3 CALL LCD_MSG RET MSAG3: DB 1H,81H,'BALANCE AMOUNT',0C3H,'Rs.',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ COUNT_READING: MOV DPTR,#MSAG4 CALL LCD_MSG RET MSAG4: DB 1H,82H,'PULSE COUNT',0C6H,00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UNIT_PRICE:
MOV DPTR,#MSAG14 CALL LCD_MSG RET MSAG14: DB 1H,83H,'UNIT PRICE',0C4H,'Rs ',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RECHAGRE: MOV DPTR,#MSAG5 CALL LCD_MSG RET MSAG5: DB 1H,80H,'Please Recharge',0C2H,'your Account',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TITLE3: MOV DPTR,#MSAG6 CALL LCD_MSG RET MSAG6: DB 1H,84H,'New Card',0C1H,'** DETECTED **',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TITLE4: MOV DPTR,#MSAG7 CALL LCD_MSG RET
MSAG7: DB 1H,81H,'NEW UNIT PRICE',0C1H,'** STORED **',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TITLE5: MOV DPTR,#MSAG8 CALL LCD_MSG RET MSAG8: DB 1H,83H,'NEW AMOUNT',0C1H,'** RECHARGED **',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TITLE6: MOV DPTR,#MSAG9 CALL LCD_MSG RET MSAG9: DB 1H,82H,'INVALID CARD',0C0H,'****************',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SYSTEM_RESET: MOV DPTR,#MSAG91 CALL LCD_MSG RET MSAG91: DB 1H,80H,'System Restored',0C0H,'****************',00H ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;********************************************************** ; INITIALIZE THE LCD 4-BIT MODE ;********************************************************** INITLCD4: CLR CLR MOV LCD_RS LCD_E ; LCD REGISTER SELECT LINE ; ENABLE LINE
WRLCDCOM4 R4, #ONDSP ; DISPLAY ON WRLCDCOM4 R4, #ENTRYMODE ; SET ENTRY MODE WRLCDCOM4 ; INCREMENT CURSOR RIGHT, NO SHIFT R4, #CLRDSP; CLEAR DISPLAY, HOME CURSOR WRLCDCOM4
; ********************************************************** ; SOFTWARE VERSION OF THE POWER ON RESET ; ********************************************************** RESETLCD4: CLR CLR CLR CLR LCD_RS LCD_E ; LCD REGISTER SELECT LINE ; ENABLE LINE
SETB SETB SETB CLR MOV CALL SETB CLR MOV CALL SETB CLR MOV CALL CLR SETB CLR MOV CALL MOV CALL MOV CALL MOV
LCD_DB5 LCD_DB4 LCD_E LCD_E A, #4 MDELAY LCD_E LCD_E A, #1 MDELAY LCD_E LCD_E A, #1 MDELAY LCD_DB4 ; SPECIFY 4-BIT OPERATION LCD_E LCD_E A, #1 MDELAY R4, #CONFIG; FUNCTION SET WRLCDCOM4 R4, #08H ; DISPLAY OFF WRLCDCOM4 R4, #1 ; CLEAR DISPLAY, HOME CURSOR ; START ENABLE PULSE ; END ENABLE PULSE ; DELAY 1 MILLISECOND ; START ENABLE PULSE ; END ENABLE PULSE ; DELAY 1 MILLISECOND ; START ENABLE PULSE ; END ENABLE PULSE ; DELAY 1 MILLISECOND ; START ENABLE PULSE ; END ENABLE PULSE ; DELAY 4 MILLISECONDS
JMP INITLCD4
; ********************************************************** ; SUB RECEIVES A COMMAND WORD TO THE LCD ; COMMAND MUST BE PLACED IN R4 BY CALLING PROGRAM ; ********************************************************** WRLCDCOM4: CLR CLR PUSH MOV MOV MOV MOV MOV MOV MOV MOV MOV SETB CLR LCD_E LCD_RS ACC A, R4 ; SELECT READ COMMAND ; SAVE ACCUMULATOR ; PUT DATA BYTE IN ACC
C, ACC.4 ; LOAD HIGH NIBBLE ON DATA BUS LCD_DB4, C ; ONE BIT AT A TIME USING... C, ACC.5 ; BIT MOVE OPERATOINS LCD_DB5, C C, ACC.6 LCD_DB6, C C, ACC.7 LCD_DB7, C LCD_E LCD_E ; PULSE THE ENABLE LINE
MOV MOV MOV MOV MOV MOV MOV MOV CLR SETB CLR
C, ACC.0 ; SIMILARLY, LOAD LOW NIBBLE LCD_DB4, C C, ACC.1 LCD_DB5, C C, ACC.2 LCD_DB6, C C, ACC.3 LCD_DB7, C LCD_E LCD_E LCD_E ; PULSE THE ENABLE LINE
CALL MADELAY POP RET ; ********************************************************** ; SUB TO RECEIVE A DATA WORD TO THE LCD ; DATA MUST BE PLACED IN R4 BY CALLING PROGRAM ; ********************************************************** WRLCDDATA: CLR SETB PUSH MOV MOV LCD_E LCD_RS ACC A, R4 ; SELECT READ DATA ; SAVE ACCUMULATOR ; PUT DATA BYTE IN ACC ACC
MOV MOV MOV MOV MOV MOV MOV SETB CLR MOV MOV MOV MOV MOV MOV MOV MOV CLR SETB CLR NOP NOP POP RET
LCD_DB4, C ; ONE BIT AT A TIME USING... C, ACC.5 ; BIT MOVE OPERATOINS LCD_DB5, C C, ACC.6 LCD_DB6, C C, ACC.7 LCD_DB7, C LCD_E LCD_E C, ACC.0 ; SIMILARLY, LOAD LOW NIBBLE LCD_DB4, C C, ACC.1 LCD_DB5, C C, ACC.2 LCD_DB6, C C, ACC.3 LCD_DB7, C LCD_E LCD_E LCD_E ; PULSE THE ENABLE LINE ; PULSE THE ENABLE LINE
ACC
; ********************************************************** ; SUB TAKES THE STRING IMMEDIATELY FOLLOWING THE CALL AND ; DISPLAYS ON THE LCD. STRING MUST BE TERMINATED WITH A ; NULL (0). ; ********************************************************** LCD_MSG: CLR A MOVC A,@A+DPTR INC DPTR JZ LCD_Msg9 ; Clear Index ; Get byte pointed by Dptr ; Point to the next byte ; Return if found the zero (end of stringz)
CJNE A,#01H,Lcd_Msg1 ; Check if is a Clear Command MOV R4,A CALL WRLCDCOM4 JMP LCD_MSG ;If yes, RECEIVE it as command to LCD ;Go get next byte from stringz
Lcd_Msg1: CJNE A,#0FFH,FLL ;Check for displaying full character MOV R4,A CALL WRLCDDATA JMP LCD_MSG FLL: CJNE A,#080h,$+3 JC Lcd_Msg_Data MOV R4,A CALL WRLCDCOM4 ; Carry not set if A=>80, it is address ; Data or Address? If => 80h then is address. ; Carry will be set if A < 80h (Data)
JMP Lcd_Msg
RET
; Return to Caller
MDELAY: PUSH MOV MD_OLP: INC NOP NOP NOP NOP NOP A ACC A,#0A6H
NOP NOP NOP JNZ NOP POP RET MADELAY: PUSH MOV MAD_OLP: INC NOP NOP NOP NOP NOP NOP NOP NOP JNZ NOP POP RET ACC MAD_OLP A ACC A,#036H ACC MD_OLP
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DELAYS: MOV R6, #00H MOV R5, #04H LOOPB: INC R6 ACALL DELAYMS MOV A, R6 JNZ LOOPB DEC R5 MOV A, R5 JNZ LOOPB RET ;************************************************************************** DELAYMS: ; MOV R7,#00H LOOPA: INC R7 MOV A,R7 ;increase R7 by one (R7 = R7 +1) ;move value in R7 to Accumlator (also known as A) ;compare A to FF hex (256). If not equal go to LOOPA ; ;put value of 0 in register R7 ;millisecond delay routine ;increase R6 by one (R6 = R6 +1) ;call the routine above. It will run and return to here. ;move value in R6 to A ;if A is not 0, go to LOOPB ;decrease R5 by one. (R5 = R5 -1) ;move value in R5 to A ;if A is not 0 then go to LOOPB. ;One second delay routine ;put 0 in register R6 (R6 = 0) ;put 5 in register R5 (R5 = 4)
;**************************************************************************
;*********************************************************************** ; THIS ROUTINE SENDS OUT CONTENTS OF THE ACCUMULATOR ; to the EEPROM and includes START condition. Refer to the data sheets ; for discussion of START and STOP conditions. ;***********************************************************************
OUTS: MOV
R2,#8
SETB SDA1 SETB SCL1 NOP NOP NOP CLR NOP NOP NOP CLR SCL1 A SDA1
;NOTE 1
NOP NOP
CLR
SCL1
CLR RET
SCL1
;********************************************************************** ; THIS ROUTINE SENDS OUT CONTENTS OF ACCUMLATOR TO EEPROM ; without sending a START condition. ;**********************************************************************
R2,#8 A
BITL
CLR
SCL1
CLR RET
SCL1
SDA1
NOP NOP
;******************************************************************* ; THIS ROUTINE READS A BYTE OF DATA FROM EEPROM ; From EEPROM current address pointer. ; Returns the data byte in R1 ;******************************************************************* CREAD: MOV A,#RDCMD ;LOAD READ COMMAND
IN:
MOV
R2,#8
;LOOP COUNT ;SET DATA BIT HIGH FOR INPUT ;CLOCK LOW ;NOTE 1
SDA1,INL1 C A
;SET CARRY IF DATA = 1 ;ROTATE DATA INTO ACCUMULATOR ;DECREMENT COUNTER ;CLOCK LOW
;********************************************************************* ; This routine test for WRITE DONE condition ; by testing for an ACK. ; This routine can be run as soon as a STOP condition
; has been generated after the last data byte has been sent ; to the EEPROM. The routine loops until an ACK is received from ; the EEPROM. No ACK will be received until the EEPROM is done with ; the write operation. ;********************************************************************* ACKTST: MOV MOV CLR NOP NOP NOP A,#WTCMD ;LOAD WRITE COMMAND TO SEND ADDRESS
R2,#8 SDA1
CLR
SCL1 A
AKTLS: CLR
CLR
SCL1
;CLOCK LOW
;NOTE 1
;EXIT IF ACK (WRITE DONE) ;START OVER ;CLOCK LOW ;DATA LOW
;NOTE 1
;CLOCK HIGH
;STOP CONDITION
;********************************************************************* END