|
|
View previous topic :: View next topic |
Author |
Message |
Tom-H-PIC
Joined: 08 Sep 2003 Posts: 105 Location: New Castle, DE
|
Hardware SPI on the 18F252 and 18LF2620 |
Posted: Mon Nov 22, 2004 9:49 am |
|
|
CCS complier Ver 3.212
Hardware 18F252 and Atmel AT25256A
I have three hardware boards all setup identically, 18F252, 18LF2620 and 18LF4620.
All hardware use 10mhz crystals with a fuse setting of HS+PLL.
To start out with I have modified the CCS bit bang SPI driver (AT25256.c).
This bit banging works with all of the hardware.
What I would like to do is use the SPI hardware on the PIC.
I'm concentrating on the 18F252 hardware at this time. I will move the code to the 18LF4620 hardware if we can get it working.
I have used a lot of SPI hardware and the software using the hardware SPI on the 16F8xx.
This is basically the identical hardware and software that I have used on the 16F877.
I have tried ever thing that I can think of.
Would you guys look at this test code and see if I'm missing any thing.
Thanks all in advance for any help that you give.
Tom
Modification for the 18F252 header file.
Code: |
/*
Added SPI Mode Setup by Tom Hauff Mar. 09, 2003
CKP = 0, CKE = 0 SIP Mode 0,1
setup_spi (SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_64 );
CKP = 0, CKE = 1 SIP Mode 0,0
setup_spi (SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_64 );
CKP = 1, CKE = 0 SIP Mode 1,1
setup_spi (SPI_MASTER | SPI_H_TO_L | SPI_XMIT_L_TO_H | SPI_CLK_DIV_64 );
CKP = 1, CKE = 1 SIP Mode 1,0
setup_spi (SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64 );
*/
#define SPI_MODE_0_0 0x4000
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0010
#define SPI_MODE_1_1 0x4010
|
Include File Hardware SPI AT25256CAPI.c
Code: |
#bit EX_FROM_CS = 0xF8B.2 //O/P Chip Select
#bit EX_FROM_CLK = 0xF8B.3 //O/P Clock output
#bit EX_FROM_DO = 0xF8B.4 //I/P Data out of EX_EEPROM data in to MCU
#bit EX_FROM_DI = 0xF8B.5 //O/P Data out of MCU data in to EX_EEPROM
/*
#ifndef EEPROM_SELECT
#define EEPROM_SELECT PIN_C2
#define EEPROM_DI PIN_C5
#define EEPROM_DO PIN_C4
#define EEPROM_CLK PIN_C3
#endif
*/
#ifndef EEPROM_ADDRESS
#define EEPROM_ADDRESS long
#endif
void init_ext_eeprom() {
short int i;
/*
output_low(EEPROM_DI);
output_low(EEPROM_CLK);
output_high(EEPROM_SELECT); //at25256 is cs active LOW
i=input(EEPROM_DO);
*/
EX_FROM_DI = 0;
EX_FROM_CLK = 0;
EX_FROM_CS = 1;
i = EX_FROM_DO;
//Setup PIC for SPI Mode for the AT25256A
// setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_64 );
// setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16 );
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_4 );
}
BOOLEAN ext_eeprom_ready() {
int data;
EX_FROM_CS = 0; //Chip Select pin low
delay_cycles(3);
// spi_write(0x05);
data = spi_read(0x05); //Opcode to Read Status Register (RDSR)
EX_FROM_CS = 1; //Chip Select pin high
return (!(bit_test(data, 0)));
}
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) {
/*
int i,cmd[4];
cmd[0]=0x02; //write opcode
cmd[1]=((address>>8)&(0xFF)); //address msb (16bit addressing)
cmd[2]=address-cmd[2]; //address lsb
cmd[3]=data;
*/
do {} while (!(ext_eeprom_ready())); //wait until the eeprom is out of the previous write state, if applicable
EX_FROM_CS = 0; //Chip Select pin low
delay_cycles(3);
spi_write(0x06); //Opcode for enable writing to EEPROM
// EX_FROM_CS = 1; //Chip Select pin high
// delay_cycles(3);
// EX_FROM_CS = 0; //Chip Select pin low
// delay_cycles(3);
spi_write(0x02);
spi_write(make8(address,1));
spi_write(make8(address,0));
spi_write(data);
/*
for(i=0;i<=3;++i) {
spi_write(cmd[i]);
}
*/
EX_FROM_CS = 1; //Chip Select pin high
}
BYTE read_ext_eeprom(EEPROM_ADDRESS address) {
int i,data;
/*
int cmd[3];
cmd[0]=0x03; //read opcode
cmd[1]=((address>>8)&(0xFF));
cmd[2]=address-cmd[1];
*/
do {} while (!(ext_eeprom_ready())); //wait until the eeprom is out of the previous write state, if applicable
EX_FROM_CS = 0; //Chip Select pin low
delay_cycles(3);
spi_write(0x03);
spi_write(make8(address,1));
data = spi_read(make8(address,0)); //Read Data
EX_FROM_CS = 1; //Chip Select pin high
return(data);
}
|
Main Test code
Code: |
/////////////////////////////////////////////////////////////
//Name: F252SPIT.c Rev - /
//Last rev: 2004/11/22 /
/////////////////////////////////////////////////////////////
//(C) Copyright 2004 /
//Delta Engineering Writen by Thomas W. Hauff /
/////////////////////////////////////////////////////////////
#include <18F252SPI.h>
#opt 11
#fuses H4,NOOSCSEN,NOBROWNOUT,NOWDT,NOPROTECT,NOLVP //PIC18F252 ,NOCPD,NOWRTD
#use delay(clock=40000000)
#include <AT25256CSPI.c>
//#device ICD=TRUE
//------------------------------------------------------------------------------
// Setup hardware serial port
#USE RS232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, parity=n, bits=8, errors, stream=HU1)
//------------------------------------------------------------------------------
#USE FAST_IO(A)
#USE FAST_IO(B)
#USE FAST_IO(C)
//------------------------------------------------------------------------------
//Constants
#define hart_ints_ms 495 //The number of times that the 1ms timer interrupts for 500ms heartbeat
//------------------------------------------------------------------------------
//Define input output Pins and Register assignments
#byte porta = 0xF80
#byte portb = 0xF81
#byte portc = 0xF82
#bit Hart = 0xF80.0 //hart bet, On port A bit 0
//#bit Test = 0xF80.1 //Test if we are getting 1mS
//------------------------------------------------------------------------------
// Variables
int1 one_ms, W_EX_EEPROM,R_EX_EEPROM;
int Loop_count = 0, EEPROM_timer = 8, data;
int16 Hart_Timer = hart_ints_ms, EE_Address;
//------------------------------------------------------------------------------
// Timer 3 interrupts handler
#INT_TIMER3
void timer3_isr(void){
one_ms = True;
set_timer3(55586); } //set timer 3 to interrupt for 1ms
//------------------------------------------------------------------------------
void main() {
//Setup digital input output ports
set_tris_a(0b00000000); // Port A set 1 = input; 0 = output
set_tris_b(0b10011111); // Port B set 1 = input; 0 = output
set_tris_c(0b10010011); // Port C set 1 = input; 0 = output
port_b_pullups(True); //Port B Set Pullups 1 = Pullup on
//Setup Ext EEPROM
init_ext_eeprom();
W_EX_EEPROM = True;
EE_Address = 0;
//Set timer 3 for 1mS
setup_timer_3(T3_INTERNAL|T3_DIV_BY_1); // Setup timer 3 for 1ms
set_timer3(55586); //set timer 3 for 1ms
//ADC Setup
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
// Lets enable the interrupts!
//disable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER3);
enable_interrupts(GLOBAL);
fprintf(HU1,"RS232 Port Alive Address = %lu data = %u \n\r",EE_Address,data);
//{{{{{{{{{{{{{{{{{{{{{{{{{{ Start of Main }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
while (TRUE) { // Endless main loop
//------------------------------------------------------------------------------
//Start of 1Ms timer
if (one_ms){
one_ms = False;
/* if (Test == True) { //Test pulse at a pin of 1 mS
Test = 0; }
else {
Test = 1; } */
//------------------------------------------------------------------------------
//500mS timer for heartbeat LED and EEPROM read out
if (--Hart_Timer == 0){
Hart_Timer = hart_ints_ms; //Reset hart timer
if (Hart == True) { //Test if Heartbeat LED is on
Hart = 0; } //Turns off HeartBeat LED
else { //Heartbeat LED is off
Hart = 1; } //Turns on HeartBeat LED
if (W_EX_EEPROM){ //Blue Radio 500ms flag trap
if (--EEPROM_timer == 0){ //Blue Radio timer
data = ++Loop_count;
write_ext_eeprom(EE_Address++,data); //put data in eeprom
fprintf(HU1,"Write Address = %lu data = %u \n\r",EE_Address,data);
W_EX_EEPROM = False;
R_EX_EEPROM = True;
EEPROM_timer = 8;}}
if (R_EX_EEPROM){ //slave is not responding to the connect request
if (--EEPROM_timer == 0){ //Blue Radio timer
data = 0;
data = read_ext_eeprom(EE_Address); //get data from eeprom
fprintf(HU1,"Read Address = %lu data = %u \n\r",EE_Address,data);
R_EX_EEPROM = False;
W_EX_EEPROM = True;
EEPROM_timer = 8;}}
}
} //END of 1mS loop
} //while (TRUE); for Main
} //------ End of Main---------------------------------------
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Nov 22, 2004 11:22 am |
|
|
The spi_read() function writes and reads data simultaneously using the same 8 clock pulses. This means that everywhere where you have used the spi_read() function you have 8 missing clock pulses.
replace Code: | data = spi_read(0x05); //Opcode to Read Status Register (RDSR) | with Code: | spi_write(0x05); //Opcode to Read Status Register (RDSR)
data = spi_read(0x00);
|
and replace Code: | spi_write(0x03);
spi_write(make8(address,1));
data = spi_read(make8(address,0)); //Read Data | with Code: | spi_write(0x03);
spi_write(make8(address,1));
spi_write(make8(address,0));
data = spi_read(0x00); //Read Data |
|
|
|
Tom-H-PIC
Joined: 08 Sep 2003 Posts: 105 Location: New Castle, DE
|
Made the changes that you suggested No Help |
Posted: Mon Nov 22, 2004 1:17 pm |
|
|
The change that you suggested is the way that I had the code when I first started down this road.
At that time I had no luck at getting it to work so I changed the code to the way that I first posted.
I have made the changes you have suggested and retested with no help.
I don�t understand why this will not work!
I think that the entire configuration is correct. I would think that would work with out a problem but I can not get it to work.
Below is the include file with changes
Code: |
#bit EX_FROM_CS = 0xF8B.2 //O/P Chip Select
#bit EX_FROM_CLK = 0xF8B.3 //O/P Clock output
#bit EX_FROM_DO = 0xF8B.4 //I/P Data out of EX_EEPROM data in to MCU
#bit EX_FROM_DI = 0xF8B.5 //O/P Data out of MCU data in to EX_EEPROM
/*
#ifndef EEPROM_SELECT
#define EEPROM_SELECT PIN_C2
#define EEPROM_DI PIN_C5
#define EEPROM_DO PIN_C4
#define EEPROM_CLK PIN_C3
#endif
*/
#ifndef EEPROM_ADDRESS
#define EEPROM_ADDRESS long
#endif
void init_ext_eeprom() {
short int i;
/*
output_low(EEPROM_DI);
output_low(EEPROM_CLK);
output_high(EEPROM_SELECT); //at25256 is cs active LOW
i=input(EEPROM_DO);
*/
EX_FROM_DI = 0;
EX_FROM_CLK = 0;
EX_FROM_CS = 1;
i = EX_FROM_DO;
//Setup PIC for SPI Mode for the AT25256A
// setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_64 );
// setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16 );
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_4 );
}
BOOLEAN ext_eeprom_ready() {
int data;
EX_FROM_CS = 0; //Chip Select pin low
delay_cycles(3);
spi_write(0x05);
data = spi_read(0x00); //Opcode to Read Status Register (RDSR)
EX_FROM_CS = 1; //Chip Select pin high
return (!(bit_test(data, 0)));
}
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) {
/*
int i,cmd[4];
cmd[0]=0x02; //write opcode
cmd[1]=((address>>8)&(0xFF)); //address msb (16bit addressing)
cmd[2]=address-cmd[2]; //address lsb
cmd[3]=data;
*/
do {} while (!(ext_eeprom_ready())); //wait until the eeprom is out of the previous write state, if applicable
EX_FROM_CS = 0; //Chip Select pin low
delay_cycles(3);
spi_write(0x06); //Opcode for enable writing to EEPROM
// EX_FROM_CS = 1; //Chip Select pin high
// delay_cycles(3);
// EX_FROM_CS = 0; //Chip Select pin low
delay_cycles(3);
spi_write(0x02);
spi_write(make8(address,1));
spi_write(make8(address,0));
spi_write(data);
/*
for(i=0;i<=3;++i) {
spi_write(cmd[i]);
}
*/
EX_FROM_CS = 1; //Chip Select pin high
}
BYTE read_ext_eeprom(EEPROM_ADDRESS address) {
int i,data;
/*
int cmd[3];
cmd[0]=0x03; //read opcode
cmd[1]=((address>>8)&(0xFF));
cmd[2]=address-cmd[1];
*/
do {} while (!(ext_eeprom_ready())); //wait until the eeprom is out of the previous write state, if applicable
EX_FROM_CS = 0; //Chip Select pin low
delay_cycles(3);
spi_write(0x03);
spi_write(make8(address,1));
spi_write(make8(address,0));
data = spi_read(0x00); //Read Data
EX_FROM_CS = 1; //Chip Select pin high
return(data);
}
|
|
|
|
Tom-H-PIC
Joined: 08 Sep 2003 Posts: 105 Location: New Castle, DE
|
Found the issues the Hardware SPI is not working on the 18F |
Posted: Mon Nov 22, 2004 3:39 pm |
|
|
Just though that I would report back the conclusion.
Ckielstra was right about the reads 100% thank you.
But the other issues was in the write sub. I was send two commands to the EEPROM and not raising the chip select between sending one command and the next command.
Summing up:
Using the modification for the header file in the original post.
The main from the original post.
The updated include file below.
The hardware SPI works in all hardware (18F252,18LF2620 and 18LF4620).
Code: |
#bit EX_FROM_CS = 0xF8B.2 //O/P Chip Select
#bit EX_FROM_CLK = 0xF8B.3 //O/P Clock output
#bit EX_FROM_DO = 0xF8B.4 //I/P Data out of EX_EEPROM data in to MCU
#bit EX_FROM_DI = 0xF8B.5 //O/P Data out of MCU data in to EX_EEPROM
#ifndef EEPROM_ADDRESS
#define EEPROM_ADDRESS long
#endif
void init_ext_eeprom() {
short int i;
EX_FROM_DI = 0;
EX_FROM_CLK = 0;
EX_FROM_CS = 1;
i = EX_FROM_DO;
//Setup PIC for SPI Mode for the AT25256A
// setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_64 );
// setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16 );
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_4 );
}
BOOLEAN ext_eeprom_ready() {
int data;
EX_FROM_CS = 0; //Chip Select pin low
spi_write(0x05);
data = spi_read(0x00); //Opcode to Read Status Register (RDSR)
EX_FROM_CS = 1; //Chip Select pin high
return (!(bit_test(data, 0)));
}
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) {
do {} while (!(ext_eeprom_ready())); //wait until the eeprom is out of the previous write state, if applicable
EX_FROM_CS = 0; //Chip Select pin low
spi_write(0x06); //Opcode for enable writing to EEPROM
EX_FROM_CS = 1; //Chip Select pin high
EX_FROM_CS = 0; //Chip Select pin low
spi_write(0x02); //Opcode for writing to EEPROM
spi_write(make8(address,1));
spi_write(make8(address,0));
spi_write(data);
EX_FROM_CS = 1; //Chip Select pin high
}
BYTE read_ext_eeprom(EEPROM_ADDRESS address) {
int data;
do {} while (!(ext_eeprom_ready())); //wait until the eeprom is out of the previous write state, if applicable
EX_FROM_CS = 0; //Chip Select pin low
spi_write(0x03);
spi_write(make8(address,1));
spi_write(make8(address,0));
data = spi_read(0x00); //Read Data
EX_FROM_CS = 1; //Chip Select pin high
return(data);
}
|
Thanks All |
|
|
|
|
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
|