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 support@ccsinfo.com

H/W SPI on a pic24
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Apr 08, 2009 3:45 pm     Reply with quote

As expected, the PIC24FJ128GA106 SPI is working regularly. As with other PIC24, it's recommended to read the datasheet thoroughly and to check, which PCD built-in functions are working correctly and which are apparently faulty. I used PCD V4.084. There may be SPI related changes towards V4.090, but rather unlikely.

I used this setup, with some additional definitions.
Code:
#define SPI_CLK_DIV_2    0x001B
#define SPI_CPHA_0       0x0100

#define SPI_MODE_0 (SPI_L_TO_H | SPI_CPHA_0)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L | SPI_CPHA_0)
#define SPI_MODE_3 (SPI_H_TO_L)

setup_spi(SPI_MASTER | SPI_MODE_3 |SPI_CLK_DIV_1);

#pin_select preprocessor commands are generally functional, except for the RPI45 input pin that's used for SDI1 in my application. So I had to go back to manual register settings (not shown here).
Code:
#pin_select SDI1=PIN_xx
#pin_select SDO1=PIN_F3
#pin_select SCK1OUT=PIN_D9

From the read/write built-in functions, only spi_read(data) is working correctly, and it must not be used without an argument. As in other cases, PCD built-in functions apparently have never been tested at CCS.

Code:
SPI_nCS_LAT = 0;
spi_read(0xAB);
spi_read(0);
spi_read(0);
spi_read(0);
bID=spi_read(0);
SPI_nCS_LAT = 1;

The above code reads the ID byte from a serial flash memory, proving that the interface is operating correctly.

I also tried #use spi, but an error message informed me, that it isn't supporting hardware SPI.
geokonst



Joined: 04 Apr 2009
Posts: 27

View user's profile Send private message

PostPosted: Wed Apr 08, 2009 8:57 pm     Reply with quote

Dear Fvm,
Thank you for your reply.
Could you please clarify for me the following;
What exactly SPI_CPHA_0 is doing?
How did you find out that RPI45 was not working with pin_select? Did you get an error message? could this be causing my problem?
Finally why are you using four spi_reads? Do you need to send 3 bytes before the memory chip responds or is it some other reason?

Thanks for you help.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Apr 09, 2009 12:42 am     Reply with quote

Quote:
What exactly SPI_CPHA_0 is doing
It's used to set the clock phase (CPHA in the original Motorola SPI terminology). Without setting this bit, PIC24 SPI operation defaults to mode 1 and mode 3. With PCH, this option could be set by SPI_XMIT_L_TO_H. As said, you have to read the PIC24 datasheet. (And should know, which SPI modes are supported by the connected peripheral).

Code:
#pin_select SDI1=PIN_F6
results in an "Invalid Pin" error. (PIN_F6 is RPI45)

Quote:
Finally why are you using four spi_reads?
Sending 3 dummy bytes is simply required by the serial flash. Nothing specific to PIC24.
geokonst



Joined: 04 Apr 2009
Posts: 27

View user's profile Send private message

PostPosted: Thu Apr 09, 2009 1:03 pm     Reply with quote

Ok I think I've done whatever there is to do to make this work (at least for a newbie).

I just don't get it.
This code:
Code:
#include "D:\...hardware.h"
#PIN_SELECT SDI1=PIN_G8
#PIN_SELECT SDO1=PIN_G7
#PIN_SELECT SCK1OUT=PIN_G6
#PIN_SELECT U2TX=PIN_F5
#PIN_SELECT U2RTS=PIN_F4

#use rs232(UART2,baud=19200,parity=N,bits=8)

#define SPI_CLK_DIV_2    0x001B
#define SPI_MODE_3 (SPI_H_TO_L)
#define cs PIN_B2
#define id 0x8f
#define getx 0xa9
#define gety 0xab
#define getz 0xad

int dataout;

