PIC16C745 with DS1302

Status
Not open for further replies.

jean_88

New Member
Hello guy, i am new here.
just finish reading a few posts and find this forum helpful

Well, i faced a problem programming DS1302 with PIC16C745.

my problem is:
i have write in time for the RTC and after 2 mins from it start, it have to turn off my LED which is initially on.
i got the program out already, but i don't know where i have went wrong that the program is unable to work.

i really hope someone can provide me with help

the following is my program.

LIST P=16C745
#INCLUDE <P16C745.INC>
#DEFINE CE PORTC,0 ;Define PORTC,0 as CE, so as to show the link between PIC16C745 and DS1302
#DEFINE SCLK PORTC,1 ;
#DEFINE IO PORTC,2 ;

errorlevel -302 ; suppress "register not in Bank 0, check page bits" message

Bank0 udata
REGWRITE RES 1 ;To define all the following label, use this method (XXXX RES 1)
TIME_COUNT RES 1
TIME_TEMP RES 1



;--------------------------------END OF DECLARATION-------------------------------------
ORG 0

MAIN
BCF STATUS,RP0 ;Activates Bank 0, because PORT(X) located in Bank 0 - See PIC16C745 memory table.
CLRF PORTB ;Resets PORTB, Set B'00000000' into PORTB
BSF STATUS,RP0 ;Activates Bank 1, because TRIS(X) located in Bank 1
MOVLW B'00000000' ;Set PORTB as output port
MOVWF TRISB ;Send the previous binary to this exact location
BCF STATUS,RP0 ;Activates Bank 0, because PORT(X) located in Bank 0 - See PIC16C745 memory table.
BSF PORTB,6 ;Turns on LED
BSF PORTB,7 ;Turns on LED

;------------------------DS1302 Real Time Counter-------------------------------

Start
CALL WRITE_EN ;Call this subroutine so as to start up the transmission between PIC and RTC
MOVLW 0X8E ;Insert B'10001110' into REGWRITE, to point to the address - Control
MOVWF REGWRITE ;
CALL WRITE_RTC ;Call this subroutine whenever you are inputing the number into RTC
MOVLW 0x00 ;Control register
MOVWF REGWRITE ;
CALL WRITE_RTC
;******************************************
CALL WRITE_EN
MOVLW 0X80 ;Insert B'10000000' into REGWRITE, to point to the address - Sec
MOVWF REGWRITE
CALL WRITE_RTC
MOVLW 0X00 ;Second will start at 0
MOVWF REGWRITE
CALL WRITE_RTC
;******************************************
CALL WRITE_EN
MOVLW 0X82 ;Insert B'10000010' into REGWRITE, to point to the address - Min
MOVWF REGWRITE
CALL WRITE_RTC
MOVLW 0X03 ;Minute will start at 3
MOVWF REGWRITE
CALL WRITE_RTC
;******************************************
CALL WRITE_EN
MOVLW 0X84 ;Insert B'10000100' into REGWRITE, to point to the address - Hour
MOVWF REGWRITE
CALL WRITE_RTC
MOVLW 0X15 ;Hour will start at 3pm
MOVWF REGWRITE
CALL WRITE_RTC
;******************************************
the code below is the part where i test whether is it 2 mins past, if yes, turn off the initially on LED, is there sth wrong?
TURNOFF_LED
CALL READ_MIN
MOVF TIME_TEMP,W
SUBLW 0X05
BTFSS STATUS,Z
GOTO TURNOFF_LED
BCF STATUS,C
BCF PORTB,7
GOTO MAIN
Until here..
;******************************************
READ_MIN
CALL WRITE_EN
MOVLW 0X83 ;In order to read, you need to mention which address you want to read
MOVWF REGWRITE
CALL WRITE_RTC
BSF STATUS,RP0
MOVLW B'00000100'
MOVWF TRISC
BCF STATUS,RP0
CALL READ_RTC
NOP
BCF CE
NOP
NOP
RETURN

;----------------------------------Subroutines----------------------------------------
WRITE_EN
CLRF PORTC ;Resets PORTC, Set Binary '00000000' into PORTC
BSF STATUS,RP0 ;Activates Bank 1, because TRIS(X) located in Bank 1
MOVLW B'00000000' ;Using this line and the following line together means
MOVWF TRISC ;to set binary '00000000' into PORTC, to set as output
BCF STATUS,RP0 ;Activates Bank 0
BSF CE ;Input logic '1' to RST of DS1302, all communication sequences are intitiated by driving RST high
RETURN
;******************************************
WRITE_RTC
MOVLW 0X08 ;'0X' is use for hexadecimal, 08 is the hexadecimal number.
MOVWF TIME_COUNT ;Move the hexadecimal into this TIME_COUNT label

