;EXAM11
;DS1307
SDA BIT P1.0 ; SDA I2C Bus
SCL BIT P1.1 ; SCL I2C Bus
RTCID EQU 11010000B ; RTC Slave Address
FLAG EQU 02FH ; User FLAG
I2CACK BIT FLAG.0 ; Define I2C Acknowledge as bit
MAXBUFFER EQU 8
ORG 30H
SEC: DS 1 ;Seconds
MIN: DS 1 ;Minutes
HOUR: DS 1 ;Hours
DAY: DS 1 ;Day
DATE: DS 1 ;Date
MONTH: DS 1 ;Month
YEAR: DS 1 ;Year
CTRL: DS 1 ;Control Byte
I2CADR: DS 1 ;I2C Address
I2CDAT: DS 1 ;I2C Data
REGADR: DS 1
REGDAT: DS 1
StrBuff:DS 1 ;Restore char form RS232
buffer: DS MAXBUFFER ;Command Buffer
ORG 0000H ; Reset Vector
;*** Power up delay ***
;Wait for other Device
RES: MOV R2,#40H
RES1: MOV R3,#0
RES2: DJNZ R3,RES2
DJNZ R2,RES1
SETB SDA ; CLear I2C bus
SETB SCL
MAIN: LCALL InitUART ;Initial UART 9600,n,8,1 no parity
MOV DPTR,#Hello
LCALL SendSROM
ScanStr:
MOV R0,#buffer ;point to buffer
LCALL GetStr
MOV R0,#buffer ;load buffer Ptr
LCALL GetCmd ;found = 1...n
JZ ScanEx ; 0 = isn't Command
MOV StrBuff,A ;store result in StrBuff
;Check Command No.
;Check Command 1
XRL A,#01 ;?Compare A=1
JZ Cmd1 ;switch to x
;Check Command 2
MOV A,StrBuff ;Restore
XRL A,#02 ;?Compare A=2
JZ Cmd2
;Check Command 2
MOV A,StrBuff ;Restore
XRL A,#03 ;?Compare A=2
JZ Cmd3
JMP ScanStr
ScanEx: MOV DPTR,#ErrMsg1
LCALL SendSROM
LCALL LineFeed
JMP ScanStr
;Treat Command
Cmd1:
LCALL LineFeed
MOV R0,#buffer
LCALL Strlen
XRL A,#07h
JNZ Cmd1X
; Convert ASC to BCD
;Register Address
MOV A,buffer+2
CLR C
SUBB A,#30H
SWAP A
MOV REGADR,A
MOV A,buffer+3
CLR C
SUBB A,#30H
ORL A,REGADR
MOV REGADR,A
;LCALL SBYTEH
;Register Data
MOV A,buffer+5
CLR C
SUBB A,#30H
SWAP A
MOV REGDAT,A
MOV A,buffer+6
CLR C
SUBB A,#30H
ORL A,REGDAT
MOV REGDAT,A
;LCALL SBYTEH
LCALL RTCWB
LCALL LineFeed
MOV R0,#REGADR
LCALL DumpI
SJMP ScanStr
Cmd1X: MOV DPTR,#ErrMsg3
LCALL SendSROM
SJMP ScanStr
Cmd2:
LCALL LineFeed
LCALL RDRTC ;Read RTC
MOV R0,#SEC
LCALL DumpI
JMP ScanStr
Cmd3: MOV SEC,#80H
MOV MIN,#00H
MOV HOUR,#00
MOV DATE,#01
MOV MONTH,#01
MOV YEAR,#00
LCALL LineFeed
LCALL RTCWR ;Write RTC
LCALL RDRTC ;Read RTC
LCALL DISPLAY
;LCALL LineFeed
JMP ScanStr
;*** Get String ***
;IN R0 pointer to String Buffer
;R3 count n of Str
;
GetStr: MOV R3,#0
GetSnx: CLR A
LCALL RBYTE ;READ -> A
MOV StrBuff,A ;Restore char in StrBuff
;check end of str
XRL A,#0Dh ;Carriage Return
JZ ChkStr
MOV A,StrBuff ;Restore char in StrBuff
XRL A,#0Ah ;line feed LF
JZ ChkStr
MOV A,StrBuff ;Restore char in StrBuff
XRL A,#1Bh ;line feed LF
JZ GetESC
MOV A,StrBuff ;Restore char in StrBuff
LCALL SBYTE ;A -> Send ECho
MOV @R0,StrBuff ;store in buffer
INC R0 ;next point
INC R3 ;count str
;@Test buffer full
MOV A,R3
XRL A,#MAXBUFFER ;Compare with MAXBUFFER
JZ Sendfull ;>= MAXBUFFER
SJMP GetSnx
ChkStr: MOV A,R3
JZ GetDis
MOV @R0,#0 ;end of String
RET
;@
GetDis:
LCALL RDRTC ; Read RTC
LCALL DISPLAY
MOV R0,#buffer ;Point to buffer
SJMP GetStr
GetESC:
MOV DPTR,#Abortx
LCALL SendSROM
MOV R0,#buffer ;Point to buffer
SJMP GetStr
Sendfull:
MOV DPTR,#ErrMsg2
LCALL SendSROM
MOV R0,#buffer ;Point to buffer
SJMP GetStr
DISPLAY:
MOV A,DATE
LCALL SBYTEH
MOV A,#'/'
LCALL SBYTE
MOV A,MONTH
LCALL SBYTEH
MOV A,#'/'
LCALL SBYTE
MOV A,YEAR
LCALL SBYTEH
MOV A,#' '
LCALL SBYTE
MOV A,HOUR
LCALL SBYTEH
MOV A,#':'
LCALL SBYTE
MOV A,MIN
LCALL SBYTEH
MOV A,#':'
LCALL SBYTE
MOV A,SEC
LCALL SBYTEH
LCALL LineFeed
RET
;*** Get Command ***
;R0 point to Str buffer
;DPTR point to command
;R2 save
;R7 result
;return command in A
; found 1...n
; not found 0
;
;REG change = R0,R2,R7
;
GetCmd: MOV R7,#01 ;count
MOV A,R0 ;save R0->R2
MOV R2,A ;Restore Ptr
MOV DPTR,#Command1
LCALL StrCmp
JZ CmdEQU ;A=0 Equ
;If not Equ next Cmp
INC R7 ;inc result
MOV A,R2 ;get ptr
MOV R0,A ;Reload Ptr
MOV DPTR,#Command2
LCALL StrCmp
JZ CmdEQU
INC R7 ;inc result
MOV A,R2 ;get ptr
MOV R0,A ;Reload Ptr
MOV DPTR,#Command3
LCALL StrCmp
JZ CmdEQU
;not found
MOV R7,#0 ;result is NULL
CmdEQU: MOV A,R7 ;result in R7
RET
;StrCmp(@R0,DPTR);
;R0 point to Str buffer
;DPTR point to command
;reg change = R0,DPTR
;result in A 0 = Equ
; FFh = nEqu
StrCmp: CLR A
MOVC A,@A+dptr
JZ StrEq ;end of str
XRL A,@R0 ;Compare A=@R0 ?
JNZ StrNEq
INC R0 ;next char in buffer
INC dptr ;next command
JMP StrCmp
StrNEq: MOV A,#0FFh ;not equal
RET
StrEq: CLR A ;equal ret 0
RET
;*** I2C RTC Read***
RDRTC: MOV I2CADR,#RTCID ; Set RTC as I2C Write Slave
LCALL I2CSLAVE ; Connect Slave
MOV I2CDAT,#00H ;Set Slave Address 00H
LCALL I2CWrDat ;Write Data to Slave
MOV I2CADR,#RTCID+1 ;Set RTC as I2C Read Slave
LCALL I2CSLAVE ;Connect Slave
LCALL I2CRdDat ;Read Data from Slave
MOV SEC,I2CDAT ;Read Data to SEC
LCALL I2CAckBit ;Send Acknowledge
LCALL I2CRdDat ;Read Data from Slave
MOV MIN,I2CDAT ;Read Data to MIN
LCALL I2CAckBit ;Send Acknowledge
LCALL I2CRdDat ;Read Data from Slave
MOV HOUR,I2CDAT ;Read Data to HOUR
LCALL I2CAckBit ;Send Acknowledge
LCALL I2CRdDat ;Read Data from Slave
MOV DAY,I2CDAT ;Read Data to DAY
LCALL I2CAckBit ;Send Acknowledge
LCALL I2CRdDat ;Read Data from Slave
MOV DATE,I2CDAT ;Read Data to DATE
LCALL I2CAckBit ;Send Acknowledge
LCALL I2CRdDat ;Read Data from Slave
MOV MONTH,I2CDAT ;Read Data to MONTH
LCALL I2CAckBit ;Send Acknowledge
LCALL I2CRdDat ;Read Data from Slave
MOV YEAR,I2CDAT ;Read Data to YEAR
LCALL I2CAckBit ;Send Acknowledge
LCALL I2CRdDat ;Read Data from Slave
MOV CTRL,I2CDAT ;Read Data to CTRL
LCALL I2CNackBit ;Send Not Acknowledge
LCALL I2CSTOP ;Send Stop Condition
RET ;Return
;*** I2C RTC Write ***
RTCWR: MOV I2CADR,#RTCID ; Set RTC as I2C Write Slave
LCALL I2CSLAVE ; Connect Slave
MOV I2CDAT,#00H ; Set Slave Address 00H
LCALL I2CWrDat ; Write Data to Slave
MOV I2CDAT,SEC ; Write SEC to RTC
LCALL I2CWrDat
MOV I2CDAT,MIN ; Write MIN to RTC
LCALL I2CWrDat
MOV I2CDAT,HOUR ; Write HOUR to RTC
LCALL I2CWrDat;
MOV I2CDAT,DAY ; Write DAY to RTC
LCALL I2CWrDat;
MOV I2CDAT,DATE ; Write DATE to RTC
LCALL I2CWrDat;
MOV I2CDAT,MONTH ; Write MONTH to RTC
LCALL I2CWrDat;
MOV I2CDAT,YEAR ; Write YEAR to RTC
LCALL I2CWrDat;
MOV I2CDAT,CTRL ; Write CTRL to RTC
LCALL I2CWrDat;
LCALL I2CSTOP ; Send Stop Condition
RET ; Return
;*** RTC write 1 Byte ***
;IN REGADR=Address,REGDAT=DATA
RTCWB: MOV I2CADR,#RTCID ; Set RTC as I2C Write Slave
LCALL I2CSLAVE ; Connect Slave
MOV I2CDAT,REGADR ; Set Slave Address
LCALL I2CWrDat ; Write Data to Slave
MOV I2CDAT,REGDAT ; Set Slave Address
LCALL I2CWrDat ; Write Data to Slave
LCALL I2CSTOP ; Send Stop Condition
RET ; Return
;*** I2C Data Write ***
; IN I2CDAT
; REG: R5
I2CWrDat:
PUSH ACC ;Push ACC.
SETB I2CACK ;Set ACK. bit
MOV A,I2CDAT ;Get Data
MOV R5,#008 ;Set loop 8 times
I2CWrD1:RLC A ;Rotate ACC. to Left with Carry
MOV SDA,C ;Move Carry Flag to SDA
ACALL I2CCLK ;Pulse I2C Clock
DJNZ R5,I2CWrD1 ;Do until 8 times
SETB SDA ;Set SDA
ACALL I2CDELAY ;Delay
SETB SCL ;Set SCL
ACALL I2CDELAY ;Delay
JB SDA,I2CWrD2 ;Check Acknowledge from Slave
CLR I2CACK ;Clear ACK. bit
I2CWrD2:CLR SCL ;Clear SCL
POP ACC ;Pop ACC.
RET ;Return
;*** I2C Data Read ***
; OUT I2CDAT
; REG: R5
I2CRdDat:
PUSH ACC ;Push ACC.
CLR A ;Clear ACC.
MOV R5,#08 ;Set loop 8 times
I2CRdD1:ACALL I2CDELAY ;Delay
SETB SCL ;Set SCL
ACALL I2CDELAY ;Delay
MOV C,SDA ;Get SDA to Carry Flag
RLC A ;Rotate ACC. to Left with Carry
CLR SCL ;Clear SCL
DJNZ R5,I2CRdD1 ;Do until 8 times
MOV I2CDAT,A ;Move Data to I2CDAT
POP ACC ;Pop ACC.
RET ;Return
;*** I2C Slave Connect ***
;IN I2CADR
;OUT Flag: I2CACK
;REG: R5
I2CSLAVE:
PUSH ACC ;Push ACC.
SETB I2CACK ;Set ACK. bit
MOV A,I2CADR ;Get Slave Address
ACALL I2CSTART ;Send Start Condition
MOV R5,#008 ;Set loop 8 times
I2CSLA1:RLC A ;Rotate ACC. to Left with Carry
MOV SDA,C ;Move Carry Flag to SDA
ACALL I2CCLK ;Pulse I2C Clock
DJNZ R5,I2CSLA1 ;Do until 8 times
SETB SDA ;Set SDA
ACALL I2CDELAY ;Delay
SETB SCL ;Set SCL
ACALL I2CDELAY ;Delay
JB SDA,I2CSLA2 ;Check Acknowledge from Slave
CLR I2CACK ;Clear ACK.
I2CSLA2:CLR SCL ;Clear SCL
POP ACC ;Pop ACC.
RET ;Return
;*** I2C Start Condition ***
I2CSTART:
JNB SCL,I2CST1 ;Check current SCL set?
CLR SCL ;Clear SCL
I2CST1: SETB SDA ;Set SDA
SETB SCL ;Set SCL
ACALL I2CDELAY ;Delay
CLR SDA ;Clear SDA during SCL set
ACALL I2CDELAY ;Delay
CLR SCL ;Clear SCL
RET ;Return
;*** I2C Stop Condition ***
I2CSTOP:JNB SCL,I2CSTP1 ;Check current SCL set?
CLR SCL ;Clear SCL
I2CSTP1:CLR SDA ;Clear SDA
ACALL I2CDELAY ;Delay
SETB SCL ;Set SCL
ACALL I2CDELAY ;Delay
SETB SDA ;Set SDA during SCL set
RET ;Return
;*** I2C Clock ***
I2CCLK: ACALL I2CDELAY ;Pulse SCL
SETB SCL
ACALL I2CDELAY
CLR SCL
RET ;Return
;*** I2C Acknowledge***
I2CAckBit:
CLR SDA ;Clear SDA
ACALL I2CDELAY ;Delay
ACALL I2CCLK ;Pulse I2C Clock
SETB SDA
RET ;Return
;*** I2C Not Acknowledge ***
I2CNackBit:
SETB SDA ;Set SDA
ACALL I2CDELAY ;Delay
ACALL I2CCLK ;Pulse I2C Clock
SETB SCL
RET ;Return
;*** Dummy Delay time I2CDELAY, LCD_DELAY, 10m, 100m, 1s ***
I2CDELAY: MOV R6,#00CH ; Each loop = 50 us
I2C_DELAY_1: NOP
NOP
DJNZ R6,I2C_DELAY_1
RET
DELAY_10ms: MOV R7,#010 ;Do 10 times
DELAY_10ms_1: MOV R6,#0E6H ;Each loop = 1 ms
DELAY_10ms_2: NOP
NOP
DJNZ R6,DELAY_10ms_2
DJNZ R7,DELAY_10ms_1
RET
DELAY_100ms: MOV R7,#100 ;Do 100 times
DELAY_100ms_1: MOV R6,#0E6H ;Each loop = 1 ms
DELAY_100ms_2: NOP
NOP
DJNZ R6,DELAY_100ms_2
DJNZ R7,DELAY_100ms_1
RET
DELAY_1s: MOV R5,#100 ;Do 100 times
DELAY_1s_1: ACALL DELAY_10ms
DJNZ R5,DELAY_1s_1
RET
;*** Send String in Program Memory ***
;Input DPTR
SendSROM:
CLR A
MOVC A,@A+DPTR ;load char
JZ EndStr ;yes end
LCALL SBYTE ;send 1 byte
INC DPTR ;point to next char
SJMP SendSROM ;load next char
EndStr: RET
;*** Send String in RAM ***
;Input R0
SendSRAM:
MOV A,@R0
LCALL SBYTE ;send 1 byte
INC R0 ;point to next char
DJNZ R7,SendSRAM
;SJMP SendSRAM ;load next char
EndRStr:
RET
;*** Initial UART ***
InitUART:
MOV SCON,#01010010B ;Set SCON Serial Control Mode 1: 8-bit UART (Timer-Based).
MOV TMOD,#00100000B ;Set Mode 2 8-bit Auto-Reload
MOV TH1,#0FDH ;Set Baud Rate 9600
SETB TR1 ;Enable Timer 1
RET
; ********** SBYTE SUB **********
;SEND BYTE
;IN = A
;REG = NO
SBYTE: JNB TI,SBYTE ;Wait For Sending done
CLR TI
MOV SBUF,A
RET
; ********** RBYTE SUB **********
;OUT = A
;REG = A
RBYTE: JNB RI,RBYTE ;Wait For Receive already
CLR RI
MOV A,SBUF
RET
;*** DUMP table in InternalRAM 8 Byte ***
;R0 Ptr to table in internal RAM
;
;R0,R6,R7
DumpI: MOV A,R0
MOV R7,A ;store Ptr in R7
MOV R6,#8
Dumpx: MOV A,@R0
LCALL SBYTEH
INC R0
MOV A,#' ' ;separate with ' '
LCALL SBYTE
DJNZ R6,Dumpx
MOV R6,#8
Dspc: MOV A,#' ' ;separate with ' '
LCALL SBYTE
DJNZ R6,Dspc
MOV A,R7 ;Restore Ptr
MOV R0,A
MOV R6,#8
DASC: MOV A,@R0
MOV R7,A
SUBB A,#' '
JC Dmark
MOV A,R7
LCALL SBYTE
JMP Dloop
Dmark: MOV A,#'.'
LCALL SBYTE
Dloop: INC R0
DJNZ R6,DASC
LCALL LineFeed
RET
;*** Send line feed ***
LineFeed:
MOV A,#0Dh
LCALL SBYTE
feed: MOV A,#0Ah
LCALL SBYTE
RET
; ********** SBYTEH SUB **********
; SEND 2 BYTE HEX FROM A
; IN = A
; REG = A,R2,R3
SBYTEH: LCALL HTOA
MOV A,R2
LCALL SBYTE
MOV A,R3
LCALL SBYTE
RET
; ********** HTOA SUB **********
; CONVERT HEX TO ASCII
; IN = A
; OUT = R2,R3
; REG = A,R2,R3
HTOA: PUSH ACC
SWAP A
LCALL HTOAS
MOV R2,A
POP ACC
LCALL HTOAS
MOV R3,A
RET
HTOAS: ANL A,#0FH
CJNE A,#0AH,$+3
JNC HTOAS1
ORL A,#30H
RET
HTOAS1: SUBB A,#9
ORL A,#40H
RET
;*** String LEN ***
;IN R0
;OUT A
Strlen: MOV R2,#0
StrLNx: MOV A,@R0
XRL A,#0
JZ StrLEX
INC R0
INC R2
SJMP StrLNx
StrLEX: MOV A,R2
RET
Hello: DB 0DH,"*** RTC DS1307 ***",0DH,0AH,00
ErrMsg1: DB 0Dh,0Ah,'Invalid Command',00
ErrMsg2: DB 0Dh,0Ah,'buffer full',0Dh,0Ah,00
ErrMsg3: DB 0Dh,0Ah,'Lenght Error',0Dh,0Ah,00
Abortx: DB 0Dh,0Ah,'*** Abort ***',0Dh,0Ah,00
Command1: DB 'w',00
Command2: DB 'r',00
Command3: DB 'x',00
END