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

Hardware SPI on the 18F252 and 18LF2620

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Tom-H-PIC



Joined: 08 Sep 2003
Posts: 105
Location: New Castle, DE

View user's profile Send private message

Hardware SPI on the 18F252 and 18LF2620
PostPosted: Mon Nov 22, 2004 9:49 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Nov 22, 2004 11:22 am     Reply with quote

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

View user's profile Send private message

Made the changes that you suggested No Help
PostPosted: Mon Nov 22, 2004 1:17 pm     Reply with quote

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

View user's profile Send private message

Found the issues the Hardware SPI is not working on the 18F
PostPosted: Mon Nov 22, 2004 3:39 pm     Reply with quote

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
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