WRITE_LOOP
BCF SCLK ;Disallow data movement
BSF IO ;Set I/O pin to 'high'
BTFSS REGWRITE,0 ;Ensure that bit 0 is a 0, so that it mean to write into the RTC
BCF IO ;Set I/O pin to 'low'
NOP ;No operation, coz' this command provide a timing break to the next command
BSF SCLK ;Allow data movement since there is a need to write to RTC
RRF REGWRITE,1 ;Rotates bit 1 in REGWRITE to the right, and put the result back in REGWRITE
DECFSZ TIME_COUNT,1;Decrements a file register and if the result is zero, skips the next instruction and result will be put back into file register
GOTO WRITE_LOOP ;Looping
RETURN
;******************************************
READ_RTC
CLRF TIME_TEMP
MOVLW 0X08 ;'0X' is use for hexadecimal, 08 is the hexadecimal number.
MOVWF TIME_COUNT ;Move the hexadecimal into this TIME_COUNT label

READ_LOOP
BSF SCLK
BSF STATUS,C
BTFSS IO
BCF STATUS,C
BCF SCLK
RRF TIME_TEMP,1
DECFSZ TIME_COUNT,1;Delay
GOTO READ_LOOP ;Looping
MOVF TIME_TEMP,0

RETURN
;******************************************
;------------------------------------------End of Subroutine-------------------------------------

END
 
Well my attention span isn't what it used to be, so I'm not going to try to debug your code.

But, what I will say, is to seperate your code. From the sound of it, the only 'output' you have is that little LED. Not much indication of what is going on. I would first make sure that the RTC is working correctly.

That is, write (or copy from your above code) a routine to program the DS1302. Then read it back. This will involves some form of 'SPI-like' interface....which you appear to have. Also, I believe the PIC16C745 has a UART? It may be beneficial to use it to communicate with a PC to see what is going on. Read the time from the RTC, and send it to the UART. You do'nt have to format it in anyway. It may be over-kill but it'll be helpfull...otherwise how would you know if you are writing/reading the RTC correctly? Or perhaps some LED's....maybe an LED flash routine after every write/read. So if your LED doesn't flash at all, you know it has got stuck somewhere.

Step by step my friend, it may be a long process rather than just spotting the problem in your code...but its good practice.

I assume you MUST use an RTC? if all you need to do is to turn off an LED 2 minutes after the microcontroller is powered....just use a delay routine. You know the clock frequency, so its just a matter of counting.

Blueteeth

Also, I just noticed a bit of your code If you assume it is all working perfectly...and it does indeed turn off the LED after 2 minutes (when the minutes gets to '5' in your code) then it goes back to 'main'. And what happens there? you set up the ports and turn the LED back on! the time it is 'off' is only a few CPU cycles, so unless you're using a VERY slow clock you won't see it turn off then on again and it will appear to stay on.

After you have turned off the LED, simply have a loop that goes nowhere. OR....a delay so you can at least see the LED turn off.
 
Last edited:
Please use Code tags when posting code. Simply click on the # in the menu before pasting your code.

By the way, you don't have to use uppercase for all your code. In my opinion that just makes it hard to read.

Code tags make it look like this:
Code:
	LIST	P=16C745
	#INCLUDE <P16C745.INC>
	#DEFINE	CE	PORTC,0	;Define PORTC,0 as CE, so as to show the link between PIC16C745 and DS1302
	#DEFINE	SCLK	PORTC,1 ;
	#DEFINE	IO	PORTC,2 ;

	errorlevel -302	; suppress "register not in Bank 0, check page bits" message

Bank0 udata
REGWRITE	RES	1	;To define all the following label, use this method (XXXX RES 1)
TIME_COUNT	RES	1
TIME_TEMP	RES	1



;--------------------------------END OF DECLARATION-------------------------------------
	ORG	0

MAIN	BCF	STATUS,RP0	;Activates Bank 0, because PORT(X) located in Bank 0 - See PIC16C745 memory table.
	CLRF	PORTB		;Resets PORTB, Set B'00000000' into PORTB
	BSF	STATUS,RP0	;Activates Bank 1, because TRIS(X) located in Bank 1
	MOVLW	B'00000000'	;Set PORTB as output port
	MOVWF	TRISB		;Send the previous binary to this exact location
	BCF	STATUS,RP0	;Activates Bank 0, because PORT(X) located in Bank 0 - See PIC16C745 memory table.
	BSF	PORTB,6		;Turns on LED
	BSF	PORTB,7		;Turns on LED

