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