⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc2000_spi.c

📁 基于lpc2148(arm7)的wav音乐格式播放器的设计
💻 C
字号:
/*****************************************************************************\
*              efs - General purpose Embedded Filesystem library              *
*          --------------------- -----------------------------------          *
*                                                                             *
* Filename : lpc2000_spi.c                                                    *
* Description : This file contains the functions needed to use efs for        *
*               accessing files on an SD-card connected to an LPC2xxx.        *
*                                                                             *
* This program is free software; you can redistribute it and/or               *
* modify it under the terms of the GNU General Public License                 *
* as published by the Free Software Foundation; version 2                     *
* of the License.                                                             *
                                                                              *
* This program is distributed in the hope that it will be useful,             *
* but WITHOUT ANY WARRANTY; without even the implied warranty of              *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
* GNU General Public License for more details.                                *
*                                                                             *
* As a special exception, if other files instantiate templates or             *
* use macros or inline functions from this file, or you compile this          *
* file and link it with other works to produce a work based on this file,     *
* this file does not by itself cause the resulting work to be covered         *
* by the GNU General Public License. However the source code for this         *
* file must still be made available in accordance with section (3) of         *
* the GNU General Public License.                                             *
*                                                                             *
* This exception does not invalidate any other reasons why a work based       *
* on this file might be covered by the GNU General Public License.            *
*                                                                             *
*                                                    (c)2005 Martin Thomas    *
\*****************************************************************************/

/*****************************************************************************/
#include "interfaces/lpc2000_spi.h"
#include "interfaces/sd.h"
#include "config.h"
/*****************************************************************************/

#ifndef HW_ENDPOINT_LPC2000_SPINUM
#error "HW_ENDPOINT_LPC2000_SPINUM has to be defined in config.h"
#endif

// LPC2103/2/1 ### SSP ### ("SPI1")

// SSPCR0  Bit-Definitions
#define CPOL    6
#define CPHA    7
// SSPCR1  Bit-Defintions
#define SSE     1
#define MS      2
#define SCR     8
// SSPSR  Bit-Definitions
#define TNF     1
#define RNE     2
#define BSY		4

#define SPI_SCK_PIN    14   /* Clock       P0.14  out */
#define SPI_MISO_PIN   19   /* from Card   P0.19  in  */
#define SPI_MOSI_PIN   20   /* to Card     P0.20  out */
/* Card-Select P0.20 - GPIO out during startup
   Function 03 during normal operation */
#define SPI_SS_PIN	   21   

#define SPI_PINSEL0    PINSEL0
#define SPI_SCK_FUNCBIT   28

#define SPI_PINSEL     PINSEL1
#define SPI_MISO_FUNCBIT  6
#define SPI_MOSI_FUNCBIT  8
#define SPI_SS_FUNCBIT    10

#define SPI_PRESCALE_REG  SSPCPSR

// Note: SD Cards are only specified to operate up to 25MHz.
//
// If processor clock is 70MHz, then prescaler of 4 gives us:
// 70MHz / 4 = 17.4MHz, which is as close as we can get.
// 70MHz / 4 = 17.4MHz, which is as close as we can get.
#define SPI_PRESCALE_MIN  4 /* must be an even numbered value */
//#define SPI_PRESCALE_MIN  2 /* must be an even numbered value */

esint8 if_initInterface(hwInterface* file, eint8* opts)
{
	euint32 sc;

	if_spiInit(file); /* init at low speed */
	
	if(sd_Init(file)<0)	{
		DBG((TXT("Card failed to init, breaking up...\n")));
		return(-1);
	}
	if(sd_State(file)<0){
		DBG((TXT("Card didn't return the ready state, breaking up...\n")));
		return(-2);
	}
	
	// file->sectorCount=4; /* FIXME ASAP!! */
	
	sd_getDriveSize(file, &sc);
	file->sectorCount = sc/512;
	if( (sc%512) != 0) {
		file->sectorCount--;
	}
	DBG((TXT("Drive Size is %lu Bytes (%lu Sectors)\n"), sc, file->sectorCount));

	 // increase speed after init
	SSPCR0 = ((8-1)<<0) | (0<<CPOL);
	if_spiSetSpeed(SPI_PRESCALE_MIN);
	// if_spiSetSpeed(100); // debug - slower
	
	DBG((TXT("Init done...\n")));
	return(0);
}
/*****************************************************************************/ 