;------------------------DS1302 Real Time Counter-------------------------------

Start	CALL	WRITE_EN	;Call this subroutine so as to start up the transmission between PIC and RTC
	MOVLW	0X8E		;Insert B'10001110' into REGWRITE, to point to the address - Control
	MOVWF	REGWRITE	;
	CALL	WRITE_RTC	;Call this subroutine whenever you are inputing the number into RTC
	MOVLW	0x00		;Control register
	MOVWF	REGWRITE ;
	CALL	WRITE_RTC
;******************************************
	CALL	WRITE_EN
	MOVLW	0X80		;Insert B'10000000' into REGWRITE, to point to the address - Sec
	MOVWF	REGWRITE
	CALL	WRITE_RTC
	MOVLW	0X00		;Second will start at 0
	MOVWF	REGWRITE
	CALL	WRITE_RTC
;******************************************
	CALL	WRITE_EN
	MOVLW	0X82		;Insert B'10000010' into REGWRITE, to point to the address - Min
	MOVWF	REGWRITE
	CALL	WRITE_RTC
	MOVLW	0X03		;Minute will start at 3
	MOVWF	REGWRITE
	CALL	WRITE_RTC
;******************************************
	CALL	WRITE_EN
	MOVLW	0X84		;Insert B'10000100' into REGWRITE, to point to the address - Hour
	MOVWF	REGWRITE
	CALL	WRITE_RTC
	MOVLW	0X15		;Hour will start at 3pm
	MOVWF	REGWRITE
	CALL	WRITE_RTC
;******************************************
the code below is the part where i test whether is it 2 mins past, if yes, turn off the initially on LED, is there sth wrong?
TURNOFF_LED
	CALL	READ_MIN
	MOVF	TIME_TEMP,W
	SUBLW	0X05
	BTFSS	STATUS,Z
	GOTO	TURNOFF_LED
	BCF	STATUS,C
	BCF	PORTB,7
	GOTO	MAIN
Until here..
;******************************************
READ_MIN
	CALL	WRITE_EN
	MOVLW	0X83		;In order to read, you need to mention which address you want to read
	MOVWF	REGWRITE
	CALL	WRITE_RTC
	BSF	STATUS,RP0
	MOVLW	B'00000100'
	MOVWF	TRISC
	BCF	STATUS,RP0
	CALL	READ_RTC
	NOP
	BCF	CE
	NOP
	NOP
	RETURN

;----------------------------------Subroutines----------------------------------------
WRITE_EN
	CLRF	PORTC		;Resets PORTC, Set Binary '00000000' into PORTC
	BSF	STATUS,RP0	;Activates Bank 1, because TRIS(X) located in Bank 1
	MOVLW	B'00000000'	;Using this line and the following line together means
	MOVWF	TRISC		;to set binary '00000000' into PORTC, to set as output
	BCF	STATUS,RP0	;Activates Bank 0
	BSF	CE		;Input logic '1' to RST of DS1302, all communication sequences are intitiated by driving RST high
	RETURN
;******************************************
WRITE_RTC
	MOVLW	0X08		;'0X' is use for hexadecimal, 08 is the hexadecimal number.
	MOVWF	TIME_COUNT	;Move the hexadecimal into this TIME_COUNT label

WRITE_LOOP
	BCF	SCLK		;Disallow data movement
	BSF	IO		;Set I/O pin to 'high'
	BTFSS	REGWRITE,0	;Ensure that bit 0 is a 0, so that it mean to write into the RTC
	BCF	IO		;Set I/O pin to 'low'
	NOP			;No operation, coz' this command provide a timing break to the next command
	BSF	SCLK	 ;Allow data movement since there is a need to write to RTC
	RRF	REGWRITE,1	;Rotates bit 1 in REGWRITE to the right, and put the result back in REGWRITE
	DECFSZ	TIME_COUNT,1	;Decrements a file register and if the result is zero, skips the next instruction and result will be put back into file register
	GOTO	WRITE_LOOP	;Looping
	RETURN
;******************************************
READ_RTC
	CLRF	TIME_TEMP
	MOVLW	0X08		;'0X' is use for hexadecimal, 08 is the hexadecimal number.
	MOVWF	TIME_COUNT	;Move the hexadecimal into this TIME_COUNT label

READ_LOOP
	BSF	SCLK
	BSF	STATUS,C
	BTFSS	IO
	BCF	STATUS,C
	BCF	SCLK
	RRF	TIME_TEMP,1
	DECFSZ	TIME_COUNT,1	;Delay
	GOTO	READ_LOOP	;Looping
	MOVF	TIME_TEMP,0

	RETURN
