RasCreationKing said:Greetings to everyone!
I am new to the forum and I've been reading some interesting stuff on the message board.
I need help, I am designing a real time clock using PIC16F877 and DS1302. I write the software using MPLAB assembler language. I am having a problem of setting time,date and day using assembler. The LCD display do not display anything. Can anyone help with an example code in assembler on how to set date, and time for DS1302 using PIC16f877.
Your help is greatly appreciated.
Yours Truly
Ras Creation King
Can anyone help with an example code in assembler on how to set date, and time for DS1302 using PIC16f877.
CONV_ASCII_RTN ; ASCII conversion routine
SWAPF BUFFER1,W ; w now contains buffer1, with nibbles inverted
ANDLW 0FH ; AND buffer1 with 1111 to get NIBBLE in lower bits
ADDLW 30H ; add 30h (b'110000') to make ASCII
MOVWF HiNibble ; save HiNibble
MOVF BUFFER1,W ; move buffer1 back to W to get the high byte
ANDLW 0FH ; AND buffer1 with 1111 to get NIBBLE in lower bits
ADDLW 30H ; add 30h (b'110000') to make ASCII
MOVWF LoNibble ; save LoNibble
RETURN
READ_SEC ; DS1302 read seconds register
BSF IO_RST ; take IO reset high to initiate transfer
MOVLW 81H ; binary is 10000001 read seconds command
MOVWF BUFFER1 ; store it in the buffer
CALL SHIFT_OUT ; and send to DS 1320
CALL SHIFT_IN ; read a bite from DS1320
BCF IO_RST ; IO_RST low
RETURN
READ_MIN ; DS1302 read minutes register
BSF IO_RST ; take IO reset high to initiate transfer
MOVLW 83H ; binary is 10000011 read minutes command
MOVWF BUFFER1 ; store it in the buffer
CALL SHIFT_OUT ; and send to DS 1320
CALL SHIFT_IN ; read a bite from DS1320
BCF IO_RST ; IO_RST low
RETURN
READ_HOUR ; DS1302 read hour register
BSF IO_RST
MOVLW 85H
MOVWF BUFFER1
CALL SHIFT_OUT
CALL SHIFT_IN
BCF IO_RST ; IO_RST low
RETURN
READ_DAY ; DS1302 read day register
BSF IO_RST
MOVLW 87H
MOVWF BUFFER1
CALL SHIFT_OUT
CALL SHIFT_IN
BCF IO_RST ; IO_RST low
RETURN
READ_MONTH ; DS1302 read month register
BSF IO_RST
MOVLW 89H
MOVWF BUFFER1
CALL SHIFT_OUT
CALL SHIFT_IN
BCF IO_RST ; IO_RST low
RETURN
READ_YEAR ; DS1302 read year register
BSF IO_RST
MOVLW 8DH
MOVWF BUFFER1
CALL SHIFT_OUT
CALL SHIFT_IN
BCF IO_RST
RETURN
DS1302_INIT_RTN
SET_SEC ; Set seconds on DS1302
BSF IO_RST ; take IO reset high to init transfer
MOVLW 8EH ; Write protect off bin 10001110
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 00H ; Write protect on
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST ; toggle IO reset
NOP
BSF IO_RST ; IO_RST high
MOVLW 80H ; Select second register
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
; this needs to have a set_time var moved into W, rather than literal: ie 55h.
; MOVLW 55H ; This is the value seconds will be set at.
MOVF CLOCK_SEC, W ; ***! UPDATED !***
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST ; IO_RST low
RETURN
SET_MIN ; Set minutes on DS1302
BSF IO_RST ; take IO reset high to init transfer
MOVLW 8EH ; Write protect off
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 00H ; Write protect on
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST ; toggle IO reset
NOP
BSF IO_RST
MOVLW 82H ; b'10000010' is write minutes command
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
; MOVLW 59H ; This is the value minutes will be set at.
MOVF CLOCK_MIN, W ; ***! UPDATED !***
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST ; IO_RST low
RETURN
SET_HOUR ; Set hours on DS1302
BSF IO_RST ; take IO reset high to init transfer
MOVLW 8EH ; Write protect off
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 00H ; Write protect on
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST ; toggle IO reset
NOP
BSF IO_RST
MOVLW 84H ; b'10000100' is write hour command.
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
; MOVLW 22h ; This is the value that will be set in hours. 23H
MOVF CLOCK_HRS, W ; ***! UPDATED !***
; working here the time is set before entering the routine, so look for all calls to set_hour!
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST
RETURN
SET_DAY ; Set days on DS1302
BSF IO_RST ; take IO reset high to init transfer
MOVLW 8EH ; Write protect off
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 00H
MOVWF BUFFER1
CALL SHIFT_OUT
BCF IO_RST ; toggle IO reset
NOP
BSF IO_RST
MOVLW 86H ; b'10000110' is write date command.
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 31H ; This is the value that is set.
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST
RETURN
SET_MONTH ; Set months on DS1302
BSF IO_RST ; take IO reset high to init transfer
MOVLW 8EH ; Write protect off
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 00H
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST ; toggle IO reset
NOP
BSF IO_RST
MOVLW 88H ; '10001000' is write month command.
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 12H ; This is the value that is set.
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST
RETURN
SET_YEAR ; Set years on DS1302
BSF IO_RST ; take IO reset high to init transfer
MOVLW 8EH ; Write protect off
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 00H
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST ; toggle IO reset
NOP
BSF IO_RST
MOVLW 8CH ; b'10001100' is write year command.
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
MOVLW 01H ; This is the value that is set.
MOVWF BUFFER1 ; send to ds 1320
CALL SHIFT_OUT
BCF IO_RST
RETURN
SHIFT_IN ; Read a byte from the DS1302 and store it in BUFFER1
BSF STATUS,RP0 ; bank 1
MOVLW B'00000100' ; make b2 an input
MOVWF TRISA
BCF STATUS,RP0 ; bank 0
MOVLW .8
MOVWF LOOP_CNT1 ; initialize loop counter for 8 bits of data
CLRF BUFFER1 ; clear the buffer
BCF IO_CLK
SH_2 BSF IO_CLK
BCF STATUS,C
BTFSC IO_DATA
BSF STATUS,C
BCF IO_CLK
RRF BUFFER1, F ; rotate the buffer
DECFSZ LOOP_CNT1, F
GOTO SH_2
BSF STATUS,RP0
MOVLW B'00000000'
MOVWF TRISA
BCF STATUS,RP0
RETURN
SHIFT_OUT ; DS1302 serial out routine
MOVWF BUFFER1
MOVLW .8
MOVWF LOOP_CNT1
BCF IO_CLK
SH_1
BTFSC BUFFER1,0
BSF IO_DATA
BTFSS BUFFER1,0
BCF IO_DATA
BSF IO_CLK
RRF BUFFER1,1
BCF IO_CLK
DECFSZ LOOP_CNT1, F
GOTO SH_1
RETURN
That's because I haven't included any LCD source in this clip. At that time I was using a serial LCD, so it's likely my routines wouldn't work for your project.I don't see where you initialised LCD.
;;;**********************************************************************************************************
;;; Subroutine Name: Readtime
;;; Description: Read the clock and store the time in vars.
;;;
;;; Requires: Three vars for each part of time - hours, minutes, seconds,
;;; day, month, year.
;;; Returns: An ascii char in each of the Hi/Low vars.
;;; Locations Affected: W and all the variables used.
;;;**********************************************************************************************************
Readtime ; ***! LOOKS LIKE THIS COULD USE WORKING HERE SOON! !***
; If I got rid of all the high low ascii vars, could also get rid of
; call convert to ascii and below in each!
CALL READ_HOUR
; readTime rd_hrs
MOVF BUFFER1, W ; load the raw data
MOVWF BCD_HOURS ; STORE THE RAW VALUE
CALL CONV_ASCII_RTN ; BCD to ASCII
MOVF HiNibble, W ; NIBBLE
MOVWF HOURS_H ; Store the high byte
MOVF LoNibble, W ; NIBBLE
MOVWF HOURS_L ; Store the low byte
CALL READ_MIN
; readTime rd_min
MOVF BUFFER1, W ; load the raw data
MOVWF BCD_MINUTES ; STORE THE RAW VALUE
CALL CONV_ASCII_RTN ; BCD to ASCII
MOVF HiNibble,W ; NIBBLE
MOVWF MINUTES_H ; Store the high byte
MOVF LoNibble,W ; NIBBLE
MOVWF MINUTES_L ; Store the low byte
CALL READ_SEC
; readTime rd_sec
MOVF BUFFER1, W ; load the raw data
MOVWF BCD_SECONDS ; STORE THE RAW VALUE
CALL CONV_ASCII_RTN ; BCD to ASCII
MOVF HiNibble,W ; NIBBLE
MOVWF SECONDS_H ; Store the high byte
MOVF LoNibble,W ; NIBBLE
MOVWF SECONDS_L ; Store the low byte
CALL READ_DAY
; readTime rd_day
MOVF BUFFER1, W ; load the raw data
MOVWF BCD_DAYS ;
CALL CONV_ASCII_RTN ; BCD to ASCII
MOVF HiNibble,W ; NIBBLE
MOVWF DAYS_H ; Store the high byte
MOVF LoNibble,W ; NIBBLE
MOVWF DAYS_L ; Store the low byte
CALL READ_MONTH
; readTime rd_mth
MOVF BUFFER1, W ; load the raw data
MOVWF BCD_MONTH ;
CALL CONV_ASCII_RTN ; BCD to ASCII
MOVF HiNibble,W ; NIBBLE
MOVWF MONTHS_H ; Store the high byte
MOVF LoNibble,W ; NIBBLE
MOVWF MONTHS_L ; Store the low byte
CALL READ_YEAR
; readTime rd_yr
MOVF BUFFER1, W ; load the raw data
MOVWF BCD_YEAR ;
CALL CONV_ASCII_RTN ; BCD to ASCII
MOVF HiNibble,W ; NIBBLE
MOVWF YEARS_H ; Store the high byte
MOVF LoNibble,W ; NIBBLE
MOVWF YEARS_L ; Store the low byte
RETURN
I am using SDA and SCL of PIC 16f877 to communicate with DS1302.
#DEFINE IO_RST PORTA,0 ; SERIAL DATA
#DEFINE IO_CLK PORTA,1 ; SERIAL CLOCK
#DEFINE IO_DATA PORTA,2 ; DATA IN/OUT
;set up the ports
INIT_RTN
CLRWDT
BANK1 ; switch to bank one
MOVLW B'00000111' ; Port A all digital
MOVWF ADCON1
MOVLW B'00000000' ; B'00000000' 0X17 00010000
MOVWF TRISA ; Port A is output
MOVLW B'00001111'
MOVWF TRISC ; PortC is input/output
MOVLW B'00000000'
MOVWF TRISB ; PORTB is output
MOVWF TRISD ; PORTD is output
MOVWF TRISE ; PORTE is output
BANK0 ; switch back to bank zero
You do, however, need to declare some variables.I hope retrieving data(time, date, etc) from variables and display it on LCD would not be troublesome.
; MOVLW 22h ; This is the value that will be set in hours.
MOVF CLOCK_HRS, W ; ***! UPDATED !***
; The folowing are to store time
CBLOCK 0x32
HOURS_H ; VARIABLE 32h
HOURS_L ; VARIABLE 33h
MINUTES_H ; VARIABLE 34h
MINUTES_L ; VARIABLE 35h
SECONDS_H ; VARIABLE 36h
SECONDS_L ; VARIABLE 37h
DAYS_H ; VARIABLE 38h
DAYS_L ; VARIABLE 39h
MONTHS_H ; VARIABLE 3Ah
MONTHS_L ; VARIABLE 3Bh
YEARS_H ; VARIABLE 3Ch
YEARS_L ; VARIABLE 3Dh
...
BCD_HOURS ; VARIABLE 45h change to BCD_SECONDS
BCD_MINUTES ; VARIABLE 46h change to BCD_MINUTES
BCD_SECONDS ; VARIABLE 47h COUNT_HOURS
BCD_DAYS ; VARIABLE 48h COUNT_DAYS
BCD_MONTH ; VARIABLE 49h COUNT_MONTH
BCD_YEAR ; VARIABLE 4Ah 4Ah COUNT_YEAR
ENDC ;***! 0x4A !***
; *************** DECLARE CONSTANTS ********************
; *************** DS1302 CONSTANTS ********************
#define rd_sec 81h
#define rd_min 83h
#define rd_hrs 85h
#define rd_day 87h
#define rd_mth 89h
#define rd_yr 8Dh
#define wt_sec 80h
#define wt_min 82h
#define wt_hrs 84h
#define wt_day 86h
#define wt_mth 88h
#define wt_yr 8Ch
#define loctCmd 8Ch
#define initCmd 8Ch
#define clrCmd 8Ch
#define HiConst b'00000010'
#define LoConst b'00001001'
#define twntThr b'00100011'
;*********************************************************************************************************
;* LCD SUBROUTINEs
;;;**********************************************************************************************************
;;; Subroutine Name: LOCATE_0_0
;;; Description: Sends a command to serial LCD,
;;; calling for coordinates corresponding
;;; to ROW 0, COL 0.
;;; Requires: Nothing.
;;;
;;;
;;; Returns: Nothing.
;;; Locations Affected: W is destroyed.
;;;**********************************************************************************************************
LOCATE_0_0
MOVLW 0A1H ; LOCATE command loctCmd 0,0
CALL SENDCHAR ; send to micro TX_PROC
MOVLW 00H ; ROW 0(x location of display) (X axis is from 0 to 20.)
CALL SENDCHAR ; send location to micro TX_PROC
MOVLW 00H ; COL 0(y location of display) ( Y axis is from 0 to 3)
CALL SENDCHAR ; send location to micro TX_PROC
RETURN
LOCATE_0_1
MOVLW 0A1H ; locate 0,0 command loctCmd
CALL SENDCHAR ; send command to micro TX_PROC
MOVLW 00H ; row 0 command
CALL SENDCHAR ; send command to micro TX_PROC
MOVLW 01H ; colume 1 command
CALL SENDCHAR ; send command to micro TX_PROC
RETURN
CLEAR
MOVLW 0xA3 ; clrCmd
CALL SENDCHAR ; TX_PROC
MOVLW 01H
CALL SENDCHAR ; TX_PROC
RETURN
CURSOR_OFF
MOVLW 0A3H ; cursor off command is 0xA30C, SEND 0xA3
CALL SENDCHAR ; SEND cursor off command TX_PROC
MOVLW 0CH ; second part of cmd is 0x0C
CALL SENDCHAR ; so send it TX_PROC
RETURN
CURSOR_ON
MOVLW 0A3H ; cursor off command is 0xA30C, SEND 0xA3 ***! ??? !***
CALL SENDCHAR ; SEND cursor off command TX_PROC
MOVLW 0CH ; second part of cmd is 0x0C
CALL SENDCHAR ; so send it TX_PROC
RETURN
LCD_INIT
MOVLW 0xA0 ; LCD initialization command is 0A0H initCmd
CALL SENDCHAR ; send the command TX_PROC
MOVLW .200 ; DELAY aroud 600US
CALL DELAY_US ; wait for lcd
RETURN
LCD_STRING
MOVLW 0A2H ; String command (PRINT) is 0xA2
CALL SENDCHAR ; send string command to micro TX_PROC
RETURN
PRINT
MOVLW 0A2H ; string command (print)
CALL SENDCHAR ; send command to micro TX_PROC
RETURN
END_STR CLRF FETCH_SEQ ; clear the variable FETCH_SEQ
MOVLW 00H ; End of string COMMAND
CALL SENDCHAR ; send command to micro TX_PROC
RETURN
;;;*****************************************************************************************************
;;; Subroutine Name: COLON
;;; Description: Print a colon.
;;;
;;; Requires: sub- SENDCHAR.
;;; Returns: A colon on the LCD.
;;; Locations Affected: .
;;;*****************************************************************************************************
COLON
MOVLW 03AH ; COLON COMMAND
CALL SENDCHAR ; TX_PROC
RETURN
;;;*****************************************************************************************************
;;; Subroutine Name: SPACE
;;; Description: Print a blank space.
;;;
;;; Requires: sub- SENDCHAR.
;;; Returns: A space on the LCD.
;;; Locations Affected: .
;;;*****************************************************************************************************
_SPACE
MOVLW 20h ; 0C7H
CALL SENDCHAR ; SENDCMD TX_PROC
RETURN
;;; *********************************************************************************************************
;;; Subroutine Name: SENDCHAR
;;; Description: SENDCHAR outputs a byte to the serial LCD.
;;;
;;; Requires: the char, in ASCII format, to be stored in W, before calling it..
;;; Calls: DELAY_ONE.
;;; Uses variables BUFFER1, LOOP_CNT.
;;; Locations Affected: IO_TX pin, STATUS, BUFFER1.
;;; *********************************************************************************************************
SENDCHAR ; SERIAL OUT
MOVWF BUFFER1 ; Send W reg to file BUFFER1
; From tx procedure
MOVLW .8 ; Because 8BIT transmission,
MOVWF LOOP_CNT ; so count to 8
BCF IO_TX ; send low on lcd bus
CALL DELAY_ONE ; wait 52 usec
SEND_1 CLRWDT ; Clear the watchdog
RRF BUFFER1, F ; rotate variable BUFFER1 to the right
BTFSS STATUS,CF ; CF EQU .0 = STATUS
BCF IO_TX ; IO_TX = PORTB,0 - first pin of B is lcd bus
BTFSC STATUS,CF ;
BSF IO_TX ; set lcd bus high
CALL DELAY_ONE ;
DECFSZ LOOP_CNT, F ; decriment the loop counter
GOTO SEND_1 ; while there is still data o transmit, go back to SEND_1
BSF IO_TX ; lcd bus high
CALL DELAY_ONE ;
RETURN
;**************************************************************************************************************
;* DELAY SUBROUTINEs
;;;**********************************************************************************************************
;;; Subroutine Name: DELAY_ONE
;;; Description: Timer delay for serial LCD,
;;; 4800-> 208US Delay(64) , 192000->52US Delay (14)
;;; Requires: DELAY_US, DL_0.
;;;
;;; Returns: Nothing.
;;; Locations Affected: W is destroyed.
;;;**********************************************************************************************************
DELAY_ONE ;
MOVLW .14 ; 19200 Baud Rate
;MOVLW .64 ; 4800 Baud Rate
DELAY_US
MOVWF DELAY_TIMER
DL_0 DECFSZ DELAY_TIMER, F
GOTO DL_0
RETURN
DELAY_MS
MOVWF LOOP_CNT
CLRF LOOP_CNT1
DE_1 DECFSZ LOOP_CNT1, F
GOTO DE_1
DECFSZ LOOP_CNT, F
GOTO DE_1
RETURN
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?