📄 spi.c
字号:
/*****************************************************************************
* spi.c: SPI C file for NXP LPC210x Family Microprocessors
*
* Copyright(C) 2006, NXP Semiconductor
* All rights reserved.
*
* History
* 2005.10.01 ver 1.00 Prelimnary version, first Release
*****************************************************************************/
#include "LPC210x.h" /* LPC21XX Peripheral Registers */
#include "type.h"
#include "irq.h"
#include "spi.h"
#include "i2c.h"
volatile DWORD SPI0Status = 0;
volatile DWORD TxCounter = 0;
static BYTE sSPI_Initialized = 0;
/*****************************************************************************
** Function name: SPI0_Handler
** Description: SPI0 interrupt handler
** Parameter: None
** Returned value: None
*****************************************************************************/
void SPI0_Handler (void) __irq
{
DWORD regValue;
S0SPINT = SPI0_INT_FLAG; /* Clear interrupt flag */
IENABLE; /* Handles nested interrupt */
regValue = S0SPSR;
if( regValue & WCOL )
{
SPI0Status |= SPI0_COL;
}
if( regValue & SPIF )
{
SPI0Status |= SPI0_TX_DONE;
TxCounter++;
}
IDISABLE;
VICVectAddr = 0; /* Acknowledge Interrupt */
} // SPI0_Handler
/*****************************************************************************
** Function name: SPI_Init
** Description: SPI port initialization routine
** Parameter: None
** Returned value: true or false; if the interrupt handler cannot be
** installed correctly, return false.
*****************************************************************************/
DWORD SPI_Init(void)
{
if(sSPI_Initialized)
return (TRUE);
PINSEL0 &= 0xFFFF00FF;
#if SPI_LPC2106
PINSEL0 |= 0x00005100; // Set P0.4 as SCK0 and P0.6 as MOSI; P0.7 as SSEL0
#else
PINSEL0 |= 0x00001100; // Set P0.4 as SCK0 and P0.6 as MOSI
#endif
IODIR |= SPI0_SSEL; // Set P0.7 as output
IOSET |= SPI0_SSEL; // Set P0.7 as High
S0SPCR = 0x00; // Reset SPI0 control register
S0SPCCR = 0x08; // SPI0 rate = PCLK/S0SPCCR = 15/8 = 1.875 MHz
#if INTERRUPT_MODE /* Interrupt mode */
if( install_irq( SPI0_INT, (void *)SPI0Handler ) == FALSE )
{
return (FALSE);
}
S0SPCR |= SPI0_SPIE | SPI0_MSTR; // CPOL = CPHA = 0, SPI master mode, MSB first, interrupt enabled
#else /* Polling mode */
S0SPCR |= SPI0_MSTR | SPI0_CPOL | SPI0_CPHA; // Configure SPI0 as SPI master mode, CPOL:'1' - SCK is active low, CPHA:'1' - Data sampled on second clock edge of SCK
#endif
sSPI_Initialized = 1;
return (TRUE);
} // SPI_Init
/*****************************************************************************
** Function name: SPI_DeInit
** Description: SPI Port de-initialization routine
** Parameter: None
** Returned value: true or false; if the interrupt handler cannot be
** uninstalled correctly, return false.
*****************************************************************************/
DWORD SPI_DeInit(void)
{
if(!sSPI_Initialized)
return (TRUE);
PINSEL0 &= 0xFFFF00FF;
/* Set SPI ports at non-operational state */
IODIR &= ~(SPI0_SCK | SPI0_MOSI | SPI0_SSEL); // Set P0.4(SCK0), P0.6(MOSI0) and P0.7(SSEL0) as input ports
#if INTERRUPT_MODE /* Interrupt mode */
if( uninstall_irq(SPI0_INT) == FALSE )
{
return (FALSE);
}
#endif
sSPI_Initialized = 0;
return (TRUE);
} // SPI_DeInit
/*****************************************************************************
** Function name: SPI_Send
** Description: This function sends a block of data to the SPI port, one
** byte at a time.
** Parameter: Buffer pointer; block length
** Returned value: None
*****************************************************************************/
void SPI_Send(BYTE *buf, DWORD Length)
{
DWORD i;
if(sSPI_Initialized)
{
if(Length == 0)
return;
for(i=0; i<Length; i++)
{
S0SPDR = (BYTE) *buf;
#if INTERRUPT_MODE /* Interrupt mode */
/* In the interrupt, there is nothing to be done if TX_DONE, SPI transfer
complete bit, is not set, so it's polling if the flag is set or not which
is being handled inside the ISR. Not an ideal example but show how the
interrupt is being set and handled. */
while( (SPI0Status & SPI0_TX_DONE) != SPI0_TX_DONE );
SPI0Status &= ~SPI0_TX_DONE;
#else /* Polling mode */
while( !(S0SPSR & SPIF) );
#endif
buf++;
}
}
} // SPI_Send
/*****************************************************************************
** Function name: SPI_Receive
** Description: This function will receive one byte of data from the SPI
** port. It waits until SPI transfer is completed before
** reading the data register to get the SPI data.
** Parameter: Buffer pointer
** Returned value: None
*****************************************************************************/
void SPI_Receive(BYTE *buf)
{
if(sSPI_Initialized)
{
/* Wait for transfer complete, SPIF bit set */
#if INTERRUPT_MODE /* Interrupt mode */
/* In the receive routine, there is nothing to be done if TX_DONE, or
SPI transfer complete bit, is not set, so it's polling if the flag is set
or not which is being handled inside the ISR. Not an ideal example but
show how the interrupt is being set and handled. */
while( (SPI0Status & SPI0_TX_DONE) != SPI0_TX_DONE );
SPI0Status &= ~SPI0_TX_DONE;
#else /* Polling mode */
while( !(S0SPSR & SPIF) );
#endif
*buf = S0SPDR;
}
} // SPI_Receive
/*****************************************************************************
** Function name: SPI_Config
** Description: This function allows the configuration of SPI settings, which
** includes:
** (1) SPI Clock Counter (S0SPCCR)
** (2) Clock phase (CPHA)
** (3) Clock polarity (CPOL)
** (4) LSB First (LSBF)
**
** I2C data format for SPI configuration:
**
** 1. I2C0RxBuffer[1] - Second byte of I2C Rx buffer
**
** - SPI Clock Counter configuration
** - Value must be an even number that is greater than or equal to 8
** - Size: 8 bits
**
** 2. I2C0RxBuffer[2] - Third byte of I2C Rx buffer
**
** - bits 3~7: Not used
** - bit 2: LSB First (LSBF) Control ('1': MSB first; '0': LSB first)
** - bit 1: Clock Polarity (CPOL) Control ('1': SCK active low; '0': SCK active high)
** - bit 0: Clock Phase (CPHA) Control ('1': Data sampled on first SCK clock edge; '0': Data sampled on second SCK clock edge)
**
** Parameter: None
** Returned value: None
*****************************************************************************/
void SPI_Config(BYTE *buf)
{
if(sSPI_Initialized)
{
/* Configuration of SPI clock counter */
if( !(*(buf+1) % 2) && (*(buf+1) >= 8) )
{
S0SPCCR = *(buf+1);
}
/* Configuration of SPI Clock Phase */
if( *(buf+2) & 1 )
S0SPCR |= SPI0_CPHA;
else
S0SPCR &= ~SPI0_CPHA;
/* Configuration of SPI Clock Polarity */
if( *(buf+2) & (1<<1) )
S0SPCR |= SPI0_CPOL;
else
S0SPCR &= ~SPI0_CPOL;
/* Configuration of SPI LSB First direction */
if( *(buf+2) & (1<<2) )
S0SPCR |= SPI0_LSBF;
else
S0SPCR &= ~SPI0_LSBF;
}
} // SPI_Config
/*****************************************************************************
** Function name: SPI_OnOff
** Description: This function allows the I2C host to enable or disable
** the SPI function. The I2C host is required to send an
** instruction byte to enable or disable the SPI function.
**
** SPI Enable/Disable instruction byte:
** - 0x00: Disable SPI function
** - 0x01: Enable SPI function
**
** Parameter: None
** Returned value: None
*****************************************************************************/
void SPI_OnOff(void)
{
if(I2C0RxBuffer[1] == 1)
SPI_Init();
else if(I2C0RxBuffer[1] == 0)
SPI_DeInit();
} // SPI_OnOff
/******************************************************************************
** End Of File
******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -