This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SPI problem with LPC2129 (using MCB2100)

I have pull up resistors on the /SSEL pins of the SPI bus. I want to use the LPC2129 as master, let him send 10 bytes .. 1 time Ox55 and 9 times 0x00 but it seems not to work. Is there something wrong with the code?

With a scope I see the P0.0 work well as chip selector but I don't see a clk running also no data on the mosi/miso lines.

Here is my code:


#include <LPC21xx.H>
#include "Timer.h"                                    functions
unsigned int dummy;
unsigned int status = 0x0;
unsigned int s          = 0x0;
unsigned int i          = 0x0;
unsigned int cnt        = 0x0;
unsigned int buf[10];



void SPI0_Init(void)
{
        S0SPCCR         = 0xFA;
        S0SPCR          = 0x28;
        IOSET1          = 0x00020000;
}

int SPI0_WriteAA(void)
{
        S0SPDR = 0x55;

        while(!(S0SPSR & 0x80)){}

        if (S0SPSR != 0x80)
        {
                IOCLR1          = 0x00400000;
                IOSET1          = 0x00800000;
                status          = 0x1;
        }
        else
        {
                IOCLR1          = 0x00800000;
                IOSET1          = 0x00400000;
                status          = 0x0;
        }

        s = S0SPSR;

        return(status);
}

int SPI0_WriteFF(void)
{
        S0SPDR  = 0x00;

        while(!(S0SPSR & 0x80)){};

        if (S0SPSR != 0x80)
        {
                IOCLR1          = 0x00400000;
                IOSET1          = 0x00800000;
                status          = 0x1;
        }
        else
        {
                IOCLR1          = 0x00800000;
                IOSET1          = 0x00400000;
                status          = 0x0;
        }

        s = S0SPSR;

        return(status);
}

int SPI0_Read(void)
{
        dummy = S0SPDR;                                                                 //read data register
        buf[cnt] = dummy;
        if (cnt < 10) {
        cnt++;
        }
        return(dummy);
}

void wait (void)
{
  unsigned long i;

  i = timeval;
  while ((i + 100) != timeval);
}

void waitstartup (void)
{
  unsigned long i;

  i = timeval;
  while ((i + 15) != timeval);
}

