LPC1114: Setting up SPI

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

LPC1114: Setting up SPI

4,954件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 00:04:21 MST 2013
Hi,

This is my first time dabbing with SPI, so I'm not 100% comfortable with it.

I'm trying to initialize it, but I still have no relevant output on my pins, more specifically SCK.

This is the code I have so far:

void config_SSP(void)
{
LPC_SYSCON->PRESETCTRL |= (0x1<<0);
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 11);

LPC_SYSCON->SSP0CLKDIV = 0x0a;

LPC_IOCON->PIO0_8 &= ~0x07; /* SSP I/O config */
LPC_IOCON->PIO0_8 |= 0x01; /* SSP MISO */
LPC_IOCON->PIO0_9 &= ~0x07;
LPC_IOCON->PIO0_9 |= 0x01; /* SSP MOSI */
LPC_IOCON->SCK_LOC = 0x02;
LPC_IOCON->PIO0_6 = 0x02;
LPC_IOCON->PIO0_2 &= ~0x07;
LPC_IOCON->PIO0_2 |= 0x01;

  /* Set DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0, and SCR is 7 */
    LPC_SSP0->CR0 = 0x0707;

  /* SSPCPSR clock prescale register, master mode, minimum divisor is 0x02 */
    LPC_SSP0->CPSR = 0x2;

  /* Master mode */
    LPC_SSP0->CR1 = 0;
}

Can someone please orient me on how to set this up correctly so I can at least see an SCK on the output pin? My slave broke recently so I can't do a full test with it until I get the replacement, but I still want to get ahead.

Thank you very much!
0 件の賞賛
返信
17 返答(返信)

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Sat Apr 27 22:09:19 MST 2013
Hi, figured it out! After painfully excruciating analysis, I realized I am not enabling the clock to the IOCON block, so by adding a simple LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 16); to the SSP config, it worked!
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 14:54:38 MST 2013
Thank you so much man. I'll try this later and I'll let you know how it goes!
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Apr 26 14:37:00 MST 2013
Or just use a Keil sample?

http://www.keil.com/forum/17798/
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 13:49:19 MST 2013
It should be right? Since I can run blinky, the LPC should be running and IOCON should be enabled.

The pins are also defined correctly from what I check on lpc11xx.h
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Apr 26 13:27:08 MST 2013
Switching DIR is working for GPIO only. So it's useless for SSP functions.

/* SSP Status register */
#define SSPSR_TFE       (0x1<<0)
#define SSPSR_TNF       (0x1<<1)
#define SSPSR_RNE       (0x1<<2)
#define SSPSR_RFF       (0x1<<3)
#define SSPSR_BSY       (0x1<<4)

/* SSP CR1 register */
#define SSPCR1_LBM      (0x1<<0)
#define SSPCR1_SSE      (0x1<<1)
#define SSPCR1_MS       (0x1<<2)
#define SSPCR1_SOD      (0x1<<3)

void config_SSP(void)
{
    //enable clocks for the SSP
    LPC_SYSCON->PRESETCTRL |= (0x1<<0);
    LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 11);

    LPC_SYSCON->SSP0CLKDIV = 0xFF; //Orig clk is 3MHz??
    //from the interwebzz -- VERIFY
    LPC_IOCON->PIO0_8 &= ~0x07; //SSP I/O config
    LPC_IOCON->PIO0_8 |= 0x01; //SSP MISO
    LPC_IOCON->PIO0_9 &= ~0x07;
    LPC_IOCON->PIO0_9 |= 0x01; //SSP MOSI
    LPC_IOCON->SCK_LOC = 0x02;
    LPC_IOCON->PIO0_6 = 0x02;
    LPC_IOCON->PIO0_2 &= ~0x07;
    LPC_IOCON->PIO0_2 |= 0x01;

      //Set DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0, and SCR is 7
    LPC_SSP0->CR0 = 0x0707;

      //SSPCPSR clock prescale register, master mode, minimum divisor is 0x02
    LPC_SSP0->CPSR = 0x2;

      //Master mode
    LPC_SSP0->CR1 = SSPCR1_SSE;
}


uint8_t SPI0_write(uint8_t byte)
{
 uint8_t readback;
#if !USE_CS0
 LPC_GPIO0->DATA &=~(1<<2);
#endif
 LPC_SSP0->DR = byte;
/* Wait until the Busy bit is cleared */
 while (!(LPC_SSP0->SR & SSPSR_BSY));
// while ((LPC_SSP0->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );


  readback = LPC_SSP0->DR;
#if !USE_CS0
 LPC_GPIO0->DATA |=(1<<2);
#endif
 return(readback);
}

