Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

need help for SPI and PIC18f~!

Status
Not open for further replies.

kusosan

New Member
Hi,

I have some problems in PIC18f programming..
my task is to use PIC18f and SPI to read temperature data from CS5463. So I initialized the I/O ports of PIC18f and the SPI. but the temp. reading turned out to be very weird.. 70+ Celsius, while room temp. is about 20+only. the main program is as follows. I'm not sure if the command should be wirtten as "SSPBUF=00100110"? Plz help.

//synchronize clock. connect the SCLK of CS5463 to RB1
LATBbits.LATB1 = 1;

//connect SDO RC7 to SDI of Cs5463
LATC = 0;
TRISC = 0;
PORTC = 0x00;


//initializing SPI operation
//SSPSTAT=11xxxxxx;
SSPSTATbits.SMP=1;
SSPSTATbits.CKE=1;

//SSPCON1=xx110000;
SSPCON1bits.SSPEN=1;
SSPCON1bits.CKP=1;
SSPCON1bits.SSPM3=0;
SSPCON1bits.SSPM2=0;
SSPCON1bits.SSPM1=0;
SSPCON1bits.SSPM0=0;

//control bits specified

//enabling I/O
//SDO must have TRISC<7> bit cleared
TRISCbits.TRISC7=0;

//SCK must have TRISB<1> bit cleared.
TRISBbits.TRISB1=0;

LATBbits.LATB1 = 1;
LATBbits.LATB0 = 1;
//send commands to read temp from CS5463
SSPBUF=00100110;

//delay so that the temp. value can be read
Delay10KTCYx(40);
 
I have some problems in PIC18f programming.
Which PIC?

I'm not sure if the command should be wirtten as "SSPBUF=00100110"? Plz help.
Are you using C18? In BoostC you would write that as
Code:
	sspbuf=0b00100110;
as the default radix is decimal. (In C18 you probably have to capitalize SSPBUF. BoostC wants lower case.) I'm guessing that your compiler thinks 00100110 is a decimal number, and is seriously confused by it. :p Since 100110 is too big to fit in a byte, it's probably truncating everything but 110, which would be $6e hex or 1101110 binary.
 
Last edited:
thx futz.
i'm using PIC18f2455 and the programming lang. used is C.
I have also tried SSPBUF=0b00100110
but seems like SSPBUF only shows 26h, which is the value of 00100110 binary. In this case, the command was not sent out?
 
