CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Switching from hardware spi to software spi

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
J Hopkins
Guest







Switching from hardware spi to software spi
PostPosted: Sun May 10, 2009 2:28 pm     Reply with quote

I am using a pic18f4520 to control an fm25v10 f-ram. I am using compiler v 4.016.

I initially used a hardware spi interface to control the fram, which was simple and straight forward. However, we layed out a board with some traces in the wrong places, so I now need to use a software interface so that I can select which pins are which. I tried to develop a software interface but so far I can't seem to get it to work. I am testing both interfaces with the same setup. One thing I am wonder is, is it a problem to declare a software interface on the same pins that a hardware interface would go on?

For the test I try to write/read both a single character and a string of characters from the fram. In either case with software I get back characters that are all 1's. I know that software spi is slower than hardware, so there is no way I am outrunning the fram. The minimum setup and hold times are not even close to being violated. I don't have a scope with me so I cannot look at what the pic is sending.

This is a serious problem, as we are in a rush to ship our otherwise-working product. I would really appreciate any help anyone could offer. Thanks.

Working hardware interface:

Code:
#include <18F4520.h>
#device PASS_STRINGS = IN_RAM
#device HIGH_INTS=TRUE
#include <stdio.h>
#include <string.h>

#use delay(INTERNAL=8M, clock=16M)
#fuses INTRC//, DEBUG

//Spi Modes (F-Ram only uses 0 or 3
#define SPI_MODE_0  (SPI_XMIT_L_TO_H | SPI_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_XMIT_L_TO_H | SPI_H_TO_L)

//F-RAM Commands
#define WREN 0x06
#define WRDI 0x04
#define RDSR 0x05
#define WRSR 0x01
#define READ 0x03
#define FSTRD 0x0B
#define WRITE 0x02
#define SLEEP 0xB9
#define RDID 0x9F
#define SNR 0xC3

#define NO_WR_PROTECT 0x00


struct portb_pin_map {
   unsigned short led0;      
   unsigned short led1;      
   unsigned short led2;      
   unsigned short led3;         
   unsigned short pic_mode;   
   unsigned short CTS;         
   unsigned short reserved;   
   unsigned short bit7;   
      } portb;

#locate portb = getenv("sfr:PORTB")

struct portc_pin_map {
   unsigned short b0;         
   unsigned short HOLD;      
   unsigned short SS;         // SPI SS   -- Place holder.
   unsigned short SCK;         // SPI SCK   -- Place holder.
   unsigned short SDI;         // SPI SDI   -- Place holder.
   unsigned short SDO;         // SPI SDO   -- Place holder.
   unsigned short TX;         // RS232 TX   -- Place holder.
   unsigned short RX;         // RS232 RX   -- Place holder.
      } portc;

#locate portc = getenv("sfr:PORTC")

#use rs232(BAUD=9600, XMIT=PIN_A1, RCV=PIN_A0, BITS=8, PARITY=N)

void leds(int a) {
   portb.led0=a&1;
   portb.led1=(a>>1)&1;
   portb.led2=(a>>2)&1;
   portb.led3=(a>>3)&1;
}

void tx(char *tx) {
   int a=0;
   while(tx[a])
      putc(tx[a++]);
   putc(13);
   putc(10);
}

void spi_wr_enable() {
   portc.SS=0;
   spi_write(WREN);
   portc.SS=1;
}

void setup_fram() {
   spi_wr_enable();
 
   //write to status register
   portc.SS=0;
   spi_write(WRSR);
   spi_write(0b01000000);
   portc.SS=1;
}

void fram_write(int32 adr, char data) {
   spi_wr_enable();
   
   //write data
   portc.SS=0;
   spi_write(WRITE);
   spi_write((adr>>16)&1);
   spi_write((adr>>8)&0xFF);
   spi_write(adr&0xFF);
   spi_write(data);
   portc.SS=1;
}

void fram_read(int32 adr, char *out, int16 num) {
   int16 i=0;

   //read data
   portc.SS=0;
   spi_write(READ);
   spi_write((adr>>16)&1);
   spi_write((adr>>8)&0xFF);
   spi_write(adr&0xFF);
   while(num--)
      out[i++]=spi_read(0);
   out[i]=NULL;
   portc.SS=1;
}

void main(void) {
   int i=0;
   char message[40]="This is just a simple test.";
   char result[40];
   int32 adr=0;

   setup_oscillator(OSC_16MHZ);
   delay_ms(1000);

   disable_interrupts(global);
   set_tris_b(0xF0);
   set_tris_c(0xA0);
   portc.SS=1;
   portc.HOLD=1;
   setup_spi (SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4 );
   delay_ms(500);

   setup_fram();

   do {
      fram_write(adr++,message[i]);
   }
   while(message[i++]);
   tx(message);
      
   adr=0;
   fram_read(adr,result,40);
   tx(result);
   tx("\r\n");
   
}


