EmbeddedRelated.com
Forums

How to access to the SPI bus (LPC2138)

Started by pouettagada July 3, 2009
Hi everybody,

I used a LPC2138 with an OS freeRTOS. I'd like to access to the SPI bus but I don't know how. I'm a beginner on it

Could you tell me how can I do it?

Have you some examples? some tutorials?
Thank you for your helps

An Engineer's Guide to the LPC2100 Series

On Friday 03 July 2009 11:21:26 pouettagada wrote:
> I used a LPC2138 with an OS freeRTOS. I'd like to access to the SPI bus
> but I don't know how. I'm a beginner on it
>
> Could you tell me how can I do it?
>
> Have you some examples? some tutorials?

'The Insider's Guide To The Philips ARM7-Based Microcontrollers' tells the
basics, NXP has an appnote with some code (to acces an SD card, i think).

Use google, they are both easy to find.

Start without FreeRTOS, just the basics. Once that works, you might need to do
some more work if you want to access the SPI interface from multiple tasks,
but that's a whole other question.

Greetings,
-bas
Hi

i am trying to estalish communication between tw0 LPC2148 uisng SPI
protocol.

i read the manual also.

but i am not able to write the data and read the data from/to SPI data
register(S0SPDR).

i am not getting the solution for this?

help me,thanks in advance
On Fri, Jul 3, 2009 at 8:40 PM, Bastiaan van Kesteren
wrote:

> On Friday 03 July 2009 11:21:26 pouettagada wrote:
> > I used a LPC2138 with an OS freeRTOS. I'd like to access to the SPI bus
> > but I don't know how. I'm a beginner on it
> >
> > Could you tell me how can I do it?
> >
> > Have you some examples? some tutorials?
>
> 'The Insider's Guide To The Philips ARM7-Based Microcontrollers' tells the
> basics, NXP has an appnote with some code (to acces an SD card, i think).
>
> Use google, they are both easy to find.
>
> Start without FreeRTOS, just the basics. Once that works, you might need to
> do
> some more work if you want to access the SPI interface from multiple tasks,
> but that's a whole other question.
>
> Greetings,
> -bas
>
Give us a little more information on what you have done so far. 'Help
me' is not very informative.

Sutton

Raju N wrote:
> Hi
>
> i am trying to estalish communication between tw0 LPC2148 uisng SPI
> protocol.
>
> i read the manual also.
>
> but i am not able to write the data and read the data from/to SPI data
> register(S0SPDR).
>
> i am not getting the solution for this?
>
> help me,thanks in advance
> On Fri, Jul 3, 2009 at 8:40 PM, Bastiaan van Kesteren
> >wrote:
>
> > On Friday 03 July 2009 11:21:26 pouettagada wrote:
> > > I used a LPC2138 with an OS freeRTOS. I'd like to access to the
> SPI bus
> > > but I don't know how. I'm a beginner on it
> > >
> > > Could you tell me how can I do it?
> > >
> > > Have you some examples? some tutorials?
> >
> > 'The Insider's Guide To The Philips ARM7-Based Microcontrollers'
> tells the
> > basics, NXP has an appnote with some code (to acces an SD card, i
> think).
> >
> > Use google, they are both easy to find.
> >
> > Start without FreeRTOS, just the basics. Once that works, you might
> need to
> > do
> > some more work if you want to access the SPI interface from multiple
> tasks,
> > but that's a whole other question.
> >
> > Greetings,
> > -bas
> >
> >
> >
> >
> >
--- In l..., Sutton Mehaffey wrote:
>
> Give us a little more information on what you have done so far. 'Help
> me' is not very informative.
>
> Sutton
>
Agreed!

Here is some code for RECEIVING SPI as a slave device using interrupts and jamming the data into a FreeRTOS queue. Whether you use FreeRTOS or not, you will probably always want to use a queue to present the data to the application.

SENDING SPI is trivial

/* Standard includes. */

#include

/* hardware include */
#include "lpc210x.h"

/* Scheduler includes. */

#include "FreeRTOS.h"

#include "queue.h"

#include "task.h"

/* Demo application includes. */