int main (void)
{
        int c;

        PINSEL0         = 0x00005500;
        IODIR0          = 0x00010001;
        IOCLR0          = 0xFFFFFFFF;
        IOSET0          = 0x00010001;
        PINSEL1         = 0x154542A8;
        IODIR1          = 0x00FF0000;
        IOCLR1          = 0x00FF0000;
        IOSET1          = 0x00010000;

        SPI0_Init();
        init_timer();
        waitstartup();

        IOCLR0  = 0x00000001;
        IOSET1  = 0x00040000;

        while (1)
        {
                if (i==0)
                {
                        SPI0_WriteAA();

                        if (status == 0x0)
                        {
                                SPI0_Read();
                        }

                        for (c=0;c<9;c++)
                        {
                                SPI0_WriteFF();

                                if (status == 0x0)
                                {
                                        SPI0_Read();
                                }
                        }
                   i=1;

                IOSET0          = 0x00000001;
                wait();
                IOCLR1          = 0x00040000;
                }
        }
}

  • I noticed that after

    S0SPDR = 0x55;

    S0SPDR stays 0x00 when I use the debug mode in uVision. This can't be right.. can it?
    Is there another way to write something to S0SPDR?

  • Do you like code with a lot of long "magic" hex constants? It takes significant time to look at them and correlate with the datasheet to see what your intentions are.

  • I did delete the comments here with comments I think it will make some more sense.

    ;/*******************************************************************************/
    ;/* Sensor.c:   Reading the angle via the Melexis 90316 using SPI                           */
    ;/*                     the measured angle will be send out via CAN.                    */
    ;/*******************************************************************************/
    #include <LPC21xx.H>                                                      // LPC21xx definitions
    #include <stdio.h>
    #include "Timer.h"                                                            // Timer voor wait functions
    unsigned int dummy;
    unsigned int status = 0x0;                                              //0x0 = ok , 0x1 = error
    unsigned int s          = 0x0;
    unsigned int i          = 0x0;
    unsigned int cnt        = 0x0;
    unsigned int buf[10];
    
    //#define S0SPCR                                                        control function SPI interface
    //#define S0SPSR                                                        monitor status SPI interface
    //#define S0SPDR                                                        transmit/received data register
    //#define S0SPCCR                                                       controls clock rate (as master)
    //#define S0SPINT                                                       interupt flag
    
    void SPI0_Init(void)
    {
            S0SPCCR         = 0x3C;                                                 /* 8 >, even, SCK=15M/250 = 60k */
            S0SPCR          = 0x28;                                                 /* CPHA=1, CPOL=0, master mode,
                                                                                                       MSB first, interrupt enabled  */
            IOSET1          = 0x00020000;                                   /* Blink a led                                   */
    }
    
    int SPI0_WriteAA(void)
    {
            S0SPDR = 0x55;                                                          //write data to SPI data register, AA after inv.
    
            while(!(S0SPSR & 0x80)){}                                   //wait until SPIF bit is set
    
            if (S0SPSR != 0x80)
            {
                    IOCLR1          = 0x00400000;
                    IOSET1          = 0x00800000;                           //error indicatie
                    status          = 0x1;
            }
            else
            {
                    IOCLR1          = 0x00800000;
                    IOSET1          = 0x00400000;                           //status = ok
                    status          = 0x0;
            }
    
            dummy = S0SPDR;
    
            return(status);
    }
    
    int SPI0_WriteFF(void)
    {
            S0SPDR  = 0x00;                                                         //write data to SPI data register, FF after inv.
    
            while(!(S0SPSR & 0x80)){};                                  //wait until SPIF bit is set
    
            if (S0SPSR != 0x80)
            {
                    IOCLR1          = 0x00400000;
                    IOSET1          = 0x00800000;                           //error indicatie
                    status          = 0x1;
            }
            else
            {
                    IOCLR1          = 0x00800000;
                    IOSET1          = 0x00400000;                           //status = ok
                    status          = 0x0;
            }
    
            s = S0SPSR;
    
            return(status);
    }
    
    int SPI0_Read(void)
    {
            dummy = S0SPDR;                                                                 //read data register
            buf[cnt] = dummy;
            if (cnt < 10) {
            cnt++;
            }
            return(dummy);
    }
    
    void wait (void)
    {                                                               /* wait function */
      unsigned long i;
    
      i = timeval;
      while ((i + 100) != timeval);              /* wait 100ms */
    }
    
    void waitstartup (void)
    {                                                               /* wait function */
      unsigned long i;
    
      i = timeval;
      while ((i + 15) != timeval);              /* wait 5ms */
    }
    
    int main (void)
    {
            int c;
    
            PINSEL0         = 0x00005500;                                   /* Pin select                                    */
            IODIR0          = 0x00010001;                                   /* Select pin direction                  */
            IOCLR0          = 0xFFFFFFFF;
            /* GPIO P0.3 and P0.16 as outputs */
            IOSET0          = 0x00010001;                                   /* SSEL = '1'                                    */
    
            PINSEL1         = 0x154542A8;
            IODIR1          = 0x00FF0000;                                   /* Select direction pins                 */
            /* GPIO P1.16 - P1.23 as outputs */
            IOCLR1          = 0x00FF0000;                                   /* All leds off                                  */
            IOSET1          = 0x00010000;                                   /* Status led, system is running */
    
            SPI0_Init();
            init_timer();
            waitstartup();
    
            IOCLR0  = 0x00000001;                                   //SSEL = '0'
            IOSET1  = 0x00040000;                                   //set SSEL led
    
            while (1)
            {
                    IOCLR0  = 0x00000001;                                   //SSEL = '0'
    
                    SPI0_WriteAA();
    
                    if (status == 0x0)
                            {
                                    SPI0_Read();
                            }
    
                    IOSET0          = 0x00000001;                   //SSEL = '1'
                    wait();                                                         //extra wait voor LED indicatie
                    IOCLR1          = 0x00040000;                   //clear SSEL led
            }
    }
    

  • ;/*******************************************************************************/
    ;/* Sensor.c:   Reading the angle via the Melexis 90316 using SPI                           */
    ;/*                     the measured angle will be send out via CAN.                    */
    ;/*******************************************************************************/
    #include <LPC21xx.H>                                                      // LPC21xx definitions
    #include <stdio.h>
    #include "Timer.h"                                                            // Timer voor wait functions
    unsigned int dummy;
    unsigned int status = 0x0;                                              //0x0 = ok , 0x1 = error
    unsigned int s          = 0x0;
    unsigned int i          = 0x0;
    unsigned int cnt        = 0x0;
    unsigned int buf[10];
    
    //#define S0SPCR                                                        control function SPI interface
    //#define S0SPSR                                                        monitor status SPI interface
    //#define S0SPDR                                                        transmit/received data register
    //#define S0SPCCR                                                       controls clock rate (as master)
    //#define S0SPINT                                                       interupt flag
    
    void SPI0_Init(void)
    {
            S0SPCCR         = 0x3C;                                                 /* 8 >, even, SCK=15M/250 = 60k */
            S0SPCR          = 0x28;                                                 /* CPHA=1, CPOL=0, master mode,
                                                                                                       MSB first, interrupt enabled  */
            IOSET1          = 0x00020000;                                   /* Blink a led                                   */
    }
    
    int SPI0_WriteAA(void)
    {
            S0SPDR = 0x55;                                                          //write data to SPI data register, AA after inv.
    
            while(!(S0SPSR & 0x80)){}                                   //wait until SPIF bit is set
    
            if (S0SPSR != 0x80)
            {
                    IOCLR1          = 0x00400000;
                    IOSET1          = 0x00800000;                           //error indicatie
                    status          = 0x1;
            }
            else
            {
                    IOCLR1          = 0x00800000;
                    IOSET1          = 0x00400000;                           //status = ok
                    status          = 0x0;
            }
    
            dummy = S0SPDR;
    
            return(status);
    }
    
    int SPI0_WriteFF(void)
    {
            S0SPDR  = 0x00;                                                         //write data to SPI data register, FF after inv.
    
            while(!(S0SPSR & 0x80)){};                                  //wait until SPIF bit is set
    
            if (S0SPSR != 0x80)
            {
                    IOCLR1          = 0x00400000;
                    IOSET1          = 0x00800000;                           //error indicatie
                    status          = 0x1;
            }
            else
            {
                    IOCLR1          = 0x00800000;
                    IOSET1          = 0x00400000;                           //status = ok
                    status          = 0x0;
            }
    
            s = S0SPSR;
    
            return(status);
    }
    
    int SPI0_Read(void)
    {
            dummy = S0SPDR;                                                                 //read data register
            buf[cnt] = dummy;
            if (cnt < 10) {
            cnt++;
            }
            return(dummy);
    }
    
    void wait (void)
    {                                                               /* wait function */
      unsigned long i;
    
      i = timeval;
      while ((i + 100) != timeval);              /* wait 100ms */
    }
    
    void waitstartup (void)
    {                                                               /* wait function */
      unsigned long i;
    
      i = timeval;
      while ((i + 15) != timeval);              /* wait 5ms */
    }
    
    int main (void)
    {
            int c;
    
            PINSEL0         = 0x00005500;                                   /* Pin select                                    */
            IODIR0          = 0x00010001;                                   /* Select pin direction                  */
            IOCLR0          = 0xFFFFFFFF;
            /* GPIO P0.3 and P0.16 as outputs */
            IOSET0          = 0x00010001;                                   /* SSEL = '1'                                    */
    
            PINSEL1         = 0x154542A8;
            IODIR1          = 0x00FF0000;                                   /* Select direction pins                 */
            /* GPIO P1.16 - P1.23 as outputs */
            IOCLR1          = 0x00FF0000;                                   /* All leds off                                  */
            IOSET1          = 0x00010000;                                   /* Status led, system is running */
    
            SPI0_Init();
            init_timer();
            waitstartup();
    
            IOCLR0  = 0x00000001;                                   //SSEL = '0'
            IOSET1  = 0x00040000;                                   //set SSEL led
    
            while (1)
            {
                    IOCLR0  = 0x00000001;                                   //SSEL = '0'
    
                    SPI0_WriteAA();
    
                    if (status == 0x0)
                            {
                                    SPI0_Read();
                            }
    
                    IOSET0          = 0x00000001;                   //SSEL = '1'
                    wait();                                                         //extra wait voor LED indicatie
                    IOCLR1          = 0x00040000;                   //clear SSEL led
                    if (i==0)
                    {
                            SPI0_WriteAA();
    
                            if (status == 0x0)
                            {
                                    SPI0_Read();
                            }
    
                            for (c=0;c<9;c++)                            // 8 bytes 0xFF
                            {
                                    SPI0_WriteFF();
    
                                    if (status == 0x0)
                                    {
                                            SPI0_Read();
                                    }
                            }
                       i=1;
    
                    IOSET0          = 0x00000001;                   //SSEL = '1'
                    wait();                                                         //extra wait voor LED indicatie
                    IOCLR1          = 0x00040000;                   //clear SSEL led
                    }
            }
    }
    

    why are there no edit buttons here? There was something missing in the code in the post above.

  • That's what the 'Preview' is for - check the preview before you press 'Post'!

    You shouldn't be editing the posted code anyhow!
    If it's been edited in the forum, it's not what you're compiling or running - and that's not helpful.

    Always and only use copy-and-paste to post code.

    Have you used TABs to lay-out your code?
    These are entirely unreliable, and lead to the loss of tabulation.

    Use only spaces to lay-out your code!
    Any decent programmer's editor will be able to convert existing TABs to spaces, and will be able to insert spaces when you press the TAB key.

  • The missing edit buttons can in some cases be handled by the preview function.

    A couple of notes about your comments:

    PINSEL0 selects mode for a numbers of P0.x pins, so the comment shouldn't mention "Pin select" but what special configuration you are specifying (such as enabling the SPI pins).

    IODIR0 selects I/O direction for a number of pins, so the comment "Select pin direction" doesn't give much extra help. Which pins are set as outputs?

    The comment "GPIO P0.3 and P0.16 as outputs" doesn't seem to match the I0DIR0 assign.

    If you declare a constant SSEL = 0, you may write

    IOSET1 = 1 << SSEL;
    

    Your program performs just about everything using global variables. That doesn't help you a lot. It isn't visible which global variables are updated by which calls, so when reading the code, you can not see if an if statement makes sense or not.

    Note how similar SPI0_WriteAA and SPI0_WriteFF are? That may be a good indication that you should just have a SPI0_Write() function, and use a parameter to inform what value to send.

  • Per Westermark said, "Do you like code with a lot of long "magic" hex constants? It takes significant time to look at them and correlate with the datasheet to see what your intentions are."

    Bas van Dijk replied, "I did delete the comments here with comments I think it will make some more sense."

    Magic numbers with comments is little more help than "bare" magic numbers!

    Much better to use meaningful symbolic names!

  • Yeah I used TABs.. I use Keil uVision.
    Problems with SPI are fixed but I didn't change anything in the code so the code is right. Don't really know what was wrong. But it works now.

    I deleted the tabs and have spaces in my code now.

    uhh.. that's the only thing I changed, is it possible that that was the cause of the SPI problems?

  • "Yeah I used TABs.. I use Keil uVision."

    The uVision editor can be configured to insert spaces when you press the TAB key.

    Although it has many limitations, that isn't one of them!