i'm using PIC18f2455 and the programming lang. used is C.
I know you're using C. What I was asking is which compiler? They have differences, you know.
I have also tried SSPBUF=0b00100110
but seems like SSPBUF only shows 26h, which is the value of 00100110 binary. In this case, the command was not sent out?
You have to wait for sspstat.BF to be set, signalling that the transfer is complete. Might be slightly different on a 2455, but I doubt it. I'm looking at a 18F248 datasheet. I've done SPI on many different PICs and they're almost all the same. Here's a typical SPI byte transfer function (send only - as you can see I'm discarding junk):
Code:
void spi_byte(unsigned char one)
{
	unsigned char junk;
	sspbuf=one;
	while(!sspstat.BF);
	junk=sspbuf;
}
Unlike most SPI functions there's no SS control in this one, as the device I'm using doesn't need it. Add one if you need it.

Try bit-banging your SPI. It's almost easier than using the hardware SPI. Here's a quick 16-bit example. Easily modified to do 8-bit instead. This routine is also send-only:
Code:
#define clock	porta.1
#define cs	porta.0	
#define data	porta.7

void spiout(unsigned char msb,unsigned char lsb)
{
	unsigned char bits,temp;
	cs=0;
	for(bits=0;bits<8;bits++){
		temp=msb<<bits;
		data=temp.7;
		nop();nop();
		clock=1;nop();nop();clock=0;
	}
	for(bits=0;bits<8;bits++){
		temp=lsb<<bits;
		data=temp.7;
		nop();nop();
		clock=1;nop();nop();clock=0;
	}
	cs=1;
}
All the nop()'s are because that code is for a 16F628A and it was having what I assume were read-modify-write problems. Adding a few nop's cured it completely.
 
Last edited:
Another thing that can mess things up is if you have the clock polarity set wrong. Either you have to look up in the device's datasheet what it wants, or just try it both ways. One will work and one will be off by one bit, which usually means the device doesn't work right or at all.
 
I have tried to add in the SPI-byte transfer function, but it seems like the command can be sent, but nothing was received, even after changing the clock polarity. The jump and SSPBUF have a value of 80h... the code is as follows and I dun know what is wrong..

#include <p18f2458.h>
#include <stdio.h>
#include <delays.h>

#pragma config WDT = OFF,PWRT = ON

void spi_byte(unsigned char one)
{
unsigned char junk;
SSPBUF=one;
while(!SSPSTATbits.BF);
junk=SSPBUF;
}

unsigned char one = 0b00100110;

void main (void)
{
ADCON1 = 0x0F; //SET Ra AS DIGITAL I/0 PINS

LATA = 0;
TRISA = 0;
PORTA = 0x00;

// reset all resistors into default state. connect RA2 to reset pin of CS5463
LATAbits.LATA2 = 0;

//activate the serial port interface. connect RA1 to CS pin of CS5463
//re-initialize the SPI for CS5463, drive the CS pin high, then low
LATAbits.LATA1 = 1;
LATAbits.LATA1 = 0;

LATB = 0;
TRISB = 0b00000101;
PORTB = 0x00;
//LATB = 0x00;

//synchronize clock. connect the SCLK of CS5463 to RB1
LATBbits.LATB1 = 1;
//send commands to read temp from CS5463
//connect SDO RC7 to SDI of Cs5463
LATC = 0;
TRISC = 0;
PORTC = 0x00;

//initializing SPI operation
//SSPSTAT=11xxxxxx;
SSPSTATbits.SMP=1;
SSPSTATbits.CKE=1;

//SSPCON1=xx110000;
SSPCON1bits.SSPEN=1;
SSPCON1bits.CKP=1;
SSPCON1bits.SSPM3=0;
SSPCON1bits.SSPM2=0;
SSPCON1bits.SSPM1=0;
SSPCON1bits.SSPM0=0;

//control bits specified

//enabling I/O
//SDO must have TRISC<7> bit cleared
TRISCbits.TRISC7=0;

//SCK must have TRISB<1> bit cleared.
TRISBbits.TRISB1=0;



//SSPCON2=0;
LATBbits.LATB1 = 1;
LATBbits.LATB0 = 1;
SSPBUF=00100110;

//unsigned char one = 0b00100110;
spi_byte(one);

Delay10KTCYx(40);

//connect SDO of CS5463 to RB0 of PIC (SDI)


}
 
I have tried to add in the SPI-byte transfer function, but it seems like the command can be sent, but nothing was received, even after changing the clock polarity. The jump and SSPBUF have a value of 80h... the code is as follows and I dun know what is wrong..
You did hear me say that I was throwing away the received value in this function, didn't you? :p Guess not. :D I did mention it in the previous post.
Code:
void spi_byte(unsigned char one)
{
	unsigned char junk;
	SSPBUF=one;
	while(!SSPSTATbits.BF);
	junk=SSPBUF;
}
To keep and use it you'd have to change it to look something like this (untested):
Code:
unsigned char spi_byte(unsigned char one)
{
	unsigned char junk;
	SSPBUF=one;
	while(!SSPSTATbits.BF);
	junk=SSPBUF;
	return(junk);
}
and call it like this:
Code:
	x=spi_byte(byte-to-send);	//x is what is received from the SPI device
Guess I should look up your device's datasheet and see if I can give you clearer advice. I have to go to work now. I'll look later today.

EDIT: Oh ya! Though you're using the CODE tags, you're somehow managing to kill all your formatting (indentation) before pasting your code. Just use CTRL-A to select all your source in your code editing window. Then hit CTRL-C to copy. Put your cursor between the [code] and [/code] tags here on the forum editor and hit CTRL-V to paste. That should cure the problem.

The way you're doing it now leaves your code unreadable. I find it hard to follow when there's no indentation, so I have to put it in an editor and reformat it properly every time. Annoying.

On the other hand, if your original source code actually looks like that, you need to study some properly written C and learn some proper formatting style. Proper indentation makes source code readable and prevents errors.
 
Last edited:
Hi Folks,
I am hoping someone could help me with regards to issue i am having with programming my PIC18F45K20 device via MPLAB C and the output. I am quite the newbie when it comes to programming a PIC etc so any help is greatly appreciated. Basically i am looking to send a series of bytes to a device through SPI configuration. It appears that my code is working except i do not have a continuous oscilation on my SCK line, it appears the line is idle high and then just pulses for 8 bits. Could someone tell me how i could generate a continuous clock cycle? For this SPI set-up, my slave device does not send any acknowledgement etc back thus i just require simple transmission of various bytes of data via SPI.
Any help is greatly appreciated, please see code
Regards,
Chris.

#pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF // CONFIG1H
#pragma config PWRT = OFF, BOREN = OFF, BORV = 30 // CONFIG2L
#pragma config WDTEN = OFF, WDTPS = 32768 // CONFIG2H
#pragma config MCLRE = ON, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC // CONFIG3H
#pragma config STVREN = ON, LVP = OFF, XINST = OFF // CONFIG4L
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF // CONFIG5L
#pragma config CPB = OFF, CPD = OFF // CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF // CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF // CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF // CONFIG7L
#pragma config EBTRB = OFF // CONFIG7H

#include <p18f45k20.h>
#include <delays.h>
#define SS PORTAbits.RA5


void init_pic(void);
void init_spi(void);

void main(void)
{
init_pic();
init_spi();
while(1)
{
Delay1KTCYx(2000);
Delay1KTCYx(2000);
SSPBUF=0x20; // sends byte to buffer
Delay1KTCYx(2000);
Delay1KTCYx(2000);
SSPBUF=0x21;
Delay1KTCYx(2000);
Delay1KTCYx(2000);
SSPBUF=0x22;
Delay1KTCYx(2000);
Delay1KTCYx(2000);
SSPBUF=0x23;
Delay1KTCYx(2000);
Delay1KTCYx(2000);
SSPBUF=0x24;
Delay1KTCYx(2000);
Delay1KTCYx(2000);
SSPBUF=0x25;
Delay1KTCYx(2000);
Delay1KTCYx(2000);
SSPBUF=0x26;
}
}


void init_pic(void)
{
TRISA=0b00000000;
TRISB=0b00000000;
TRISC=0b00010000;
ADCON1=0xFF; // Turns off A/D
}
void init_spi(void)
{
SSPSTAT=0b01000000; // Sets CKE bit to 1. This will set SPI mode to 1:1 with CKP pin in SSPCON1
SSPCON1=0b00110000; // Sets SSPEN pin to 1 and CKE pin to 1
}
 
Dude, you dont have to try bit banging, the SSPBUF is a cool thing in PIC18F series... I think the point that you forgot is setting all the pins to digital. Set ADCON1=0x0F and the problem will be solved.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top