main(){
setup_spi(SPI_MASTER | SPI_MODE_3 |SPI_CLK_DIV_1);

output_low(PIN_B15);

//who_am_i
output_low(cs);
spi_read(id);
dataout=spi_read(0);
putc(dataout);
output_high(cs);

delay_ms(500);
//cfg
output_low(cs);
spi_read(0x20);
spi_read(0xC7); //11000011
output_high(cs);

while (1){
putc (0x80);

output_low(cs);
spi_read(getx);
dataout=spi_read(0);
putc(dataout);
output_high(cs);

output_low(cs);
spi_read (gety);
dataout=spi_read(0);
putc(dataout);
output_high(cs);

output_low(cs);
spi_read (getz);
dataout=spi_read(0);
putc(dataout);
output_high(cs);
}

}


Does not work (sends 80 and 3 zeroes to the serial port)

The same sequence with my software spi:

Code:
#include "C:\...uclboard.h"
#PIN_SELECT U2TX=PIN_F5
#PIN_SELECT U2RTS=PIN_F4

#use rs232(UART2,baud=19200,parity=N,bits=8)

#define in PIN_G8
#define out PIN_G7
#define clk PIN_G6
#define cs PIN_B2
#define id 0x8f
#define getx 0xa9
#define gety 0xab
#define getz 0xad

int recVal = 0x00;
int i;


void spisend(sendVal)
{
for (i=7;i>=0;i--){
output_bit(out,BIT_TEST(sendVal,i));
output_low(clk);
output_high(clk);
}
}

void spiread()
{
for (i=7;i>=0;i--){
output_low(clk);
if (input(in)){
    BIT_SET(recVal,i);
}
output_high(clk);
}
putc(recVal);
recVal=0x00;
}

void main()
{
output_low(PIN_B15);

output_high(clk);

//who_am_i
output_low(cs);
spisend(id);
//spiread();
output_high(cs);

delay_ms(500);
//cfg
output_low(cs);
spisend(0x20);
spisend(0xC7); //11000011
output_high(cs);

while (1){
putc (0x80);

output_low(cs);
spisend(getx);
spiread();
output_high(cs);

output_low(cs);
spisend(gety);
spiread();
output_high(cs);

output_low(cs);
spisend(getz);
spiread();
output_high(cs);
}

}


Works perfectly!

both files have the same .h

Code:
#include <24FJ256GB106.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOJTAG                   //JTAG disabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES ICS3                     //ICD communication channel 3
#FUSES WINDIS                   //Watch Dog Timer in non-Window mode
#FUSES WPRES128                 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16                 //Watch Dog Timer PostScalar 1:32768
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FRC_PS                   //Fast RC Oscillator with Post Scaler
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES NOOSCIO                  //OSC2 is general purpose output
#FUSES NOPR                     //Pimary oscillaotr disabled
#FUSES IOL1WAY                  //Allows only one reconfiguration of peripheral pins
#FUSES WPEND_LOW             
#FUSES NOWPCFG               
#FUSES NOWPDIS               
#FUSES WPFP0                 
#FUSES PLL12                    //Divide By 12(48MHz oscillator input)
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(internal=8M)



...and were uploaded to the very same hardware one after the other.
Unfortunately I blew up my Explorer 16 board and can't use the scope any more, but last time I tried I got a good response from the accelerometer (LIS302DL) on h/w spi but the pic wouldn't read it. I can still use the serial though.

If anyone has an idea PLEASE PLEASE post it. This can't be so hard!
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Apr 09, 2009 2:44 pm     Reply with quote

I don't see anything wrong with your hardware SPI usage. Also the #pin_select commands seem to generate correct code.
geokonst



Joined: 04 Apr 2009
Posts: 27

View user's profile Send private message

PostPosted: Thu Apr 09, 2009 3:48 pm     Reply with quote

What's going wrong then? It's driving me mad. Why doesn't it read a perfectly sent response? I really don't want to switch back to C30! I hate c30!
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Apr 09, 2009 4:15 pm     Reply with quote

It's not necessarily a PCD issue. Although hardware SPI should be able to communicate with the ST acceloremeter, there may be a problem with your hardware and the faster HW operation. I would try to trace it at the hardware level. You also could replace the device with a SDO/SDI loopback to verify basic send/receive operation.
geokonst



Joined: 04 Apr 2009
Posts: 27

View user's profile Send private message

PostPosted: Thu Apr 09, 2009 4:35 pm     Reply with quote

But, you see the accelerometer is responding, so if it's a hardware issue it must be PIC's

The loopback is a very good idea!
geokonst



Joined: 04 Apr 2009
Posts: 27

View user's profile Send private message

PostPosted: Thu Apr 09, 2009 6:41 pm     Reply with quote

The loopback test failed as well. I still get zeros. And I've tried different pins too. :(

FvM could the fact that I'm using the internal osc have anything to do with it? Doesn't sound likely but I'm running out of ideas.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Apr 10, 2009 2:59 am     Reply with quote

As previously reported, hardware SPI is basically working with PIC24F chips, at least using the read_spi() instruction. I tested with V4.084 and most recent V4.090. Of course, I had to check with my hardware, that is using different pins, so it must not necessarily work with your configuration. I also can't see, if there's something in your hardware.h include file that disturbs SPI operation. Generally I would proceed like this:

- check the code operation at the assembly/register level with MPLAB debugger (requires e.g. ICD2 or PICkit ICSP adapter).
- check the hardware operation with an oscilloscope or other hardware debug tools

I don't expect problems related to internal oscillator.
Ken Johnson



Joined: 23 Mar 2006
Posts: 197
Location: Lewisburg, WV

View user's profile Send private message

PostPosted: Fri Apr 10, 2009 7:05 am     Reply with quote

I'm using SPI on 24H for 2 different devices (ADC and FRAM) at 2 different clock speeds, using (sorry) Microchip's C30. Here are some code snippets:

Code:

    SPI2STAT = 0;               //  Disable the SPI2 module for setup;
    SPI2CON1bits.CKP    = 0;    //  Clock idles lo;
    SPI2CON1bits.CKE    = 1;    //  Read data on rising edge of SCK;
    SPI2CON1bits.MSTEN  = 1;    //  PIC is the master;
    SPI2CON1bits.PPRE   = 2;


and

Code:

void    SaveFRAM (ushort offset, const void *pRAM, ushort nBytes)
//  Writes nBytes from pRAM into STORAGE at offset:
{
    const   dbyte   *p;
    ushort  nWords;

    nWords = nBytes / 2;        //  16-bit transfers;
    p = (dbyte*) pRAM;          //  Pointer to 16-bit items;
    TaskBlock (ProcessTask);    //  Shares the SPI Port;
    SPI2CON1bits.MODE16 = 0;    //  8-bit transfers on SPI2;
    SPI2CON1bits.SPRE   = 7;    //  10MHz (max SCLK);
    SPI2STATbits.SPIEN  = 1;    //  Enable the SPI module;
    SelectFRAM (0);             //  Chip Select;
    SPI2BUF = WREN;             //  Write the command and wait:
    while ( !SPI2STATbits.SPIRBF );
    SPI2BUF;                    //  Read buffer to clear SPIRBF;
    SelectFRAM (1);             //  Toggle Chip Select;
    SelectFRAM (0);             //  Write the next command:
    SPI2BUF = WRITE;
    while ( !SPI2STATbits.SPIRBF );
    SPI2BUF;                    //  Read buffer to clear SPIRBF;
    SPI2STAT = 0;               //  Disable the SPI, and change mode:
    SPI2CON1bits.MODE16 = 1;    //  Now do 16-bit transfers;
    SPI2STATbits.SPIEN  = 1;    //  Enable the SPI module;
    SPI2BUF = offset;           //  Write the address;
    while ( !SPI2STATbits.SPIRBF );
    SPI2BUF;                    //  Read buffer to clear SPIRBF;
    while ( nWords-- ) {        //  Now write all the data:
        SPI2BUF = *p++;
        while ( !SPI2STATbits.SPIRBF );
        SPI2BUF;
    }
    SelectFRAM (1);
    SPI2STAT = 0;               //  Disable PIC SPI, and clear the read overrun flag;
    TaskUnBlock (ProcessTask);
}


Maybe comparing this with the CCS generated asm code will show something?

