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.

Problem with sample SPI transmission

Status
Not open for further replies.

kyru27

New Member
According to what I have seen about SPI, I think the following code should work fine (Writing a 0x0E and later reading it:

Code:
#include "p18F4620.h"
#include "spi.h"



#pragma config XINST=OFF
#pragma config OSC=INTIO67


#pragma code



void main (void)
{
	char rxdata;

    //SS' is on RA0
    TRISA = 0b00000001; 
    TRISC = 0b00010000; 
    TRISE = 0b00000000;

    SSPCON1bits.SSPEN = 1;   
    SSPCON1bits.CKP = 0;

    SSPSTATbits.SMP = 1; /* Data Input Sample Bit: Cleared in SPI slave mode */
    SSPSTATbits.CKE = 0; /* Clock Edge Select Bit: (1)transmit occurs on transition active->idle */

  	SSPCON1bits.SSPM3=0;
	SSPCON1bits.SSPM2=0;
	SSPCON1bits.SSPM1=0;
	SSPCON1bits.SSPM0=0;
	
	WriteSPI("0x0E");   

	while (!SSPSTATbits.BF);

	rxdata=ReadSPI();

}

But instead, rxdata is all the time 0x00 (which, in fact, if the write never occurs, it's what should be as it's an EEPROM full of 0's), the write really seems not to happen as if I read the EEPROM there doesn't seem to be 0x0E anywhere.

I know it's not too useful to write on an EEPROM memory position (which I think this code should be doing), but right now, I just want to check SPI functionallity before getting into more difficult things.

Maybe as it's an EEPROM it requires some type of special treatment other SPI devices don't need, but as from what I read seems not to, I'm posting this here.

Thanks.
 
Eeprom's need a sequence of events

For example: you need to write A instruction , B address , C value....To Read... write A instruction , B address , read C value..

This is for a 25lc1024 from microchip.
 
Last edited:
I still have a problem into writing the EEPROM memory:

I have written the following code, based, well almost equal to the one shown in here (https://www.electro-tech-online.com/threads/help-with-spi-eeprom.36542/#post286346) and taking into consideration other things written on that post:

Code:
#include <p18F4620.h>
#include <delays.h>
#include <spi.h>
#include <usart.h>
#include <stdio.h>
 
#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config LVP = OFF
#pragma config XINST=OFF
#pragma config OSC=INTIO67

#define CLOCK_FREQ		(40000000ul)      // Hz 
 
#define CSEE PORTCbits.RC0 // select line for Serial EEPROM
 
#define SEE_WRSR 	1 // write status register
#define SEE_WRITE 	2 // write command
#define SEE_READ 	3 // read command
#define SEE_WRDI 	4 // write disable
#define SEE_STAT 	5 // read status register
#define SEE_WREN 	6 // write enable
 
 
void SPIEEPROMInit();
void UARTInit();
 
void writeSPI()
{
	CSEE = 0;
	SSPBUF = SEE_WREN; 			// write to buffer for TX
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	CSEE = 1;					// brought high to set write enable latch
	Delay1TCY();				// 100ns delay. minimum delay is 50ns.
 
	CSEE = 0;
	SSPBUF = SEE_WRITE;

	while( !SSPSTATbits.BF );	// wait for transfer to complete
	SSPBUF = 0b00000000;		// First address byte
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	SSPBUF = 0b00000010;		// Second address byte
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	SSPBUF = 0b10101010;		// Write data
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	CSEE = 1;					// To start writing
	Delay10KTCYx(5);			// Internal write cycle time of 5ms
 
	CSEE = 0;
	SSPBUF = SEE_WRDI;
	while( !SSPSTATbits.BF );	// wait for transfer to complete
	CSEE = 1;
}//writeSPI
 
int readSPI()
{
	CSEE = 0;
	SSPBUF = SEE_READ;
	while( !SSPSTATbits.BF );	// wait for transfer to complete
	SSPBUF = 0b00000000;		// First address byte
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	SSPBUF = 0b00000010;		// Second address byte
	while( !SSPSTATbits.BF ); 	// wait for data received
	Delay1TCY();
	SSPBUF = 0b00000000;		// Send dummy byte
	while( !SSPSTATbits.BF ); 	// wait for data received
	SSPBUF=getcSPI();
	CSEE = 1;					// Stop receiving
	return SSPBUF;
}//readSPI
 
void main()
{
int data1, data2, i;	
	SPIEEPROMInit();	
TRISCbits.TRISC0 = 0;
 
 
 
 
while (1)
{
	writeSPI();

i=1000;

	while (i>0)
	{
//	Delay10KTCYx(100);			//Delay 1ms
	i=i-1;
	}		

	data1 = readSPI();
	Delay10KTCYx(200);			//Delay 1ms
}
}
 
void SPIEEPROMInit()
{
	SSPSTAT = 0xC0; //SPI Bus mode 0,0
	SSPCON1 = 0x21; //Enable SSP,Fosc/16
 
	DDRCbits.RC7 = 0; //Define CS as Output
	DDRCbits.RC3 = 0; //Define SCK as Output
	DDRCbits.RC4 = 1; //Define SDI as Input
	DDRCbits.RC5 = 0; //Define SDO as Output
	CSEE = 1; // 
}

But I do still have problems with these code:

1) The SPI bus is being written but, I get a 00FF instead of 00AA as it should when readSPI is executed.

2) The Delay10KTCYx(100); seems to enter an infinite loop randomly, to prevent that I wrote

Code:
	while (i>0)
	{
//	Delay10KTCYx(100);			//Delay 1ms
	i=i-1;
	}

But, although it might be causing the same effect as the Delay10KTCYx, I still get 00FF, but the point is that maybe it might not be causing the same effect, so if that is the point I'd like to know how could I correct that.

Thanks.
 
Have you checked with Oscope that the SPI signals are there and as expected?

Not sure what this ( SSPBUF=getcSPI();) is meant for? But since you are pretty much doing the Writes and Reads yourself you can remove it. The SSPBUF will already have the received data immediately after the last bit of (dummy) data is transmitted (i.e. as each bit is transferred out of the transmit buffer, the receive buffer is updated).

Can't help with the Delay10KTCYx; that is a built-in command to (which C compiler)?
 
Do not have an Oscope, and I don't think I'll buy one as it's likely I'd just need it for this, so it wouldn't be worth the cost.

The getcSPI() was just a try based on the thread I mention on my first message. I didn't find it useful either but just in case it worked...

That's from C18 compiler, anyway the wrong part is the frequency that's on 40 Mhz where it should be 8 Mhz.

Think the problems have to be similar to the ones I found on the thread (https://www.electro-tech-online.com/threads/problem-with-i2c-eeprom.127962/), I'll give it a check based on those.
 
Well I finally got it, frequency was wrong and read routine was also wrong, default delay functions of C18 seem to keep on giving problems, but I can work around this with other delay routines:

This code goes right:

Code:
#include <p18F4620.h>
#include <delays.h>
#include <spi.h>
#include <usart.h>
#include <stdio.h>

void delayUs( int x );
void delayMs( int x);
 
#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config LVP = OFF
#pragma config XINST=OFF
#pragma config OSC=INTIO67

#define CLOCK_FREQ		(8000000ul)      // Hz 
 
#define CSEE PORTCbits.RC0 // select line for Serial EEPROM

#define SEE_WRSR 	1 // write status register
#define SEE_WRITE 	2 // write command
#define SEE_READ 	3 // read command
#define SEE_WRDI 	4 // write disable
#define SEE_STAT 	5 // read status register
#define SEE_WREN 	6 // write enable
 
 
void SPIEEPROMInit();
void UARTInit();

 void writeSPI()
{
	CSEE = 0;
	SSPBUF = SEE_WREN; 			// write to buffer for TX
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	CSEE = 1;					// brought high to set write enable latch
	Delay1TCY();				// 100ns delay. minimum delay is 50ns.
 
	CSEE = 0;
	SSPBUF = SEE_WRITE;
 
	while( !SSPSTATbits.BF );	// wait for transfer to complete
	SSPBUF = 0b00000000;		// First address byte
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	SSPBUF = 0b00000010;		// Second address byte
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	SSPBUF = 0b10101010;		// Write data
	while( !SSPSTATbits.BF ); 	// wait for transfer to complete
	CSEE = 1;					// To start writing
	Delay10KTCYx(5);			// Internal write cycle time of 5ms
 
	CSEE = 0;
	SSPBUF = SEE_WRDI;
	while( !SSPSTATbits.BF );	// wait for transfer to complete
	CSEE = 1;
}//writeSPI
 
int readSPI()
{
	int var;
	CSEE = 0;                           
  WriteSPI(0x03);    // WriteSPI is defined in "spi.h"
  WriteSPI(0b00000000);
  WriteSPI(0b00000010); 
  var = getcSPI();   // getcSPI is defined in "spi.h"
  CSEE = 1;          
  return var;     
}//readSPI
 
void main()
{
int data1, data2, i;	
	SPIEEPROMInit();	
TRISCbits.TRISC0 = 0;
 
 
 
 
while (1)
{
	writeSPI();
 
i=1000;
 
	
	
	delayUs(500);			//Delay 1ms
			
 
	data1 = readSPI();
	delayUs(500);			//Delay 1ms
}
}
 
void SPIEEPROMInit()
{
	SSPSTAT = 0xC0; //SPI Bus mode 0,0
	SSPCON1 = 0x21; //Enable SSP,Fosc/16
 
	DDRCbits.RC7 = 0; //Define CS as Output
	DDRCbits.RC3 = 0; //Define SCK as Output
	DDRCbits.RC4 = 1; //Define SDI as Input
	DDRCbits.RC5 = 0; //Define SDO as Output
	CSEE = 1; // 
}

void delayUs( int x )
   {
   while(x--)
      {
      Nop(); /// add these to get 1uS
      }
   }
 
void delayMs( int x)
   {
   while(x--)
	{
      delayUs(1000);
   }
	}

Thanks everyone for your help.
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top