|
|
View previous topic :: View next topic |
Author |
Message |
J Hopkins Guest
|
Switching from hardware spi to software spi |
Posted: Sun May 10, 2009 2:28 pm |
|
|
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
|
|
Posted: Sun May 10, 2009 2:33 pm |
|
|
I strongly question whether #use spi() works in vs. 4.016. |
|
|
J Hopkins Guest
|
I didn't know that |
Posted: Sun May 10, 2009 2:36 pm |
|
|
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
|
|
Posted: Sun May 10, 2009 2:49 pm |
|
|
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 |
|
|
|
|
|
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
|