Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem with the assebmly code PIC16F877 7 Digit Clock

Status
Not open for further replies.

nobody968

Newbie level 3
Joined
Mar 19, 2013
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,303
Hello all:

This is my first post on this board, I was looking for a 7 digit clock project to built as a hobby project I found one at this board along the code, originally the project was for Common Cathode, but the author also provided alternate code for common anode. I did build the common anode version as common cathode 7 digits are not available in my country. However I am having a strange problem that during the AM hours the clock shows digits from 1 - 9 while hour ten digit is blanc, however during PM timings instead the the hour 10 digit goes blanc it shows 8, I have been looking into the code but couldnt seem to find the problem.

I am posting the code here, and would really appreciate any help, to me it seems that there is only one line of code which is causing the problem, as during the AM the hour ten digit is blanc.

Code:
; Adding AM/PM -ok (11-Aug-2009
; fixed with this - ok	(23-July-2009)
;	Common Cathode ( For Common Anode Change Table And Search And Change (bsf PORTC,7) to (bcf PORTC,7)
;	Blanking First Digit If Zero (AM/PM Indicator Will Be Done Later)
;	Shrinking - Phase1 - ok
;	Adding Keys To Adjust Time - ok
;	Added Hour + And Hour - And Min+ And Min- (from 4 keys 1=setup 2=+ 3=- 4=Done)
;	Update From RTC only Done Hourly After Time Tics xx:59:59 -> xx:00:00 (to Avoide Flicker) Using 4Mhz
;########################################################################################################
;########################################################################################################
;#################################	Wish To Do List		#########################################
; 
; 
; 
;########################################################################################################
;########################################################################################################
	LIST	p=16F877a		;tell assembler what chip we are using
	include "P16F877a.inc"		;include the defaults for the chip
	ERRORLEVEL	0,	-302	;suppress bank selection messages
;	__config 0x3939			;sets the configuration settings (oscillator type etc.)for 16F87x
   __config 0x3F39         
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;rtc  Read Write Address
I2C_PORT	Equ	PORTB
I2C_TRIS	Equ	TRISB

Chip_Read	Equ	0xD1			;DS1307 address values
Chip_Write	Equ	0xD0
Buf_Size	Equ	0x03			;buffer 3 bytes long

ErrFlag		Equ	0x00
StartFlag	Equ	0x01			;flags used for received bit
One		Equ	0x02
Zero		Equ	0x03
Time		Equ	0x04			;flag for setting time, line1 or line2

#define		SCL	1
#define		SDA 	2

		CBLOCK	0x20
			Secs
			Mins			 
			Hrs
			DisplayPosition	; Store Location Here - should Find Another Way
			DispStatus	;bit0 - colon	2- Update Time 3-Am/Pm
			tempcount
			tempcount1
; For Delay
			count1		;used in delay routine
			counta		;used in delay routine
			countb		;used in delay routine
; I2C Temps
			count		;used in looping routines
			DAT_VAL
			_N		; Store Bits Sended I2C
			N		; Buff Size N Number Of Time 2 Read Or Write
			I2C_Address	; DS1307 memory address to be accessed
			Data_Page	; DS1307 page, 0-7
			InputByte	; byte read from DS1307 is stored in this register
			OutputByte	; used for holding byte to be output to DS1307
			I2Cflags	; flag bit register
			HourTen
			HourOne
			MinOne
			MinTen
			SecsTen
			SecsOne
; Store W and Status Register, In Time Of interrupt
			STATUS_TMP	;
			W_TMP		;
		ENDC


Reset		ORG	0x00
		GoTo	Start
		org     0x04			; 
		GoTo	INTRUPT				; 

;########################################################################################################
;########################################################################################################
;-- Table
;########################################################################################################
;########################################################################################################

TABLA		ADDWF	PCL,F
;                      Dp G F E D C B A (RC7-0) 0-On 1-Off
;Common Cathode Also Have To Change (bcf PORTC,7) to (bsf PORTC,7)
; dig1pm (bcf PORTC,7) to (bsf PORTC,7) 
;		RETLW	B'00111111'	; == 0
;		RETLW	B'00000110'	; == 1
;		RETLW	B'01011011'	; == 2
;		RETLW	B'01001111'	; == 3
;		RETLW	B'01100110'	; == 4
;		RETLW	B'01101101'	; == 5
;		RETLW	B'01111101'	; == 6
;		RETLW	B'00000111'	; == 7
;		RETLW	B'01111111'	; == 8
;		RETLW	B'01101111'	; == 9
;		RETLW	B'01000000'	; - 0x0A
;		RETLW	B'01110100'	; h 0x0B
;		RETLW	B'01010100'	; n 0x0C
;		RETLW	0x00
; Common Anode Also Have To Change (bsf PORTC,7) to (bcf PORTC,7) 
; dig1pm (bsf PORTC,7) to (bcf PORTC,7) 
		RETLW	B'11000000'	; == 0
		RETLW	B'11111001'	; == 1
		RETLW	B'10100100'	; == 2
		RETLW	B'10110000'	; == 3
		RETLW	B'10011001'	; == 4
		RETLW	B'10010010'	; == 5
		RETLW	B'10000010'	; == 6
		RETLW	B'11111000'	; == 7
		RETLW	B'10000000'	; == 8
		RETLW	B'10010000'	; == 9
		RETLW	B'10111111'	; - 0x0A
		RETLW	B'10001011'	; h 0x0B
		RETLW	B'10101011'	; n 0x0C
		RETLW	0x00
;########################################################################################################
;########################################################################################################
;-- End Of Table
;########################################################################################################
;########################################################################################################
; start interrupt by saving w and status registers before altered by interrupt routine
;########################################################################################################
;########################################################################################################

INTRUPT		movwf	W_TMP		; w to w_tmp storage
		swapf	STATUS,w	; status to w
		movwf	STATUS_TMP	; status in status_tmp  
		bcf	STATUS,RP0	; select memory bank 0

		btfss	INTCON,T0IF	; TMRO overflow interrupt flag 
		GoTo	RECLAIM
;---------------------------------------------  
;-- Digits To Display
;---------------------------------------------  
		movf	TMR0,w		; timer value	
					; freq is 4MHz/4/4/(256(-8+2))=1kHz
		nop
		nop			; synchronise counter read with divide by 4 ie add two cycles
		addlw	0x8		; add to timer register and takes 2 cycles to start counting
		movwf	TMR0		; place in timer (the two cycles plus 2-cycle delay = 4cycles)
		bcf	INTCON,T0IF	; clear TMRO interrupt flag
; 1000 ms = 1 sec So 500 ms to Clear Colon And The Next To Update Colon and Time
		incfsz	tempcount,f	; 
		GoTo 	CHK_UPD		; 
		incf	tempcount1,f	; 

CHK_UPD		movf	tempcount1,w	; 500 milli Second Check And Add Colon
		xorlw	0x01		;
		btfss	STATUS,Z	;
		GoTo	MPX_DSP		; Not Yet So Multiplex Display
		movf	tempcount,w	;
		xorlw	0xF4		;
					;
		btfss	STATUS,Z	;
		GoTo	MPX_DSP		;
		clrf	tempcount	;
		clrf	tempcount1	;
		incf	tempcount,f	;
		btfsc	DispStatus,0	; 
		GoTo	COL_CR		; If Already On Then Clear Colon
		bsf	DispStatus,0	; 
		bsf	DispStatus,2	; Time For Clock Update
		GoTo	MPX_DSP
COL_CR		bcf	DispStatus,0	; 
;########################################################################################################
;########################################################################################################
;-- Time To Multiplex Display
;########################################################################################################
;########################################################################################################
MPX_DSP		BTFSC	DisplayPosition,0	; See Which Digit's On And Switch Accordingly
		GoTo	Dig2			;If digit 1 On GoTo Digit 2
		BTFSC	DisplayPosition,1
		GoTo	Dig3			;If digit 2 On GoTo Digit 3
		BTFSC	DisplayPosition,2
		GoTo	Dig4			;If digit 3 On GoTo Digit 4
		BTFSC	DisplayPosition,3
		GoTo	Dig5			;If digit 4 On GoTo Digit 5
		BTFSC	DisplayPosition,4
		GoTo	Dig6			;If digit 5 On GoTo Digit 6 If 6 Then Digit 1
; Show Digit 1 Now
Dig1		Clrf	PORTA		; Display Digit 1 That Is Hour Tens
		movf	HourTen,W
		btfsc	STATUS,Z
		GoTo	digcheck_A_P
		btfss	DispStatus,3
		goto	dig1am
dig1pm		movf	HourTen,W
		CALL	TABLA
		MOVWF	PORTC		;
		bcf	PORTC,7
		bsf	PORTA,0		;
		goto	dig1exit
dig1am		movf	HourTen,W
		CALL	TABLA
		MOVWF	PORTC		;
;		bcf	PORTC,7			; added on 18-02-2013 to see if there is no 8
		bsf	PORTA,0		;
		goto	dig1exit
digcheck_A_P	btfss	DispStatus,3
		goto	dig1exit
dig1pm2		clrf	PORTC		;
		bcf	PORTC,7			;
		bsf	PORTA,0		;
		goto	dig1exit
dig1exit	Movlw	b'00000001' 
		movwf	DisplayPosition
		GoTo	RECLAIM
; Show Digit 2 Now
Dig2		Clrf	PORTA		; Display Digit 2 That Is Hour Ones
		MOVF	HourOne,W
		CALL	TABLA
		MOVWF	PORTC		; 
		Btfsc	DispStatus,0	; Check If Time For Displaying Colon 
		bcf	PORTC,7
		bsf	PORTA,1		; 
		Movlw	b'00000010'
		movwf	DisplayPosition
		GoTo	RECLAIM
; Show Digit 3 Now
Dig3		Clrf	PORTA		; Display Digit 3 That Is Minutes Tens
		MOVF	MinTen,W
		CALL	TABLA
		MOVWF	PORTC		; 
		Btfsc	DispStatus,0	; Check If Time For Displaying Colon 
		bcf	PORTC,7
		bsf	PORTA,2		;
		Movlw	b'00000100'
		movwf	DisplayPosition
		GoTo	RECLAIM
; Show Digit 4 Now
Dig4		Clrf	PORTA		; Display Digit 4 That Is Minutes Ones
		MOVF	MinOne,W
		CALL	TABLA
		MOVWF	PORTC
		bsf	PORTA,3		; 
		Movlw	b'00001000'
		movwf	DisplayPosition
		GoTo	RECLAIM
; Show Digit 5 Now
Dig5		Clrf	PORTA		; Display Digit 5 That Is Seconds Tens
		movf	SecsTen,W
		CALL	TABLA
		MOVWF	PORTC		; 
		bsf	PORTA,4		; 
		Movlw	b'00010000'
		movwf	DisplayPosition
		GoTo	RECLAIM
; Show Digit 6 Now
Dig6		Clrf	PORTA		; Display Digit 6 That Is Seconds Ones
		MOVF	SecsOne,W
		CALL	TABLA
		MOVWF	PORTC
		bsf	PORTA,5		;
		Movlw	b'00100000'
		movwf	DisplayPosition
; End Of Digits To Display

; Time To Exit interrupt
RECLAIM		swapf	STATUS_TMP,w	; status temp storage to w
		movwf	STATUS		; w to status register
		swapf	W_TMP,f		; swap upper and lower 4-bits in w_tmp
		swapf   W_TMP,w		; swap bits and into w register
		retfie			; return from interrupt

;########################################################################################################
;########################################################################################################
;--------- Start From Reset Or Power On ------
;---------------------------------------------
;########################################################################################################
;########################################################################################################
Start
		BANKSEL ADCON1			;disable analogue inputs
		movlw 	0x06
		movwf 	ADCON1
		movlw	b'00000000'		;Set port data directions, data output
		movwf	TRISC
		movwf	TRISA
		movlw 	b'11111111'
		movwf	TRISB
		movlw	B'00000001'		; TMRO prescaler 4 division, PORTB pullups enabled
		movwf	OPTION_REG		;
		BANKSEL PORTA			;	select bank 0
;
		clrf	tempcount		; Clear Temprory Registers
		clrf	tempcount1		;	"
		clrf	DispStatus		;	'
;
		movlw	B'11111111'		; Display All Digits And All Segments (Display Test)
		movwf	PORTC
		movlw	B'11111111'
		movwf	PORTA
;
		Call	Delay255		; Give 1 Sec Delay For PowerUp
		Call	Delay255
		Call	Delay255
		Call	Delay255
;
		clrf	PORTC
		movlw	0xff
		movwf	PORTA
;
		Call	seq_out			; Check If RTC Intialized And Setup Time IfNot
		clrf	I2C_Address		; Clear DS1307 Address
		Call	Seq_Read_EEPROM		; Read From RTC
		call	rtc2hours		; RTC Format To Digits
		Movlw	b'00100000'		; Set Display Position
		movwf	DisplayPosition
		movlw	b'10100000'		; TMRO Interupt ON
		movwf	INTCON

MainLoop	nop				; MainLoop
		nop
		btfss	PORTB,5			; See If Setup Key Pressed
		GoTo	Set_key			; Then GoTo
		nop
		nop
		btfss	DispStatus,2		; see update time flag set
		GoTo 	MainLoop		; No so loop
		call	TimeUp			; yes so update time
		nop
		nop
		GoTo	MainLoop

;########################################################################################################
;########################################################################################################
Set_key					; Time To Setup Clock
		btfss	PORTB,5
		GoTo	$-1
		movlw	0x0A
		movwf	SecsTen
		movlw	0x0B
		movwf	SecsOne
loopkeyHour	btfss	PORTB,4		; Finished
		GoTo	EditDone
		btfss	PORTB,5
		GoTo	SetMin		; set mins
		btfss	PORTB,6
		GoTo	Hourplus	; set Hour +
		btfss	PORTB,7
		GoTo	HourMinus	; set Hour -
		call	Delay10
		GoTo	loopkeyHour
;########################################
SetMin
		btfss	PORTB,5
		GoTo	$-1
		movlw	0x0A
		movwf	SecsTen
		movlw	0x0C
		movwf	SecsOne
loopkeyMin	btfss	PORTB,4
		GoTo	EditDone	; Finished
		btfss	PORTB,5
		GoTo	Set_key		; set Hours
		btfss	PORTB,6
		GoTo	Minplus		; set mins +
		btfss	PORTB,7
		GoTo	MinMinus
		call	Delay10		; set mins -
		GoTo	loopkeyMin
;######################################## hour error look between here 
Hourplus
		btfss	PORTB,6		; Wait For Key Release
		GoTo	$-1
		btfss	HourTen,0	; HourTen skip if bit0 = 1
		GoTo	h10_0
h10_1		incf	HourOne,f	; Increment HourOne +1
		movf	HourOne,w
		xorlw	0x02
		btfsc	STATUS,Z	; skip if hour1 = 3
		GoTo	H_AP		; If <3 return to keys loop
		movf	HourOne,W
		xorlw	0x03
		btfss	STATUS,Z	; skip if hour1 more than 3 then Set Time to h10=0 h1=1
		goto	okhr
		movlw	0x01		; If 3 Then Clear HourTen & set HourOne=1 [so hour is 01]
		movwf	HourOne
		clrf	HourTen
		GoTo	okhr
H_AP		btfss	DispStatus,3	; Time Is 12 so set AM/PM;
		goto	$+3
		bcf	DispStatus,3
		goto	$+2
		bsf	DispStatus,3
		goto	okhr
h10_0		incf	HourOne,f	; If HourTen =0 Then Inc HourOne
		movf	HourOne,w
		xorlw	0x0A
		btfss	STATUS,Z	; skip if HourOne =10 Otherwise Finish
		GoTo	okhr
		clrf	HourOne		; If HourOne 10 Then Clear HourOne Ans Set HourTen=1 [so Hour Is 10]
		movlw	0x01
		movwf	HourTen
okhr		call	Delay255
		GoTo	loopkeyHour	;Return to keys
;########################################
HourMinus
		btfss	PORTB,7		; Wait For Key Release
		GoTo	$-1
		btfss	HourTen,0	; skip if HourTen = 1
		GoTo	h10_0_minus
		movf	HourOne,w	; if HourTen = 0 and see If HourOne is 0
		btfsc	STATUS,Z	; Then Skip to ---> h10_1_mi
		GoTo	h10_1_mi
h10_1_minus	decf	HourOne,f	; If HourOne Not 0 Then decrement HourOne And Return
		GoTo	okhr_minus
h10_1_mi	movlw	0x09		; If HourTen And HourOne is 0 then -
		movwf	HourOne		; Clear HourTen and 9 -> HourOne [so hour is 09]
		clrf	HourTen
		GoTo	okhr_minus
h10_0_minus	decfsz	HourOne,f	; if HourTen = 1 then decrement HourOne And Skip If Zero
		GoTo	okhr_minus	; If Else return to keys
		movlw	0x02		; If HourOne 0 Then Move 2 -> HourOne & 1 -> HourTen -
		movwf	HourOne		; [so hour is 12] And Return
		movlw	0x01
		movwf	HourTen
		btfss	DispStatus,3
		goto	$+3
		bcf	DispStatus,3
		goto	$+2
		bsf	DispStatus,3
okhr_minus	call	Delay255
		GoTo	loopkeyHour	;Return to keys
;######################################## and here
Minplus	
		btfss	PORTB,6		; Wait For Key Release
		GoTo	$-1
		incf	MinOne,f	; Increment MinOne and check if 10
		movf	MinOne,w
		xorlw	0x0A
		btfss	STATUS,Z	; skip if MinOne = 10 If Else return to keys
		GoTo	okmin
		clrf	MinOne		; if MinOne=10 the clear MinOne And Inc MinTen
		incf	MinTen,f
		movf	MinTen,w
		xorlw	0x06
		btfss	STATUS,Z	; skip if MinTen = 6 If Else Return to keys
		GoTo	okmin
		clrf	MinTen		; If MinTen=6 The Clear MinTen and return
okmin		call	Delay255
		GoTo	loopkeyMin	;Return to keys
;########################################
MinMinus
		btfss	PORTB,7		; Wait For Key Release
		GoTo	$-1
		movf	MinOne,w	; Check If MinOne = 0
		btfss	STATUS,Z	; If 0 Then Skip
		GoTo	MinusMin2	; If Not 0 Then GoTo ---> MinusMin2
		movf	MinTen,w	; Check If MinTen = 0 (Already Checked MinOne = 0)
		btfsc	STATUS,Z
		GoTo	MinusMin3
MinusMin4	movlw	0x09		; If MinOne = 0 & MinTen Not 0 Then Set 9 ->MinOne And -
		movwf	MinOne		; decrement MinTen And Return
		decf	MinTen,f
		GoTo	okminMinus
MinusMin3	movlw	0x05		; If MinOne And MinTen = 0 Then Set 5 ->MinTen & 9 ->MinOne
		movwf	MinTen		; [so Mins is 59]
		movlw	0x09
		movwf	MinOne
		GoTo	okminMinus
MinusMin2	decf	MinOne,f
okminMinus	call	Delay255
		GoTo	loopkeyMin	;Return to keys
;########################################
EditDone
		btfss	PORTB,5		; Wait For Key Release
		GoTo	$-1
		clrf	SecsTen		; Clear Seconds Before Exiting Setup
		clrf	SecsOne		; Clear Seconds Before Exiting Setup
		call	WriteRtc	; Update The Changed Values To DS1307
		GoTo	MainLoop	; And Return To MainLoop
;########################################################################################################
;########################################################################################################
; Time Update
;########################################################################################################
;########################################################################################################
TimeUp		bcf	DispStatus,2
		incf	SecsOne,f
		movf	SecsOne,w
		xorlw	0x0A
		btfss	STATUS,Z	;skip if SecsOne = 10
		return
		clrf	SecsOne
		incf	SecsTen,f
		movf	SecsTen,w
		xorlw	0x06
		btfss	STATUS,Z	;skip if SecsTen = 6
		return
		clrf	SecsTen
MinP		incf	MinOne,f
		movf	MinOne,w
		xorlw	0x0A
		btfss	STATUS,Z	;skip if MinOne = 10
		return
		clrf	MinOne
		incf	MinTen,f
		movf	MinTen,w
		xorlw	0x06
		btfss	STATUS,Z	;skip if MinTen = 6
		return
		clrf	MinTen
		call	Readrtc		; Update Time From RTC (only Done Hourly After Time Tics xx:59:59)
		return
;########################################################################################################
;########################################################################################################
;Start of I2C Services
;########################################################################################################
;########################################################################################################
seq_out		clrf	Data_Page		;check if ds1307 already initialized
		movlw	0x07
		movwf	I2C_Address		;
		call	Read_EEPROM
		movwf	count1
		btfsc	count1,4		; Just Temprery
		return				; if yes return
		clrf	Data_Page
		movlw	0x02
		movwf	I2C_Address		;
		movlw	0x72
		call	Write_EEPROM		; am/pm set hour 12:00:00
		clrf	Data_Page		;
		movlw	0x07
		movwf	I2C_Address		;
		movlw	0x10
		call	Write_EEPROM		; Square Wave Enable. _|-|_|-|_|-|_|-|_|-|_
		clrf	Data_Page		;
		movlw	0x01
		movwf	I2C_Address		;
		movlw	0x00
		call	Write_EEPROM		; Minutes xx:00:xx
		movlw	0x00
		movwf	I2C_Address		;
		movlw	0x00
		call	Write_EEPROM		; Seconds xx:xx:00
		return
;
; SubRoutine "ds1307_Read" ;------------------------------------------------------  
Readrtc
		bcf	INTCON,GIE
		clrf	I2C_Address			;set DS1307 address		
		call	Seq_Read_EEPROM		;read data in to buffer
		call	rtc2hours
		bsf	INTCON,GIE
		Return

rtc2hours	swapf	Hrs,w
		andlw	0x01
		movwf	HourTen
		movf	Hrs,w
		andlw	0x0F
		btfss	Hrs,5
		goto	$+3
		bsf	DispStatus,3
		goto	$+2
		bcf	DispStatus,3
rtc2mins	movwf	HourOne
		swapf	Mins,w
		andlw	0x0F
		movwf	MinTen
		movf	Mins,w
		andlw	0x0F
		movwf	MinOne
rtc2secs	swapf	Secs,w
		andlw	0x0F
		movwf	SecsTen
		movf	Secs,w
		andlw	0x0F
		movwf	SecsOne
		Return
; SubRoutine "ds1307_Write" ;------------------------------------------------------  
WriteRtc	bcf	INTCON,GIE
		swapf	SecsTen,w
		iorwf	SecsOne,w
		movwf	Secs
		swapf	MinTen,w
		iorwf	MinOne,w
		movwf	Mins
		swapf	HourTen,w
		iorwf	HourOne,w
		movwf	Hrs
		btfsc	DispStatus,3
		goto	$+4
		movlw	0x40		; AM
		addwf	Hrs,F
		goto	$+3
		movlw	0x60		; PM
		addwf	Hrs,F
		clrf	Data_Page		;set DS1307 page
		clrf	I2C_Address		;set DS1307 address		
		Call	Seq_Write_EEPROM
		bsf	INTCON,GIE
		Return
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
;Start of I2C routines

Write_EEPROM					; write W register to address I2C_Address
		movwf	DAT_VAL			; save W
		call	I2C_STARTa
		call	I2C_Set_Write

; If ACK error display 'e'

		btfsc	I2Cflags, 0
		call	Error_Routine

		call	I2C_Lo_Adr

; If ACK error display 'f'

		btfsc	I2Cflags, 0
		call	Error_Routine1

        	movf	DAT_VAL, 	W	; send the actual data
        	movwf	OutputByte
        	call	I2C_Out
        	call	I2C_NAK

; If ACK error display 'g'

		btfsc	I2Cflags, 0
		call	Error_Routine2

        	call	I2C_STOPa 
		call	WaitForWrite
        	return

Read_EEPROM					; reads data at location specified in I2C_Address
						; and page specified in Data_Page
						; returns result in W
		call 	I2C_STARTa

		call	I2C_Set_Write

; If ACK error display 'e'

		btfsc	I2Cflags, 0
		call	Error_Routine

		call	I2C_Lo_Adr

; If ACK error display 'f'

		btfsc	I2Cflags, 0
		call	Error_Routine1

        	call 	I2C_STARTa		; note there is no STOP
		call	I2C_Set_Read

; If ACK error display 'g'

		btfsc	I2Cflags, 0
		call	Error_Routine2

        	call 	I2C_READa		; fetch the byte
        	call 	I2C_Send_NAK		; send no acknowledgement

        	call 	I2C_STOPa
		movf 	InputByte, 	W	; return the byte in W
        	return

Seq_Write_EEPROM				; write buffer to address I2C_Address
		movwf	DAT_VAL			; save W
		call	I2C_STARTa
		call	I2C_Set_Write

; If ACK error display 'e'

		btfsc	I2Cflags, 0
		call	Error_Routine


		call	I2C_Lo_Adr

; If ACK error display 'f'

		btfsc	I2Cflags, 	0
		call	Error_Routine1

		movlw 	Secs			; now write Buff_Size bytes to DS1307
		movwf 	FSR		
		movlw 	Buf_Size
		movwf 	N
SEQ_WRITE_1:
		movf 	INDF, 		w	; fetch the data byte from the buffer
        	movwf	OutputByte
        	call	I2C_Out
        	call 	I2C_NAK

; If ACK error display 'g'

		btfsc	I2Cflags, 0
		call	Error_Routine2

		incf 	FSR, 		f
		decfsz 	N, 		f
		GoTo 	SEQ_WRITE_1

        	call	I2C_STOPa 
		call	WaitForWrite
        	return


Seq_Read_EEPROM					; reads data at location specified in I2C_Address
						; and page specified in Data_Page
;						; returns 4 byte result in secs
		call 	I2C_STARTa
		call	I2C_Set_Write

; If ACK error display 'e'

		btfsc	I2Cflags, 0
		call	Error_Routine

		call	I2C_Lo_Adr

; If ACK error display 'f'

		btfsc	I2Cflags, 0
		call	Error_Routine1

        	call 	I2C_STARTa		; note there is no STOP
		call	I2C_Set_Read

; If ACK error display 'g'

		btfsc	I2Cflags, 0
		call	Error_Routine2

		movlw 	Secs			; now sequentially read bytes from DS1307
		movwf 	FSR		
		movlw 	Buf_Size
		movwf 	N
SEQ_READ_1:
		call 	I2C_READa		; fetch each byte from DS1307
		movf 	InputByte,	w
		movwf 	INDF			; and save in data buffer
		incf 	FSR,		f
		decfsz 	N, 		f
		GoTo 	SEQ_READ_2		; not done
		GoTo 	SEQ_READ_3

SEQ_READ_2:
		call 	I2C_ACK			; if not done, send an ACK and continue
		GoTo 	SEQ_READ_1
SEQ_READ_3:

        	call 	I2C_Send_NAK		; send no acknowledgement

        	call 	I2C_STOPa
		movf 	InputByte, 	w	; return the byte in W
        	return

; The following routines are low level I2C routines applicable to most
; interfaces with I2C devices.

I2C_READa					; read byte on i2c bus
		clrf 	InputByte
		movlw 	0x08
		movwf 	_N			; set index to 8	
		call	HIGH_SDA		; be sure SDA is configured as input
In_Bit
		call 	HIGH_SCL		; clock high
		btfss 	I2C_PORT,	SDA	; test SDA bit
		GoTo	In_Zero
		GoTo	In_One

In_Zero
		bcf 	STATUS, 	C	; clear carry
		rlf 	InputByte, 	f	; i_byte = i_byte << 1 | 0
		GoTo 	Cont_In

In_One
		bsf	STATUS, 	C	; set carry
		rlf 	InputByte, 	f

Cont_In
		call	LOW_SCL			; bring clock low
		decfsz 	_N, 	F		; decrement index
		GoTo 	In_Bit
		return

I2C_Out:					; send w register on I2C bus
        	movwf 	OutputByte
		movlw 	0x08
		movwf 	_N
Out_Bit:
		bcf 	STATUS,		C	; clear carry
		rlf 	OutputByte, 	f	; left shift, most sig bit is now in carry
		btfss 	STATUS, 	C	; if one, send a one
		GoTo 	Out_Zero
		GoTo 	Out_One

Out_Zero:
		call 	LOW_SDA			; SDA at zero
		call 	Clock_Pulse	
		call 	HIGH_SDA
		GoTo 	Out_Cont

Out_One:
		call 	HIGH_SDA		; SDA at logic one
		call 	Clock_Pulse
Out_Cont:
		decfsz 	_N,		F	; decrement index
		GoTo 	Out_Bit
		return	

;;;;;;
		
I2C_NAK:					; bring SDA high and clock
		call 	HIGH_SDA
		call 	HIGH_SCL

		clrf	count			; wait for ACK
WaitForACK	incf	count, f		; increase timeout counter each time ACK is not received
		btfsc	STATUS, Z
		GoTo	No_ACK_Rec
		btfsc	I2C_PORT,	SDA	; test pin. If clear, DS1307 is pulling SDA low for ACK
		GoTo	WaitForACK		; ...otherwise, continue to wait
		bcf	I2Cflags, 0		; clear flag bit (ACK received)
		call 	LOW_SCL
		return

I2C_Send_NAK:					; bring SDA high and clock
		call 	HIGH_SDA
		call 	Clock_Pulse
		return

WaitForWrite					; poll ACK for write timing
		call 	I2C_STARTa
		call	I2C_Set_Write
		btfsc	I2Cflags, 0
		GoTo	WaitForWrite
		return

;------ No ACK received from slave (must use "return" from here)
;; Typically, set a flag bit to indicate failed write and check for it upon return.
No_ACK_Rec
		bsf	I2Cflags, 0		; set flag bit
		retlw 0x00

;------ No ACK received from slave.  This is the error handler.
Error_Routine
; Output error message, etc. here
		movlw	'e'
		retlw 0x00				; returns to INITIAL calling routine

Error_Routine1
; Output error message, etc. here
		movlw	'f'
		retlw 0x00

Error_Routine2
; Output error message, etc. here
		movlw	'g'
		retlw 0x00

I2C_ACK:
		call 	LOW_SDA
		call 	Clock_Pulse
		return

I2C_STARTa:				
;		call 	LOW_SCL ;;
;		call 	HIGH_SDA ;;
		call 	HIGH_SCL
		call 	LOW_SDA			; bring SDA low while SCL is high
		call 	LOW_SCL
		return

I2C_STOPa:
		call 	LOW_SCL
		call 	LOW_SDA
		call 	HIGH_SCL
		call 	HIGH_SDA		; bring SDA high while SCL is high
;		call 	LOW_SCL ;;
		return

I2C_Set_Write	rlf 	Data_Page, 	W	; shift device page
		andlw	b'00001110'		; AND to make sure in range
        	iorlw 	Chip_Write
        	call 	I2C_Out
        	call 	I2C_NAK
		return

I2C_Set_Read	rlf 	Data_Page, 	W	; shift device page
		andlw	b'00001110'		; AND to make sure in range
        	iorlw 	Chip_Read
        	call 	I2C_Out
        	call 	I2C_NAK
		return

I2C_Lo_Adr      movf 	I2C_Address, 	W	; send low byte of address
        	call 	I2C_Out
        	call 	I2C_NAK
		return

Clock_Pulse:					; SCL momentarily to logic one
		call 	HIGH_SCL
		call 	LOW_SCL
		return		

HIGH_SDA:					; high impedance by making SDA an input
		bsf 	STATUS, 	RP0	; bank 1
		bsf 	I2C_TRIS, 	SDA	; make SDA pin an input
		bcf 	STATUS, 	RP0	; back to bank 0
		return

LOW_SDA:
		bcf 	I2C_PORT, 	SDA	
		bsf 	STATUS, 	RP0	; bank 1
		bcf 	I2C_TRIS, 	SDA	; make SDA pin an output
		bcf 	STATUS, 	RP0	; back to bank 0
		return

HIGH_SCL:
		bsf 	STATUS, 	RP0	; bank 1
		bsf 	I2C_TRIS, 	SCL	; make SCL pin an input
		bcf 	STATUS, 	RP0	; back to bank 0
		return

LOW_SCL:
		bcf	I2C_PORT, 	SCL
		bsf 	STATUS, 	RP0	; bank 1
		bcf 	I2C_TRIS, 	SCL	; make SCL pin an output
		bcf 	STATUS, 	RP0	; back to bank 0
		return

; End of I2C routines
;########################################################################################################
;########################################################################################################
;########################################################################################################
;########################################################################################################
; Delay routines
;
;
Delay255	movlw	0xff		;delay 255 mS
		GoTo	d0
Delay100	movlw	d'100'		;delay 100mS
		GoTo	d0
Delay50		movlw	d'50'		;delay 50mS
		GoTo	d0
Delay20		movlw	d'20'		;delay 20mS
		GoTo	d0
Delay10		movlw	d'10'		;delay 10mS
		GoTo	d0
Delay5		movlw	0x05		;delay 5.000 ms (4 MHz clock)
d0		movwf	count1
d1		movlw	0xC7
		movwf	counta
		movlw	0x01
		movwf	countb
Delay_0		decfsz	counta, f
		GoTo	$+2
		decfsz	countb, f
		GoTo	Delay_0

		decfsz	count1	,f
		GoTo	d1
		retlw	0x00

;end of Delay routines
		End
 

Hi,

A thousand lines of code and you expect someone to pick out a single error !!:evil:

Have you contacted the author to see what he says ?


Two other ways to overcome your problem, if you have a Pickit or ICD programmer / debugger you might be able to run the debugger and watch the code that way or run the code in a simulator and debug it that way.

Might help if you post the site link so we can see the whole project in case the fault is in the hardware ..?
 

Personally I've never been good with PIC's assembly but having looked at the code I think your problem is in the following area, rest i think guys good with PIC assmbly could point out.

Code:
; Common Anode Also Have To Change (bsf PORTC,7) to (bcf PORTC,7) 
; dig1pm (bsf PORTC,7) to (bcf PORTC,7) 
;######################################## hour error look between here 
Hourplus
		btfss	PORTB,6		; Wait For Key Release
		GoTo	$-1
		btfss	HourTen,0	; HourTen skip if bit0 = 1
		GoTo	h10_0
h10_1		incf	HourOne,f	; Increment HourOne +1
		movf	HourOne,w
		xorlw	0x02
		btfsc	STATUS,Z	; skip if hour1 = 3
		GoTo	H_AP		; If <3 return to keys loop
		movf	HourOne,W
		xorlw	0x03
		btfss	STATUS,Z	; skip if hour1 more than 3 then Set Time to h10=0 h1=1
		goto	okhr
		movlw	0x01		; If 3 Then Clear HourTen & set HourOne=1 [so hour is 01]
		movwf	HourOne
		clrf	HourTen
		GoTo	okhr
H_AP		btfss	DispStatus,3	; Time Is 12 so set AM/PM;
		goto	$+3
		bcf	DispStatus,3
		goto	$+2
		bsf	DispStatus,3
		goto	okhr
h10_0		incf	HourOne,f	; If HourTen =0 Then Inc HourOne
		movf	HourOne,w
		xorlw	0x0A
		btfss	STATUS,Z	; skip if HourOne =10 Otherwise Finish
		GoTo	okhr
		clrf	HourOne		; If HourOne 10 Then Clear HourOne Ans Set HourTen=1 [so Hour Is 10]
		movlw	0x01
		movwf	HourTen
okhr		call	Delay255
		GoTo	loopkeyHour	;Return to keys
;########################################
HourMinus
		btfss	PORTB,7		; Wait For Key Release
		GoTo	$-1
		btfss	HourTen,0	; skip if HourTen = 1
		GoTo	h10_0_minus
		movf	HourOne,w	; if HourTen = 0 and see If HourOne is 0
		btfsc	STATUS,Z	; Then Skip to ---> h10_1_mi
		GoTo	h10_1_mi
h10_1_minus	decf	HourOne,f	; If HourOne Not 0 Then decrement HourOne And Return
		GoTo	okhr_minus
h10_1_mi	movlw	0x09		; If HourTen And HourOne is 0 then -
		movwf	HourOne		; Clear HourTen and 9 -> HourOne [so hour is 09]
		clrf	HourTen
		GoTo	okhr_minus
h10_0_minus	decfsz	HourOne,f	; if HourTen = 1 then decrement HourOne And Skip If Zero
		GoTo	okhr_minus	; If Else return to keys
		movlw	0x02		; If HourOne 0 Then Move 2 -> HourOne & 1 -> HourTen -
		movwf	HourOne		; [so hour is 12] And Return
		movlw	0x01
		movwf	HourTen
		btfss	DispStatus,3
		goto	$+3
		bcf	DispStatus,3
		goto	$+2
		bsf	DispStatus,3
okhr_minus	call	Delay255
		GoTo	loopkeyHour	;Return to keys
;######################################## and here
 
abidr thanks.

can some expert in PIC assembly help me sort this problem out.
 

Hi,

You need to show a link or diagram for that code, then a simulation can be done to check where the error is.
 

Attached is the complete project along proteus DSN file, original author's link both on edaboard and his other links are dead.

Thanks
 

Attachments

  • 16F876 Clock_common_Anode (2).rar
    67 KB · Views: 79

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top