#include "spi.h"
#define spiCLEAR_VIC_INTERRUPT ( ( unsigned portLONG ) 0 )
#define SPI_QUEUE_LENGTH (1024) // in bytes

xQueueHandle xSPIQueueHandle; // globally accessible;

void vSPI_ISR_Wrapper( void ) __attribute__ ((naked));

void vSPI_ISR_Handler( void );

void vSPI_ISR_Wrapper( void )
{
----portSAVE_CONTEXT();
----vSPI_ISR_Handler();
----portRESTORE_CONTEXT();
}

void vSPI_ISR_Handler(void)
{
----unsigned portBASE_TYPE status, byte;
----portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

----status = SPI_SPSR;
----byte = SPI_SPDR;
----SPI_SPINT = 0x01; // clear the interrupt

----xQueueSendFromISR( xSPIQueueHandle, &byte,
---------------------- &xHigherPriorityTaskWoken );

----if( xHigherPriorityTaskWoken )

----{

--------portYIELD_FROM_ISR();

----}

----VICVectAddr = spiCLEAR_VIC_INTERRUPT;
}

#define CPHA (3)
#define CPOL (4)
#define MSTR (5)
#define LSBF (6)
#define SPIE (7)
#define SPI_DIVIDER (16)
#define SPI_IntEnBit (10)

void vStartSPI(void)
{
----PCB_PINSEL0 |= 0x00005500; // set proper bits for SPI
----SPI_SPCR = (1 << SPIE) | (0 << LSBF) |
---------------(0 << MSTR) | (0 << CPOL) | (1 << CPHA);
----SPI_SPCCR = SPI_DIVIDER;
----VICVectCntl2 = 0x0000002A; // set priority 2 for SPI
----VICVectAddr2 = (unsigned long) vSPI_ISR_Wrapper;
----VICIntEnable = (1 << SPI_IntEnBit);

----xSPIQueueHandle = xQueueCreate( SPI_QUEUE_LENGTH,
----------------(unsigned portBASE_TYPE ) sizeof( signed portCHAR ) );
}

You'll have to remove all the dashes. Yahoo strips blanks and that makes code look even worse.

This code is for the LPC2106 but it should be similar across the product line.

Richard

--- In l..., "rtstofer" wrote:

