PIC16F886 - Problem att via I2C läsa in data från RTC-krets

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
kabelhaerva
Inlägg: 93
Blev medlem: 11 september 2010, 09:41:58
Ort: Gbg

PIC16F886 - Problem att via I2C läsa in data från RTC-krets

Inlägg av kabelhaerva »

Hej,
Håller på och försöker kommunicera med en RTC-krets (PCF8563) från en mikrokontroller (PIC16F866).
Använder mig av den inbyggda MSSP-modulen och skall skicka data via I2C.
Är helt ny på det här med seriell kommunikation, och större delen av koden är kopierad från C-kod jag fann på det stora oöverskådliga nätet, och översatt till assemblerspråk.

Att skriva data till RTC'n verkar fungera eftersom jag får tillbaka en acknowledge-signal, men sen när jag vill läsa data så fastnar jag i en loop för att receiver-bufferten (SSPSTAT, BF) aldrig blir full.
Är det något jag glömt eller missat här, måste jag cleara nån flagga i något annat register för att RTC'n ska få tillgång till att skriva?
Har testat ifall det skulle vara Write Collision eller Receive Overflow, men när jag testar bitarna i SSPCON registret så är de riktigt satta så det kan inte vara problemet.

Som jag har byggt upp programmet nu så skickas det data (00110000=30 i BCD-kod) till reg. 03h(minuter-registret i RTC) och direkt efter det försöker jag läsa in vad som blev skrivet till samma register, men där tar det som sagt stopp.
Nån som har erfarenhet av I2C-kommunikation och PIC?
Säg till ifall jag inte gett tillräcklig information, kan inte komma på något mer nu som kan tänkas tilläggas.

Kod:

Kod: Markera allt

	list      p=16f886             ; list directive to define processor
 	#include <p16f886.inc>         ; processor specific variable definitions
; 
 __CONFIG _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
 __CONFIG _CONFIG2, _WRT_OFF & _BOR21V
; These configs sets everything up in a standard manner with internal Oscilator at 4MHz by default.

Variables 	UDATA_SHR		;Sets up a block of variables 

DelayVar1		RES 1	    ;Puts these two in a shared memory we don't have to care about the banks when accessing them.          
DelayVar2		RES 1
byte_data		RES 1
temp_data		RES 1
rtc_addr		RES	1
rtc_reg			RES	1


;RESET_VECTOR    CODE    0x000       ; processor reset vector
;	goto	Init             	; go to beginning of program

;INT_VECTOR      CODE    0x004       ; interrupt vector location
;	retfie                      ; Ingen interrupt kod...

;*********************************************************
	errorlevel -302

	org 0 
;*********************************************************
;************************INIT*****************************
;*********************************************************
Init
;Temporary interrupt-settings
	banksel	INTCON
	bcf		INTCON, GIE	;Disable all interrupts. Won't be used in this program.

;Analog Init
	banksel	ANSEL	;Make sure all analog functions are 
	clrf	ANSEL	;disabled since we won't be using them.
	clrf	ANSELH


;TRIS
	banksel	TRISA	;set all pins to outputs
	clrf 	TRISA	
	clrf	TRISB
	;clrf	TRISC
	movlw	b'00001100'	;set RC3-RC4 as input (SDA/SCL)
	movwf	TRISC
	clrf	TRISE

;PORT
	banksel	PORTA	;clear all ports (=0V out)
	clrf	PORTA
	clrf	PORTB
	clrf	PORTC
	clrf	PORTE


;I2C MSSP
init_mssp
	banksel	SSPCON
	movlw	b'00111000'		;/* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
	movwf	SSPCON
	
	banksel	SSPSTAT
	movlw	b'11000000'		;/* Slew rate disabled */
	movwf	SSPSTAT

;	banksel	SSPADD			;<---- Är i samma bank som SSPSTAT på pic16f886
	movlw	b'00001001'		;/* 100Khz @ 4Mhz Fosc */
	movwf	SSPADD			


	banksel	PORTA			;lika bra att vara i bank0 vid main
	movlw	b'10100011'		;bit0 sätter R/W-mode, bit 7-1=addressen hos RTC'n
	movwf	rtc_addr

	goto main

;*********************************************************
;************************START****************************
;*********************************************************
	
main
	call	Delay



	call 	send_start_bit


	bcf		rtc_addr, 0			;bcf Write-mode, bsf blir Read-mode	
	movfw	rtc_addr
	call	send_byte

	movlw	0x03				;register Minutes i RTC kretsen.  				
	call	send_byte



	movlw	b'00110000'			;30 min BCD kodat alltså 0101 1001 = 59
	call	send_byte



	
	call	send_stop_bit


;*************************************************************
;nu läser vi in för att se om det blev inskrivet i RTC kretsen

	call 	send_start_bit


	movfw	rtc_addr			;slav-adressen
	call	send_byte

	movlw	0x03				;register Minutes i RTC kretsen.  				
	call	send_byte

	call	send_restart_bit

	bsf		rtc_addr, 0			;nu läser vi istället
	movfw	rtc_addr
	call	send_byte


	call	receive_byte
	;1 byte data läst som lagras i temp_data

	

	movlw	b'00110000'
	subwf	temp_data, w
	btfss  STATUS,Z    			; Test for Zero flag set   *****	SET=lika	CLEAR=olika
    	goto	main   	
	banksel	PORTB	
	bsf		PORTB, 5	

	call	send_stop_bit

	
	