Not working software interface:

#include <18F4520.h>
#device PASS_STRINGS = IN_RAM
#device HIGH_INTS=TRUE
#include <stdio.h>
#include <string.h>

#use delay(INTERNAL=8M, clock=16M)
#fuses INTRC//, DEBUG

//Spi Modes (F-Ram only uses 0 or 3
#define SPI_MODE_0  (SPI_XMIT_L_TO_H | SPI_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_XMIT_L_TO_H | SPI_H_TO_L)

//F-RAM Commands
#define WREN 0x06
#define WRDI 0x04
#define RDSR 0x05
#define WRSR 0x01
#define READ 0x03
#define FSTRD 0x0B
#define WRITE 0x02
#define SLEEP 0xB9
#define RDID 0x9F
#define SNR 0xC3

#define NO_WR_PROTECT 0x00


struct portb_pin_map {
   unsigned short led0;      
   unsigned short led1;      
   unsigned short led2;      
   unsigned short led3;         
   unsigned short pic_mode;   
   unsigned short CTS;         
   unsigned short reserved;   
   unsigned short bit7;   
      } portb;

#locate portb = getenv("sfr:PORTB")

struct portc_pin_map {
   unsigned short b0;         
   unsigned short HOLD;      
   unsigned short SS;         // SPI SS   -- Place holder.
   unsigned short SCK;         // SPI SCK   -- Place holder.
   unsigned short SDO;         // SPI SDO   -- Place holder.
   unsigned short SDI;         // SPI SDI   -- Place holder.
   unsigned short TX;         // RS232 TX   -- Place holder.
   unsigned short RX;         // RS232 RX   -- Place holder.
      } portc;

#locate portc = getenv("sfr:PORTC")

#use rs232(BAUD=9600, XMIT=PIN_A1, RCV=PIN_A0, BITS=8, PARITY=N)

#use spi(MASTER, MSB_FIRST, DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, BITS=8, MODE=0)

void leds(int a) {
   portb.led0=a&1;
   portb.led1=(a>>1)&1;
   portb.led2=(a>>2)&1;
   portb.led3=(a>>3)&1;
}

void tx(char *tx) {
   int a=0;
   while(tx[a])
      putc(tx[a++]);
   putc(13);
   putc(10);
}

void spi_wr_enable() {
   portc.SS=0;
   spi_xfer(WREN);
   portc.SS=1;
}

void setup_fram() {
   spi_wr_enable();
 
   //write to status register
   portc.SS=0;
   spi_xfer(WRSR);
   spi_xfer(0b01000000);
   portc.SS=1;
}

void fram_write(int32 adr, char data) {
   spi_wr_enable();
   
   //write data
   portc.SS=0;
   spi_xfer(WRITE);
   spi_xfer((adr>>16)&1);
   spi_xfer((adr>>8)&0xFF);
   spi_xfer(adr&0xFF);
   spi_xfer(data);
   portc.SS=1;
}

void fram_read(int32 adr, char *out, int16 num) {
   int16 i=0;

   //read data
   portc.SS=0;
   spi_xfer(READ);
   spi_xfer((adr>>16)&1);
   spi_xfer((adr>>8)&0xFF);
   spi_xfer(adr&0xFF);
   while(num--)
      out[i++]=spi_xfer();
   out[i]=NULL;
   portc.SS=1;
}

void main(void) {
   int i=0;
   char message[40]="This is just a simple test.";
   char result[40];
   int32 adr=0;

   setup_oscillator(OSC_16MHZ);
   delay_ms(1000);

   disable_interrupts(global);
   set_tris_b(0xF0);
   set_tris_c(0xA0);
   portc.SS=1;
   portc.HOLD=1;
//   setup_spi (SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4 );
   delay_ms(500);

   setup_fram();

   do {
      fram_write(adr++,message[i]);
   }
   while(message[i++]);
   tx(message);
      
   adr=0;
   fram_read(adr,result,40);
   tx(result);
   tx("\r\n");
   
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 10, 2009 2:33 pm     Reply with quote

I strongly question whether #use spi() works in vs. 4.016.
J Hopkins
Guest







I didn't know that
PostPosted: Sun May 10, 2009 2:36 pm     Reply with quote

PCM programmer wrote:
I strongly question whether #use spi() works in vs. 4.016.


Thanks for responding. Are you saying I need to write my own software spi interface? Has someone already written one? I'm not an assembly expert. My background is C/C++.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 10, 2009 2:49 pm     Reply with quote

Don't write it in assembly. Write it in C. Look at some of the CCS
example files for the 25-series eeproms:
Quote:
c:\program files\picc\drivers\25640.c
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group