;******************************************
;------------------------------------------End of Subroutine-------------------------------------

	END
 
One quick comment - why are you using an OTP device? - even assuming you have UV eraseable verions, it makes for a massively slow programming cycle!.

Use one of the more modern EEPROM or FLASH based chips, it will be so much faster.
 
thanks to those who reply and provide guides. =)

i uses OTP because it's my school project, and my lecturer only want PIC16C745. so i have to use it. =)
 
OTP devices? Thats a bit harsh! Your 'lecturer' can't expect all software to work flawlessly first time..unless its a course on using software emulators and debuggers Making mistakes and having to reprogram the chip is whats makes for a good education.

Anyway, did you get it working?
 
I assume he is using the JW version that has a window so it can be UV erased. A good eraser wipes them in a couple of minutes.

If he isn't using a JW version then I would use a similar flash pic to get the I2C working and then get the USB working later.

Mike.
 
Last edited:
No. i did not get it working.
therefore i needed people here to help me.

to blueteeth,
talking about the 'goto main' that thing, i made adjustment already, however, the problem don't seem to be it.
 
Need help again

the previous problem about the LED turning off automatically after 2 minutes from the RTC clocking have already works. =)

and for now, i added in a subroutine so that for whichever time that comes in from an external GUI, i am able to also turn off the LED after two minutes from that time set in the GUI. but my subroutine don't seemed to work. can anyone help me out in this? thanks

Code:
		CALL	SMS_TIME
		
TURNOFF_LED
		CALL	READ_MIN
		MOVF	TIME_TEMP,W
		SUBWF	smstime,0
		BTFSS	STATUS,Z
		GOTO	TURNOFF_LED
		BCF	PORTB,7
		BCF	STATUS,C
Loop	GOTO	Loop

SMS_TIME
		CALL	READ_MIN
		MOVF	TIME_TEMP,W
		ADDLW	0X04
		MOVWF	smstime
		RETURN
 
Assuming that your Read_Min subroutine gets the minute value from the DS1302 then it will be in BCD format. You cannot just add 4. Think what happens when the minute value is 17, when you add 4 it becomes 1B which is not a valid time.

What you need to do is bcd addition.
Try,
Code:
		CALL	READ_MIN
		MOVF	TIME_TEMP,W
		addlw	0x04		;add 4
		addlw	0x06		;add 6 to test for overflow
		btfss	STATUS,DC	;overflowed
		addlw	0x100-0x06	;no so add -6 (sub 6)
		MOVWF	smstime

Mike.
 
isn't there a flash version of the pic ? if so lay with that then change for the OTP device to keep your teacher happy
 
thanks for the reply, prommie and thunderchild.

To prommie,
i tried out your codes, but i don't think the problem lies on the part you wrote in. but i think i will definitely need it too. =)

i think the SMS_TIME subroutine seemed to have alittle problem.
when my program goes like this:

Code:
		CALL	SMS_TIME
		
TURNOFF_LED
		CALL	READ_MIN
		MOVF	TIME_TEMP,W
		SUBWF	smstime,0
		BTFSS	STATUS,Z
		GOTO	TURNOFF_LED
		BCF	PORTB,7
		BCF	STATUS,C
Loop	GOTO	Loop

SMS_TIME
		CALL	READ_MIN
		MOVF	TIME_TEMP,W
		MOVLW   OXOB
		MOVWF	smstime
		RETURN

what i expect from the above code, is to have 0x0B in smstime, so that the LED will turn off after 2 mins from the time i put in by myself, not from GUI for this instance, but it still wouldn't work. Why is that so?
 
The value you receive from the 1302 will never equal 0x0b and so the subtraction will never result in zero. The minutes value will go from 0x09 to 0x10 and therefore miss out 0x0b.

Mike.
 
oh
but previously i tried a simple program using 0x0b, it works..

but most important is that, i not sure whether the program really goes into the subroutine (SMS_TIME).
 
If it worked with 0x0b then you must have written that value to the 1302. The 1302 will never produce 0x0b during normal operation. You cannot have a value of 11 (0x0b) in the units digit, the next increment after 0x09 will be 0x10.

Mike.
 
futz said:
By the way, you don't have to use uppercase for all your code. In my opinion that just makes it hard to read.

I choose not to use case or all lower case in asm code for the same reason. It truely depends on what font type and name being used the determines the level of appeasement.
 
oh, okok..

to prommie:

oh. make me really confused how come mine works now. *scratch head*

erm, by the way, if i really want to turn off the LED after 2 mins using RTC and also with the subroutine, can you like write a simple sample for me, so to roughly give me an idea how should it be?
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…