esint8 if_readBuf(hwInterface* file,euint32 address,euint8* buf)
{
	return(sd_readSector(file,address,buf,512));
}
/*****************************************************************************/

esint8 if_writeBuf(hwInterface* file,euint32 address,euint8* buf)
{
	return(sd_writeSector(file,address, buf));
}
/*****************************************************************************/ 

esint8 if_setPos(hwInterface* file,euint32 address)
{
	return(0);
}
/*****************************************************************************/ 

// Utility-functions which does not toogle CS.
// Only needed during card-init. During init
// the automatic chip-select is disabled for SSP

static euint8 my_if_spiSend(hwInterface *iface, euint8 outgoing)
{
	euint8 incoming;

	while( !(SSPSR & (1<<TNF)) ) ;
	SSPDR = outgoing;
	while( !(SSPSR & (1<<RNE)) ) ;
	incoming = SSPDR;

	return(incoming);
}
/*****************************************************************************/ 

void if_spiInit(hwInterface *iface)
{
	euint8 i; 

	// setup GPIO
	SPI_IODIR |= (1<<SPI_SCK_PIN)|(1<<SPI_MOSI_PIN)|(1<<SPI_SS_PIN);
	SPI_IODIR &= ~(1<<SPI_MISO_PIN);
	
	// set Chip-Select high - unselect card
	UNSELECT_CARD();

	// reset Pin-Functions	
	PINSEL0 &= ~( (3<<SPI_SCK_FUNCBIT) );
	PINSEL1 &= ~( (3<<SPI_MISO_FUNCBIT) | (3<<SPI_MOSI_FUNCBIT) | (3<<SPI_SS_FUNCBIT) );

	DBG((TXT("spiInit for SSP/SPI1\n")));

	// setup Pin-Functions - keep automatic CS disabled during init
	PINSEL0 |= ( 2<<SPI_SCK_FUNCBIT );
	PINSEL1 |= (1<<SPI_MISO_FUNCBIT) | (1<<SPI_MOSI_FUNCBIT) | (0<<SPI_SS_FUNCBIT);

	// enable SPI-Master - slowest speed
	SSPCR0 = ((8-1)<<0) | (0<<CPOL) | (0x20<<SCR); //  (0xff<<SCR);
	SSPCR1 = (1<<SSE);
	
	// low speed during init
	if_spiSetSpeed(254); 

	/* Send 20 spi commands with card not selected */
	for(i=0;i<21;i++)
		my_if_spiSend(iface,0xff);

	// enable automatic slave CS for SSP
	SSPCR1 &= ~(1<<SSE); // disable interface
	PINSEL0 |= (2<<SPI_SCK_FUNCBIT);
	PINSEL1 |= ( (1<<SPI_MISO_FUNCBIT) | (1<<SPI_MOSI_FUNCBIT) | (1<<SPI_SS_FUNCBIT) );
	SSPCR1 |= (1<<SSE); // enable interface	
}
/*****************************************************************************/

void if_spiSetSpeed(euint8 speed)
{
	speed &= 0xFE;
	if ( speed < SPI_PRESCALE_MIN  ) speed = SPI_PRESCALE_MIN ;
	SPI_PRESCALE_REG = speed;
}

/*****************************************************************************/

euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
{
	euint8 incoming;

#if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
	SELECT_CARD();
	S0SPDR = outgoing;
	while( !(S0SPSR & (1<<SPIF)) ) ;
	incoming = S0SPDR;
	UNSELECT_CARD();
#endif

#if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
	// SELECT_CARD();  // done by hardware
	while( !(SSPSR & (1<<TNF)) ) ;
	SSPDR = outgoing;
	while( !(SSPSR & (1<<RNE)) ) ;
	incoming = SSPDR;
	// UNSELECT_CARD();  // done by hardware
#endif

	

	return(incoming);
}
/*****************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -