Problem with SPI comunication of a PIC

For C and ASSEMBLY users to post questions and code snippets for programming in C and ASSEMBLY. And for any other C or ASM course related questions.

Moderators: Benj, Mods

Post Reply
datch
Posts: 2
Joined: Mon Nov 06, 2006 3:31 pm
Contact:

Problem with SPI comunication of a PIC

Post by datch »

HI all

We tried to use SPI comunication mode to comunicate with a sensor called ADNS 2620. We want to receive a data from the sensor and we use the SPI. First we send the address of the register in which this data is,then we must wait 100 microsec.After that we should receive the data but the sensor doesn't transmit anything.
This is the code we are written in assembler for PIC16F877a.
We accept any suggest...also C code...

list p=16F877a
#include "p16F877a.inc"
errorlevel -302

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

deltaX RES 1
;riservo due bytes per salvare i risultati

;********************************************
ORG 0 ; Begin Code at location 0
nop
;setto la USART
BANKSEL SPBRG
movlw B'10000001'
movwf SPBRG

BANKSEL TXSTA
movlw B'00100110'
movwf TXSTA

BANKSEL RCSTA
movlw B'10000000'
movwf RCSTA

;********************************************
; Set up the SPI Port
BANKSEL TRISC ; BANK 1
movlw B'10010000' ; SCK is output (Master), Sd is input,
movwf TRISC ; SDO is output, all others output
BANKSEL SSPSTAT
movlw B'00000000' ; Mode 1,1 SPI, middle of output
movwf SSPSTAT ; time sampling
BANKSEL SSPCON ; BANK 0
movlw B'00110001' ; Mode 1,1 SPI Master Mode, 1/16 Tosc bittime
movwf SSPCON ; SSP is on


;********************************************
;controllo se esco dal loop
movf B'00110010',w
BANKSEL TXREG
movwf TXREG
BANKSEL PIR1
loopUSART8
btfss PIR1,TXIF
goto loopUSART8
;call delayPOW


lettura
BANKSEL SSPBUF
movf B'01000001',W ; chiedo status in lettura
movwf SSPBUF ; put in SSPBUF
BANKSEL SSPSTAT ; BANK 1
Char1 btfss SSPSTAT,BF ; Data transfer complete? (Buffer Full?)
goto Char1 ; if not, check again
BANKSEL TRISC
bsf TRISC,3
;leggere SSPBUF
BANKSEL SSPBUF ; BANK0
movf SSPBUF,W ; Get Data from SSPBUF
; ; Throw it away
;*******************************************
;bisogna ritardare il clock di almeno 100ns
BANKSEL TRISC ; BANK 1
movlw B'10111000' ; SCK is input (ritardo clock), Sd is input,
movwf TRISC ; SDO is input, all others output
;controllo se esco dal loop
movlw B'00110100'
BANKSEL TXREG
movwf TXREG
BANKSEL PIR1
loopUSART4 btfss PIR1,TXIF
goto loopUSART4
call delayMA
;controllo se esco dal loop
movlw B'00110011'
BANKSEL TXREG
movwf TXREG
BANKSEL PIR1
loopUSART5 btfss PIR1,TXIF
goto loopUSART5

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

;riabilita clock
BANKSEL TRISC ; BANK 1
movlw B'10110000' ; SDO is input (per lettura) , Sd is input,
movwf TRISC ;
;comincio a ricevere delta_X
BANKSEL SSPSTAT ; BANK 1
loop1 btfss SSPSTAT,BF ; Data transfer complete? (Buffer Full?)
goto loop1 ; if not, check again
;devo ritardare il clock tra un op. di
;read e l’altra
;controllo se esco dal loop
movlw B'00110101'
BANKSEL TXREG
movwf TXREG
BANKSEL PIR1
loopUSART6 btfss PIR1,TXIF
goto loopUSART6
;leggere SSPBUF
BANKSEL SSPBUF ; BANK0
movf SSPBUF,W ; Get Data from SSPBUF
BANKSEL deltaX
movwf deltaX ;salvo in deltaX
movlw D'48'
addwf deltaX,1
movf deltaX,w
BANKSEL TXREG
movwf TXREG
BANKSEL PIR1
loopUSART
btfss PIR1,TXIF
goto loopUSART
;********************************************
BANKSEL TRISC ; BANK 1
movlw B'10010000' ; SCK is output (Master), Sd is input,
movwf TRISC ; SDO is output, all others output
;********************************************

goto lettura ;ritorno al loop

delayMA
cblock
count
endc
movlw 0x6A
BANKSEL count
movwf count
delayloop
decfsz count,f
goto delayloop

return

delayPOW
cblock
d1
endc
movlw 0xFF
BANKSEL d1
movwf d1
; movlw 0x28
; BANKSEL d2
; movwf d2
; movlw 0x02
; BANKSEL d3
; movwf d3
delayloop1
decfsz d1,f
; goto $+2
; decfsz d2,f
goto delayloop1
; decfsz d3,f
; goto delayloop1

return


END

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Here is some code to initalise the SPI bus and then there is one routine for data send and receive. It is written in BoostC but should be fairly easy to convert to assembler.

void main ()
{
char responce;

FCD_SPI0_SPI_Init(); //Init SPI BUS
SPI(address); //Send Address

delayus(100); //Wait 100 microseconds

responce = SPI(0xff); //Send dummy char and receive responce
}


//*********************
//Initialise SPI Module
//*********************
void FCD_SPI0_SPI_Init()
{
clear_bit(trisc, 2); //CS
clear_bit(trisc, 3); //SCK Output bit3
set_bit (trisc, 4); //SDI Input bit4
clear_bit(trisc, 5); //SDO Output bit5

portc = 0x04;
sspstat = 0x00; // Input In the middle of the clock
sspcon = 0x12; // Passive High f/64(307.2kHz), Master
set_bit (sspcon, 5); // SPI Enable
}


//**************************
//Send Character through SPI
//**************************
char SPI(char d) // send character over SPI
{
sspbuf = d; // send character
while ((sspstat & 0x01) == 0); // wait until sent
return sspbuf; // and return the received character
}

Hope this helps :D

datch
Posts: 2
Joined: Mon Nov 06, 2006 3:31 pm
Contact:

Post by datch »

Hi,
we did not say to you that the sensor use only two pins for comunication, one for clock and one for data.
The PIC16f877a has two pins for data (one output and one input).
So we connected the two pins of the micro to the only one pin of the sensor (using the half-duplex mode).
In this way, we cannot use the previous program, because, during the receveing of the data, there were a conflict on the data line (the micro sends a dummy data and on the same line the sensor should send valid data).

If you (or someone else) can help us, we thanks him/her in advance.

Thank benj.

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Hm thats fairly odd that there is only one pin on the sensor. The problem might be that the sensor is sending back data but the fact that it is connected to the SDO output pin means that the microcontroller and the sensor are fighting as such for control of the line.

Are you sure that the sensor is SPI compatible. It seems that a bit banging method would have more success in this case. You could change the tris register to change the direction of flow from out to in without having to change the pins being used. The only complication would be effective use of the serial clock and shifting the data appropriatly on transmission and reception.

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Looking at the read-operation timing diagrams from the datasheet, there needs to be a minimum hold time of 100us between the sending of the address and the receiving of the data.

http://www.avagotech.com/assets/downloa ... do?id=1684

This could be where your code falls down. Though im still not sure about whether anything needs changing so the output of the SPI and the output of the sensor dont corrupt each other.

Post Reply