> ----VICVectAddr2 = (unsigned long) vSPI_ISR_Wrapper;
> ----VICIntEnable = (1 << SPI_IntEnBit);
>
> ----xSPIQueueHandle = xQueueCreate( SPI_QUEUE_LENGTH,
> ----------------(unsigned portBASE_TYPE ) sizeof( signed portCHAR )

> You'll have to remove all the dashes. Yahoo strips blanks and that makes code look even worse.

> Richard
>

I wondered where the dashes came from !!

I have seen other do this, but did not know why.
Thanks

don

Thanks for reply.

i am pasting the code whatever i have done.
/*FOLLOWING CODE IS THE MASTER CODE*/
#include "LPC2148.h"
#include "UART0.h"
#include "pll.h"
#include

void SPI_Init(void)
{

Tx_string("I am in INITIALIZATION part\n");

IO0DIR |=0x00000080; //(SSEL) pin p0.7 is used as output to select the slave(herae slave is another LPC 2148 board)

IO0CLR=0x00000080; //before the transfer of data and during the data transfer (SSEL) P0.7 made it LOW.

PINSEL0 |= 0x00001505; //selecting the pins for transmitter and receiver,SCK0,MISO and MOSI except SSEL

S0SPCCR = 0x0C; //clock rate for SPI bus 12MHZ/12 =1 MHZ.

Tx_string("I am in middle of INITIALIZATION part\n");

S0SPCR = 0xA8; // CPHA=1, CPOL=0, master mode, MSB first, interrupt enabled

Tx_string("I am in ending of INITIALIZATION part\n");

Tx_string("I am in ending 12 of INITIALIZATION part\n");

}

WORD32 SPI_SendAndReceive (WORD32 value)
{
WORD32 value1;

S0SPDR = value ; //Writing the data in to the data register

while(!(S0SPSR&0x80)) ; //waiting for SPIF bit be one to indicate the transfer complete
value1 = S0SPSR ;// read and ignore status
return S0SPDR;

}

int main(void)
{

PLL_init(); //initialization of PLL, i am using 12 MZ only,PLL settings not necessary here.

InitUart0(); //initialization of UART0,i am using 9600 baud rate.

Tx_string("I AM IN START OF MASTER\n");

SPI_Init(); // initilization of SPI BUS

Tx_string("INITIALIZATION IS OVER\n");

while(1)

{
WORD32 temp, temp2 ;

Tx_string("Press any key to transmit it's ASCII code to SPI.\n") ;

temp = Rx_char();

temp2 = SPI_SendAndReceive(temp) ;

printf("Sent 0x%02X to SPI, sen to 0x%02X to SPI \n\n", temp,temp2) ;

}
}
here Tx_String is the function to display the string on the hyperterminal is defined in UART code.

/*FOLLOWING CODE is the UART code*/
#include "LPC2148.h"

#define DESIRED_BAUDRATE 9600

#define CRYSTAL_FREQUENCY_IN_HZ 12000000
#define PCLK CRYSTAL_FREQUENCY_IN_HZ
#define DIVISOR (PCLK/(16*DESIRED_BAUDRATE))
void InitUart0(void)
{
/* U0LCR: UART0 Line Control Register
0x83: enable Divisor Latch access, set 8-bit word length,
1 stop bit, no parity, disable break transmission */
U0LCR=0x83;

/* VPBDIV: VPB bus clock divider
0x01: PCLK = processor clock */
VPBDIV=0x01;

/* U0DLL: UART0 Divisor Latch (LSB) */
U0DLL=DIVISOR&0xFF;

/* U0DLM: UART0 Divisor Latch (MSB) */
U0DLM=DIVISOR>>8;

/* U0LCR: UART0 Line Control Register
0x03: same as above, but disable Divisor Latch access */
U0LCR=0x03 ;

/* U0FCR: UART0 FIFO Control Register
0x05: Clear Tx FIFO and enable Rx and Tx FIFOs */
U0FCR=0x05 ;
}

char Tx_char(char ch)
{
if (ch=='\n')
{
//wait until Transmit Holding Register is empty
while (!(U0LSR&0x20)) {}

//then store to Transmit Holding Register
U0THR='\r';
}
//wait until Transmit Holding Register is empty
while (!(U0LSR&0x20)) {}

//then store to Transmit Holding Register
U0THR=ch;

return ch;
}

char Rx_char(void)
{
char ch;

//wait until there's a character to be read
while (!(U0LSR&0x01)) {}

//then read from the Receiver Buffer Register
ch=U0RBR;
return ch;
}

int IsUart0Ready ()
{
// returns non-zero if a char is received on UART0
return(U0LSR & 0x01) ;
}

int Tx_string(char *s)
{
int i=0;
while(s[i]!='\0')
{
Tx_char(s[i]);
i++;
}
return(i);
}

/*following code is the PLL CODE*/

#include "LPC2148.h" /* LPC21xx definitions */
//#include "type.h"
#include "pll.h"
/*****************************************************************************
PLL initialization function
****************************************************************************/
void PLL_init (void)
{
PLLCFG=0x00000060; // set multiplier and divider of PLL to give 12.00 MHz
PLLCON= 0x00000001; // enable PLL
PLLFEED= 0x000000AA; // update PLL registers with feed sequence
PLLFEED= 0x00000055;

while(!(PLLSTAT & 0x00000400)); // test lock bit
PLLCON= 0x00000003; // connect the PLL
PLLFEED= 0x000000AA; // update PLL registers with feed sequence
PLLFEED= 0x00000055;
VPBDIV = 0x00000001; // set the VLSI perpheral bus to 12.00 MHz
}
/*****************************************************************************
End Of File
*****************************************************************************/

In Master program,temp varable value is displaying hyperterminal but temp2 value is not displaying.it is displaying 0x00 whatever i am entered.So whatever i am entering,it is not storing in to the S0SPDR and i am not able to read the S0SPDR once transfer is completed.

PLZ help me,thanks in advance to all

--- In l..., Sutton Mehaffey wrote:
>
> Give us a little more information on what you have done so far. 'Help
> me' is not very informative.
>
> Sutton
>
> Raju N wrote:
> >
> >
> > Hi
> >
> > i am trying to estalish communication between tw0 LPC2148 uisng SPI
> > protocol.
> >
> > i read the manual also.
> >
> > but i am not able to write the data and read the data from/to SPI data
> > register(S0SPDR).
> >
> > i am not getting the solution for this?
> >
> > help me,thanks in advance
> > On Fri, Jul 3, 2009 at 8:40 PM, Bastiaan van Kesteren
> > >wrote:
> >
> > > On Friday 03 July 2009 11:21:26 pouettagada wrote:
> > > > I used a LPC2138 with an OS freeRTOS. I'd like to access to the
> > SPI bus
> > > > but I don't know how. I'm a beginner on it
> > > >
> > > > Could you tell me how can I do it?
> > > >
> > > > Have you some examples? some tutorials?
> > >
> > > 'The Insider's Guide To The Philips ARM7-Based Microcontrollers'
> > tells the
> > > basics, NXP has an appnote with some code (to acces an SD card, i
> > think).
> > >
> > > Use google, they are both easy to find.
> > >
> > > Start without FreeRTOS, just the basics. Once that works, you might
> > need to
> > > do
> > > some more work if you want to access the SPI interface from multiple
> > tasks,
> > > but that's a whole other question.
> > >
> > > Greetings,
> > > -bas
> > >
> > >
> > >
> > >
> > >
the output of following pasted code is given below.
Press any key to transmit it's ASCII code to SPI.
Sent 0x61 to SPI, sen to 0x00 to SPI

Press any key to transmit it's ASCII code to SPI.
Sent 0x62 to SPI, sen to 0x00 to SPI

Press any key to transmit it's ASCII code to SPI.
Sent 0x63 to SPI, sen to 0x00 to SPI
Just look at closely.first i entered character a,it is displayed 0x61
,but value of temp2 after storing the data ,is not displaying as 0x61
but here it is displaying the 0x00.Hence i conclude that,whatever i am
storing the data in to S0SPDR is not storing and iam not able to read
the data from SOSPDR.
--- In l..., "raju_nem" wrote:
>
> Thanks for reply.
>
> i am pasting the code whatever i have done.
> /*FOLLOWING CODE IS THE MASTER CODE*/
> #include "LPC2148.h"
> #include "UART0.h"
> #include "pll.h"
> #include void SPI_Init(void)
> {
>
> Tx_string("I am in INITIALIZATION part\n");
>
> IO0DIR |=0x00000080; //(SSEL) pin p0.7 is used
as output to select the slave(herae slave is another LPC 2148 board)
>
> IO0CLR=0x00000080; //before the transfer of
data and during the data transfer (SSEL) P0.7 made it LOW.
>
> PINSEL0 |= 0x00001505; //selecting the pins for
transmitter and receiver,SCK0,MISO and MOSI except SSEL
>
> S0SPCCR = 0x0C; //clock rate for SPI bus
12MHZ/12 =1 MHZ.
>
> Tx_string("I am in middle of INITIALIZATION part\n");
>
> S0SPCR = 0xA8; // CPHA=1, CPOL=0, master
mode, MSB first, interrupt enabled
>
> Tx_string("I am in ending of INITIALIZATION part\n");
>
> Tx_string("I am in ending 12 of INITIALIZATION part\n");
>
> }
>
> WORD32 SPI_SendAndReceive (WORD32 value)
> {
> WORD32 value1;
>
> S0SPDR = value ; //Writing the data in to the data register
>
> while(!(S0SPSR&0x80)) ; //waiting for SPIF bit be one to
indicate the transfer complete
> value1 = S0SPSR ;// read and ignore status
> return S0SPDR;
>
> }
>
> int main(void)
> {
>
> PLL_init(); //initialization of PLL, i am using 12 MZ only,PLL
settings not necessary here.
>
> InitUart0(); //initialization of UART0,i am using 9600 baud rate.
> Tx_string("I AM IN START OF MASTER\n");
>
> SPI_Init(); // initilization of SPI BUS
>
> Tx_string("INITIALIZATION IS OVER\n");
>
> while(1)
>
> {
> WORD32 temp, temp2 ;
>
> Tx_string("Press any key to transmit it's ASCII code to SPI.\n") ;
>
> temp = Rx_char();
> temp2 = SPI_SendAndReceive(temp) ;
>
> printf("Sent 0x%02X to SPI, sen to 0x%02X to SPI \n\n", temp,temp2) ;
>
> }
> }
> here Tx_String is the function to display the string on the
hyperterminal is defined in UART code.
>
> /*FOLLOWING CODE is the UART code*/
> #include "LPC2148.h"
>
> #define DESIRED_BAUDRATE 9600
>
> #define CRYSTAL_FREQUENCY_IN_HZ 12000000
> #define PCLK CRYSTAL_FREQUENCY_IN_HZ
> #define DIVISOR (PCLK/(16*DESIRED_BAUDRATE))
> void InitUart0(void)
> {
> /* U0LCR: UART0 Line Control Register
> 0x83: enable Divisor Latch access, set 8-bit word length,
> 1 stop bit, no parity, disable break transmission */
> U0LCR=0x83;
>
> /* VPBDIV: VPB bus clock divider
> 0x01: PCLK = processor clock */
> VPBDIV=0x01;
>
> /* U0DLL: UART0 Divisor Latch (LSB) */
> U0DLL=DIVISOR&0xFF;
>
> /* U0DLM: UART0 Divisor Latch (MSB) */
> U0DLM=DIVISOR>>8;
>
> /* U0LCR: UART0 Line Control Register
> 0x03: same as above, but disable Divisor Latch access */
> U0LCR=0x03 ;
>
> /* U0FCR: UART0 FIFO Control Register
> 0x05: Clear Tx FIFO and enable Rx and Tx FIFOs */
> U0FCR=0x05 ;
> }
>
> char Tx_char(char ch)
> {
> if (ch=='\n')
> {
> //wait until Transmit Holding Register is empty
> while (!(U0LSR&0x20)) {}
>
> //then store to Transmit Holding Register
> U0THR='\r';
> }
> //wait until Transmit Holding Register is empty
> while (!(U0LSR&0x20)) {}
>
> //then store to Transmit Holding Register
> U0THR=ch;
>
> return ch;
> }
>
> char Rx_char(void)
> {
> char ch;
>
> //wait until there's a character to be read
> while (!(U0LSR&0x01)) {}
>
> //then read from the Receiver Buffer Register
> ch=U0RBR;
> return ch;
> }
>
> int IsUart0Ready ()
> {
> // returns non-zero if a char is received on UART0
> return(U0LSR & 0x01) ;
> }
>
> int Tx_string(char *s)
> {
> int i=0;
> while(s[i]!='\0')
> {
> Tx_char(s[i]);
> i++;
> }
> return(i);
> }
>
> /*following code is the PLL CODE*/
>
> #include "LPC2148.h" /* LPC21xx definitions */
> //#include "type.h"
> #include "pll.h"
>
/***********************************************************************\
******
> PLL initialization function
>
************************************************************************\
****/
> void PLL_init (void)
> {
> PLLCFG=0x00000060; // set multiplier and divider of PLL to give
12.00 MHz
> PLLCON= 0x00000001; // enable PLL
> PLLFEED= 0x000000AA; // update PLL registers with feed sequence
> PLLFEED= 0x00000055;
>
> while(!(PLLSTAT & 0x00000400)); // test lock bit
> PLLCON= 0x00000003; // connect the PLL
> PLLFEED= 0x000000AA; // update PLL registers with feed sequence
> PLLFEED= 0x00000055;
> VPBDIV = 0x00000001; // set the VLSI perpheral bus to 12.00 MHz
> }
>
/***********************************************************************\
******
> End Of File
>
************************************************************************\
*****/
>
> In Master program,temp varable value is displaying hyperterminal but
temp2 value is not displaying.it is displaying 0x00 whatever i am
entered.So whatever i am entering,it is not storing in to the S0SPDR and
i am not able to read the S0SPDR once transfer is completed.
>
> PLZ help me,thanks in advance to all
> --- In l..., Sutton Mehaffey sutton@ wrote:
> >
> > Give us a little more information on what you have done so far.
'Help
> > me' is not very informative.
> >
> > Sutton
> >
> >
> >
> > Raju N wrote:
> > >
> > >
> > > Hi
> > >
> > > i am trying to estalish communication between tw0 LPC2148 uisng
SPI
> > > protocol.
> > >
> > > i read the manual also.
> > >
> > > but i am not able to write the data and read the data from/to SPI
data
> > > register(S0SPDR).
> > >
> > > i am not getting the solution for this?
> > >
> > > help me,thanks in advance
> > > On Fri, Jul 3, 2009 at 8:40 PM, Bastiaan van Kesteren
> > > bastiaan@ >wrote:
> > >
> > > > On Friday 03 July 2009 11:21:26 pouettagada wrote:
> > > > > I used a LPC2138 with an OS freeRTOS. I'd like to access to
the
> > > SPI bus
> > > > > but I don't know how. I'm a beginner on it
> > > > >
> > > > > Could you tell me how can I do it?
> > > > >
> > > > > Have you some examples? some tutorials?
> > > >
> > > > 'The Insider's Guide To The Philips ARM7-Based Microcontrollers'
> > > tells the
> > > > basics, NXP has an appnote with some code (to acces an SD card,
i
> > > think).
> > > >
> > > > Use google, they are both easy to find.
> > > >
> > > > Start without FreeRTOS, just the basics. Once that works, you
might
> > > need to
> > > > do
> > > > some more work if you want to access the SPI interface from
multiple
> > > tasks,
> > > > but that's a whole other question.
> > > >
> > > > Greetings,
> > > > -bas
> > > >
> > > >
> > > >
> > > >
> > > >
Thanks for your reply

I had seen the insiders guide, but I don't understant how the example (exercise 22) works... The functions read and write use a pointer "buffer" but where point it?

And in the philips datasheet I don't find the addresses of the SPI registers.

I will find the appnote from NXP
--- In l..., Bastiaan van Kesteren wrote:
>
> On Friday 03 July 2009 11:21:26 pouettagada wrote:
> > I used a LPC2138 with an OS freeRTOS. I'd like to access to the SPI bus
> > but I don't know how. I'm a beginner on it
> >
> > Could you tell me how can I do it?
> >
> > Have you some examples? some tutorials?
>
> 'The Insider's Guide To The Philips ARM7-Based Microcontrollers' tells the
> basics, NXP has an appnote with some code (to acces an SD card, i think).
>
> Use google, they are both easy to find.
>
> Start without FreeRTOS, just the basics. Once that works, you might need to do
> some more work if you want to access the SPI interface from multiple tasks,
> but that's a whole other question.
>
> Greetings,
> -bas
>

I come back...

In fact, I'd like to use the SSP as a SPI bus. I've found appnote with example to use the SPI bus, but not with the pins that I use. appnote use the SPI interface and I'd like to use the SSP as a SPI...
(pins P0.17,18,19,20 )

How can I do it? Where can I found a full datasheet? I'm affraid that this information is not in the datasheet from NXP/Philips (no information how to configure ssp as spi, not information about registers to read value....)

I think I have just a "light" version of the datasheet

Thanks a lot

--- In l..., "pouettagada" wrote:
>
> Thanks for your reply
>
> I had seen the insiders guide, but I don't understant how the example (exercise 22) works... The functions read and write use a pointer "buffer" but where point it?
>
> And in the philips datasheet I don't find the addresses of the SPI registers.
>
> I will find the appnote from NXP
> --- In l..., Bastiaan van Kesteren wrote:
> >
> > On Friday 03 July 2009 11:21:26 pouettagada wrote:
> > > I used a LPC2138 with an OS freeRTOS. I'd like to access to the SPI bus
> > > but I don't know how. I'm a beginner on it
> > >
> > > Could you tell me how can I do it?
> > >
> > > Have you some examples? some tutorials?
> >
> > 'The Insider's Guide To The Philips ARM7-Based Microcontrollers' tells the
> > basics, NXP has an appnote with some code (to acces an SD card, i think).
> >
> > Use google, they are both easy to find.
> >
> > Start without FreeRTOS, just the basics. Once that works, you might need to do
> > some more work if you want to access the SPI interface from multiple tasks,
> > but that's a whole other question.
> >
> > Greetings,
> > -bas
>