int main()
{
    int i, j;

    //init GPIO and SSP
    //config_GPIO();
    config_SSP();


    while (1)
    {
        SPI0_write((uint8_t)j);

        //ledOn();
        for (i = 0; i < 1E4; i++)
        {
        }
        //ledOff();
        for (i = 0; i < 1E4; i++)
        {
        }
        j++;
    }
}
is working with LPCXpresso as expected. Clock = 48MHz/2/255/8 = 11764 Hz.

But I don't know if your 1114 is running (48MHz) and IOCON is switched on. So I would suggest to use debugger to check IOCON setting of SSP pins.
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 13:13:47 MST 2013

Quote: R2D2
Use Master mode (end of init):
//Master mode
LPC_SSP0->CR1 = SSPCR1_SSE;



Still nothing... :confused:

Are these lines correct?
        LPC_GPIO0->DIR |= MY_PIO0_7;
LPC_GPIO0->DIR |= MY_PIO0_6;
LPC_GPIO0->DIR |= MY_PIO0_9;


where

MY_PIO_7 = 0x80
MY_PIO_6 = 0x40
MY_PIO_9 = 0x200

Then again, if I remove them I still get nothing...
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Apr 26 13:06:56 MST 2013
Use Master mode (end of init):
//Master mode
LPC_SSP0->CR1 = SSPCR1_SSE;
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 12:59:24 MST 2013
So it doesn't seem to hang anymore! Yay! I'm running blinky next to it to check for this, and it continues to loop fine.

Still, I can't see a valid signal in the output... :confused:

Output is still a logical high for SCK, MISO and MOSI. Any further thoughts?
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Apr 26 12:47:22 MST 2013
OOOps, waiting for RNE is not a good idea without slave:
[COLOR=Red]while (!(LPC_SSP0->SR & SSPSR_BSY));[/COLOR]
// while ((LPC_SSP0->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 12:28:40 MST 2013

Quote: R2D2
And what are the guys in the Keil forum suggesting?



I haven't posted there yet. To be honest, I found this forum last night and it seemed like a good place for info, but I'll post into the Keil forum and see what can I get as well. Thanks!


Quote: R2D2
For a simple (= polling) SPI it's enough to use a working init() and a read/write() function.



Yeah, I kind of figured this out as well, and I feel I understand better what the code is doing.


Quote: R2D2

Without slave you can test them by scoping your signals (of course without MISO). I usually use a delay and write a byte in a loop.Triggered by SSEL my scope is showing me clock and MOSI byte. If they are correct I connect the slave.


Yeah, I'm scoping the signal but I have started to get a weird output on my clk and on the MOSI. It looks like a small (400mV ptp), crappy signal. I'm using exactly what you said, a small delay while writing a byte inside a while(1) loop. This is what I have:

void config_SSP(void)
{
//enable clocks for the SSP
LPC_SYSCON->PRESETCTRL |= (0x1<<0);
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 11);

LPC_SYSCON->SSP0CLKDIV = 0xFF; //Orig clk is 3MHz??

LPC_IOCON->PIO0_8 &= ~0x07; //SSP I/O config
LPC_IOCON->PIO0_8 |= 0x01; //SSP MISO
LPC_IOCON->PIO0_9 &= ~0x07; 
LPC_IOCON->PIO0_9 |= 0x01; //SSP MOSI
LPC_IOCON->SCK_LOC = 0x02;
LPC_IOCON->PIO0_6 = 0x02;
LPC_IOCON->PIO0_2 &= ~0x07;
LPC_IOCON->PIO0_2 |= 0x01;

  //Set DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0, and SCR is 7
    LPC_SSP0->CR0 = 0x0707;

  //SSPCPSR clock prescale register, master mode, minimum divisor is 0x02
    LPC_SSP0->CPSR = 0x2;

  //Master mode
    LPC_SSP0->CR1 = 0;
    //LPC_SSP0->CR1 = SSPCR1_SSE;
}

void config_GPIO(void)
{
//enable clocks to GPIO block
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL <<  6);

//set port 0_7 to output (high current drain in LPC1114)
    LPC_GPIO0->DIR |= MY_PIO0_7;
LPC_GPIO0->DIR |= MY_PIO0_6;
LPC_GPIO0->DIR |= MY_PIO0_9;
}