;*********************************************************
;**********************Subroutines************************
;*********************************************************


;debugger funktion, blinkar led på B5 porten 2 gånger med ca 0,2s mellanrum
debug1
	banksel	PORTB
	bsf		PORTB, 5
	call	Delay
	bcf		PORTB, 5
	call	Delay
	bsf		PORTB, 5
	call	Delay
	bcf		PORTB, 5
	return




send_start_bit					;skickar start bit och väntar tills den är färdig (auto-reset av PIC'en)
	
	banksel	SSPCON2
	bsf		SSPCON2, 0
wait1
	btfsc	SSPCON2, 0
		goto	wait1
	return

;--------------------

send_stop_bit					;skickar stop bit och väntar tills den är färdig (auto-reset av PIC'en)
	banksel	SSPCON2
	bsf		SSPCON2, 2
wait2
	btfsc	SSPCON2, 2
		goto	wait2
	return

;--------------------

send_restart_bit				;skickar restart bit och väntar tills den är färdig (auto-reset av PIC'en)
	banksel	SSPCON2
	bsf		SSPCON2, 1			;Repeated Start Condition Enabled bit
wait3
	btfsc	SSPCON2, 1
		goto	wait3
	return

;--------------------

send_acknowledge_bit			;skickar acknowledge bit och väntar tills den är färdig (auto-reset av PIC'en)
	banksel	SSPCON2
	bcf		SSPCON2, 5			;Acknowledge Data bit
	bsf		SSPCON2, 4			;Acknowledge Sequence Enable bit
wait4
	btfsc	SSPCON2, 4
		goto	wait4
	return

;--------------------

send_no_acknowledge_bit			;skickar NO-acknowledge bit och väntar tills den är färdig (auto-reset av PIC'en)
	banksel	SSPCON2
	bsf		SSPCON2, 5			;Acknowledge Data bit
	bsf		SSPCON2, 4			;Acknowledge Sequence Enable bit
wait5
	btfsc	SSPCON2, 4
		goto	wait5
	return

;--------------------

send_byte						;skickar1 st byte data och väntar tills transfern är färdig, genom att kika BF i sspstat
	banksel	SSPBUF
	;movfw	byte_data
	movwf	SSPBUF
	banksel	SSPSTAT
wait6
	btfsc	SSPSTAT, 0			;Buffer Full Status bit   OBS! Olika för transmit/receive. 
		goto wait6				;Receive - färdig=1,	Transmit - färdig=0
	banksel	SSPCON2
	btfsc	SSPCON2, 6			; kollar om vi fått acknowledge från slave-modul
		goto wait6				; tydligen inte, börja om testerna tills vi fått det.
	return

;--------------------

receive_byte
	banksel	SSPCON2
	bsf		SSPCON2, 3			;Receive Enable bit 

	banksel	SSPSTAT
wait7
	btfss	SSPSTAT, 0			;Buffer full status bit - 1=complete/buffer full    0=not complete/buffer empty
		goto	wait7
	banksel	SSPBUF
	movfw	SSPBUF
	movwf	temp_data

;DEBUG1
;	call	debug1
;/DEBUG1

	call	transfer_wait

	banksel	SSPCON2
	btfss	SSPCON2, 5			; kollar om vi fått acknowledge från slave-modul
		goto $+3				; Byt ut denna buggfaktor sen, gör det på riktigt istället. 
								; Här ska det callas en byte-skift funktion.
								; ex: lagra byte emottagen, upp till receive_byte igen för att lägga
								; in nästa byte i temp_data.
								; I denna applikation behövs dock inte det då vi max får tillbaks en byte data.
	btfsc	SSPSTAT, 4			; nej ingen Acknowledge, alltså är det slut på data och vi kikar istället
		goto $-1				; efter en stop bit.
			

	movfw	temp_data
	return

;--------------------

transfer_wait
	movlw	b'00011111'			; put the value to compare with in W
	banksel	SSPCON2
wait8
    subwf  SSPCON2,w   			; subtract W from the File Register, put result in W

	btfss  STATUS,Z    			; Test for Zero flag set   *****	SET=lika	CLEAR=olika
    	goto	wait8   		; vänta tills alla bitar i SSPCON2 är 0, gå då vidare
	banksel	SSPSTAT
wait9
	btfsc	SSPSTAT, 2			; 1 = Transmit is in progress 
		goto	wait9			; 0 = Transmit is not in progress
	return

;*********************************************************
;*************************Delays**************************
;*********************************************************


Delay	;Delays about 200ms @ 4MHz
	movlw	h'ff'
	movwf	DelayVar1

Delay2
	movlw	h'ff'
	movwf	DelayVar2
	
Delay3
	nop
	nop
	nop
	nop
	decfsz	DelayVar2, f
	goto	Delay3
	
	decfsz	DelayVar1, f
	goto	Delay2
	
	return


;*********************************************************


	END