Best of luck!
Ken
Guest








PostPosted: Sat Apr 11, 2009 9:11 am     Reply with quote

geokonst-

I've made some progress over the last day or so, however I've done so using software SPI similar to what you've posted. Still nothing with the hardware (and still waiting for a response from Microchip). I was attempting to use port D on the PIC, of which one of the pins I was using apparently didn't work. However I tried port G like you were using and still didn't get a response. I'll keep you posted if I hear back from Microchip or get the hardware to work.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Apr 11, 2009 11:15 am     Reply with quote

I would be suprized, if there's a hardware problem with certain pins, but can be, of course. Anyway, it's interesting to know, which part of the SPI function is apparently failing: SCK, SDO or SDI/receive.
geokonst



Joined: 04 Apr 2009
Posts: 27

View user's profile Send private message

PostPosted: Sat Apr 11, 2009 5:32 pm     Reply with quote

I have too tried pins D1, D2, D3, G8, G7 with no luck (no compiler errors). I don't believe its a pin problem as pps works fine with the serial port. Also I've tried manually setting I/O direction.

The customer support sent me the following code which they say compiles:


Code:
#include <24fj256ga110.h>
#use delay(clock=40mhz)

#PIN_SELECT SDI1=PIN_G8
#PIN_SELECT SDO1=PIN_G7
#PIN_SELECT SCK1OUT=PIN_G6
#PIN_SELECT SS1OUT=PIN_B1

#PIN_SELECT U2TX=PIN_F5
#PIN_SELECT U2RTS=PIN_F4

#use rs232(UART1,baud=19200,parity=N,bits=8)
#use spi(SPI1, BITS=16, MODE=3)

int dataout;

void main(){
while (1){
output_low (PIN_B2);
dataout=SPI_XFER(0x8f);
output_a(dataout);
delay_us(50);
output_high (PIN_B2);
delay_ms(3);
}
}


It doesn't compile for me and the problem is the option "SPI1" in use spi. I have no idea why. Could you please try it and let me know if it compiles on your machine?

I have also tried the registers approach:
Code:
#include "D:\...24FJ256GB106_registers.h"

#PIN_SELECT SDI1=PIN_D1
#PIN_SELECT SDO1=PIN_D3
#PIN_SELECT SCK1OUT=PIN_G6
#PIN_SELECT U2TX=PIN_F5
#PIN_SELECT U2RTS=PIN_F4

#use rs232(UART2,baud=19200,parity=N,bits=8)
#define SPI_MASTER 0x0120 // select 8-bit master mode, CKE=1, CKP=0
#define SPI_ENABLE 0x8000 // enable SPI port, clear status

#define cs PIN_B2

int i;
int writeSPI2( int data)
{
SPI2BUF = data;
delay_ms(500);
return SPI2BUF; // read the received value
}
main()
{

output_high (cs);
SPI2CON1 = SPI_MASTER; // select mode
SPI2STAT = SPI_ENABLE; // enable the peripheral

while (1){
set_tris_d(0xfc);
output_low(cs);
writeSPI2( 0x8F); // send a READ STATUS COMMAND
i = writeSPI2( 0); // send dummy, read data
putc(i);
delay_ms(10);
output_high(cs);

delay_ms(10);
}
}
[/quote]
But I am really inexperienced so I probably have done something wrong.



So what is failing for me is reading the response (or putting the value in a variable). While I had access to an oscilloscope I could see that the communication was perfect. And I have also tried sorting sdi + sdo and still nothing. So SDI seems to be the problem.

Unfortunately I need hardware spi, so if you have any ideas please post them here. Thanks
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Apr 11, 2009 6:08 pm     Reply with quote

I didn't try #use spi with V4.090. As said, it didn't work with V4.084, at least for PIC24FJ128GA106 (and similar GA10x and GB10x chips). As a possible problem, CCS seems not to test built-in functions with the full choice of chips, so a lot of bugs related to chip specific features, register mappings etc. isn't detected.

I don't understand your "register approach", that uses #pin_select for SPI1 but accesses SPI2 registers. This can't work.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
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