int main()
{
int i, j;

//init GPIO and SSP
config_GPIO();
config_SSP();


while (1)
{
SPI0_write((uint8_t)j);

//ledOn();
for (i = 0; i < 0x0007FFFF; i++)
{
}
//ledOff();
for (i = 0; i < 0x0007FFFF; i++)
{
}
j++;
}   
}




Quote: R2D2

BTW: Is your Urbana Urbana in Italy?


Nope, it's Urbana, IL, USA. I'm a student here and I'm starting to dab into MCUs just for a fun side project. I wish I was in Italy!
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Apr 26 12:06:32 MST 2013

Quote: gabrielh
Thanks! I found the files even though I'm not using LPCXpresso. I'm using uVision with Keil instead. and a uLINK.



And what are the guys in the Keil forum suggesting?

For a simple (= polling) SPI it's enough to use a working init() and a read/write() function.

Without slave you can test them by scoping your signals (of course without MISO). I usually use a delay and write a byte in a loop.Triggered by SSEL my scope is showing me clock and MOSI byte. If they are correct I connect the slave.

BTW: Is your Urbana Urbana in Italy?
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 11:34:54 MST 2013
Thanks! I found the files even though I'm not using LPCXpresso. I'm using uVision with Keil instead. and a uLINK.

I'm including ssp.h, but I notice several functions at the bottom of the file (from ssp.c). Do I need to use any of these? The thing is I use slightly different libraries that define everything. I'm including the LPC11xx.h library I have for further reference. Could you help orient me why it's not working? I'm kind of lost, honestly.


I really appreciate your help!

EDIT: Ok, small update. I think I know what's going on. I feel like I have the same setup, though done differently. my config_SSP is essentially a more specific case for SSP_IOConfig and SSP_Init in ssp.c right? Therefore, I don't really need the functions defined in here, though I'm certainly using the #defines in ssp.h. After compiling and running, it seems like the run is getting stuck at this line:

  while ((LPC_SSP0->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );

It looks like the busy bit is not being cleared/set. Any input?

Thanks!
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Apr 26 11:12:10 MST 2013
In SSP sample :)

ssp.h in ...\LPCXpresso_5.2.2_2108\lpcxpresso\Examples\NXP\LPC1000\LPC11xx\NXP_LPCXpresso1114-302_2011-02-07.zip\ssp\driver
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 11:05:24 MST 2013
Where are the global variables like SSPSR_BSY and SSPSR_RNE defined?

Thanks!
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Apr 26 10:58:08 MST 2013

Quote: gabrielh
Do I have to be writing/reading in order to get a clock showing on PIO0_6?



Yes, that's the job of the master.

Quote: gabrielh

Also, to read/write, a line such as
myVar = LPC_SSP0->DR;
would be sufficient? Or do I have to do anything else?



Check busy bit and write. SPI is shifting bits through the slave
uint8_t SPI0_write(uint8_t byte)
{
 uint8_t readback;
#if !USE_CS0
 LPC_GPIO0->DATA &=~(1<<2);
#endif
 LPC_SSP0->DR = byte;
/* Wait until the Busy bit is cleared */
  while ((LPC_SSP0->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
  readback = LPC_SSP0->DR;
#if !USE_CS0
 LPC_GPIO0->DATA |=(1<<2);
#endif
 return(readback);
}
There are 'ssp' examples in your example folder, which can help you to understand the necessary things.
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gabrielh on Fri Apr 26 10:33:52 MST 2013
Hey R2D2,

Thanks for replying! Quick followup. Do I have to be writing/reading in order to get a clock showing on PIO0_6? The thing is I still get only a logic high at that pin. My SSEL outputs constant low and my MOSI and MISO aren't really connected to anything and are constant high both of them.

Also, to read/write, a line such as
myVar = LPC_SSP0->DR;
would be sufficient? Or do I have to do anything else?

In case it is helpful, I call config_GPIO first, which is this:

void config_GPIO(void)
{
//enable clocks to GPIO block
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL <<  6);


    LPC_GPIO0->DIR |= MY_PIO0_7;
LPC_GPIO0->DIR |= MY_PIO0_6; //I've tried both with and w/o these
LPC_GPIO0->DIR |= MY_PIO0_9; //lines to no avail
}

I really appreciate your help!
0 件の賞賛
返信

4,193件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Apr 26 00:24:22 MST 2013
Your init looks correct and you should see a clock at PIO0_6 while you write data to SSP. That's all what I can say without seeing your exported project :)
0 件の賞賛
返信