/*----------------------------------------------------------------------------
www.mcu123.com
--------------------------------------------------------------------------*/
#include <LPC214X.H> /* LPC214x definitions */
#include "type.h"
#include "spi_mmc.h"
BYTE MMCWRData[MMC_DATA_SIZE];
BYTE MMCRDData[MMC_DATA_SIZE];
BYTE MMCCmd[MMC_CMD_SIZE];
BYTE MMCStatus = 0;
/*
* SPI and MMC commands related modules.
*
*/
void SPI_Init( void )
{
DWORD portConfig;
BYTE i, Dummy;
/* Configure PIN connect block */
/* bit 32, 54, 76 are 0x10, bit 98 are 0x00
port 0 bits 17, 18, 19, 20 are SSP port SCK1, MISO1, MOSI1,
and SSEL1 set SSEL to GPIO pin that you will have the totoal
freedom to set/reset the SPI chip-select pin */
SSPCR1 = 0x00; /* SSP master (off) in normal mode */
portConfig = PINSEL1;
PINSEL1 = portConfig | 0x00A8;
IODIR0 = SPI_SEL; /* SSEL is output */
IOSET0 = SPI_SEL; /* set SSEL to high */
/* Set PCLK 1/2 of CCLK */
VPBDIV = 0x02;
//VPBDIV =0x00; //1/4
/* Set data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0,
and SCR is 15 */
SSPCR0 = 0x0707;
/* SSPCPSR clock prescale register, master mode, minimum divisor
is 0x02*/
SSPCPSR = 0x2;
/* Device select as master, SSP Enabled, normal operational mode */
SSPCR1 = 0x02;
for ( i = 0; i < 8; i++ )
{
Dummy = SSPDR; /* clear the RxFIFO */
}
return;
}
/*
* SPI Send a block of data based on the length
*/
void SPI_Send( BYTE *buf, DWORD Length )
{
BYTE Dummy;
if ( Length == 0 )
return;
while ( Length != 0 )
{
/* as long as TNF bit is set, TxFIFO is not full, I can write */
while ( !(SSPSR & 0x02) );
SSPDR = *buf;
/* Wait until the Busy bit is cleared */
while ( !(SSPSR & 0x04) );
Dummy = SSPDR; /* Flush the RxFIFO */
Length--;
buf++;
}
return;
}
/*
* SPI receives a block of data based on the length
*/
void SPI_Receive( BYTE *buf, DWORD Length )
{
DWORD i;
for ( i = 0; i < Length; i++ )
{
*buf = SPI_ReceiveByte();
buf++;
}
return;
}
/*
* SPI Receive Byte, receive one byte only, return Data byte
* used a lot to check the status.
*/
BYTE SPI_ReceiveByte( void )
{
BYTE data;
/* wrtie dummy byte out to generate clock, then read data from
MISO */
SSPDR = 0xFF;
/* Wait until the Busy bit is cleared */
while ( SSPSR & 0x10 );
data = SSPDR;
return ( data );
}
/************************** MMC Init *********************************/
/*
* Initialises the MMC into SPI mode and sets block size(512), returns
* 0 on success
*
*/
int mmc_init()
{
DWORD i;
/* Generate a data pattern for write block */
for(i=0;i<MMC_DATA_SIZE;i++)
{
MMCWRData[i] = i;
}
MMCStatus = 0;
IOSET0 = SPI_SEL; /* set SPI SSEL */
/* initialise the MMC card into SPI mode by sending 80 clks on */
/* Use MMCRDData as a temporary buffer for SPI_Send() */
for(i=0; i<10; i++)
{
MMCRDData[i] = 0xFF;
}
SPI_Send( MMCRDData, 10 );
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* send CMD0(RESET or GO_IDLE_STATE) command, all the arguments
are 0x00 for the reset command, precalculated checksum */
MMCCmd[0] = 0x40;
MMCCmd[1] = 0x00;
MMCCmd[2] = 0x00;
MMCCmd[3] = 0x00;
MMCCmd[4] = 0x00;
MMCCmd[5] = 0x95;
SPI_Send( MMCCmd, MMC_CMD_SIZE );
/* if = 1 then there was a timeout waiting for 0x01 from the mmc */
if( mmc_response(0x01) == 1 )
{
MMCStatus = IDLE_STATE_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* Send some dummy clocks after GO_IDLE_STATE */
IOSET0 = SPI_SEL; /* set SPI SSEL */
SPI_ReceiveByte();
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* must keep sending command until zero response ia back. */
i = MAX_TIMEOUT;
do
{
/* send mmc CMD1(SEND_OP_COND) to bring out of idle state */
/* all the arguments are 0x00 for command one */
MMCCmd[0] = 0x41;
MMCCmd[1] = 0x00;
MMCCmd[2] = 0x00;
MMCCmd[3] = 0x00;
MMCCmd[4] = 0x00;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send( MMCCmd, MMC_CMD_SIZE );
i--;
} while ( (mmc_response(0x00) != 0) && (i>0) );
/* timeout waiting for 0x00 from the mmc */
if ( i == 0 )
{
MMCStatus = OP_COND_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* Send some dummy clocks after SEND_OP_COND */
IOSET0 = SPI_SEL; /* set SPI SSEL */
SPI_ReceiveByte();
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* send mmc CMD16(SET_BLOCKLEN) to set the block length */
MMCCmd[0] = 0x50;
MMCCmd[1] = 0x00; /* 4 bytes from here is the block length */
/* LSB is first */
/* 00 00 00 10 set to 16 bytes */
/* 00 00 02 00 set to 512 bytes */
MMCCmd[2] = 0x00;
/* high block length bits - 512 bytes */
MMCCmd[3] = 0x02;
/* low block length bits */
MMCCmd[4] = 0x00;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send( MMCCmd, MMC_CMD_SIZE );
if( (mmc_response(0x00))==1 )
{
MMCStatus = SET_BLOCKLEN_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
IOSET0 = SPI_SEL; /* set SPI SSEL */
SPI_ReceiveByte();
return 0;
}
/************************** MMC Write Block ***************************/
/* write a block of data based on the length that has been set
* in the SET_BLOCKLEN command.
* Send the WRITE_SINGLE_BLOCK command out first, check the
* R1 response, then send the data start token(bit 0 to 0) followed by
* the block of data. The test program sets the block length to 512
* bytes. When the data write finishs, the response should come back
* as 0xX5 bit 3 to 0 as 0101B, then another non-zero value indicating
* that MMC card is in idle state again.
*
*/
int mmc_write_block(WORD block_number)
{
WORD varl, varh;
BYTE Status;
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* block size has been set in mmc_init() */
varl=((block_number&0x003F)<<9);
varh=((block_number&0xFFC0)>>7);
/* send mmc CMD24(WRITE_SINGLE_BLOCK) to write the data to
MMC card */
MMCCmd[0] = 0x58;
/* high block address bits, varh HIGH and LOW */
MMCCmd[1] = varh >> 0x08;
MMCCmd[2] = varh & 0xFF;
/* low block address bits, varl HIGH and LOW */
MMCCmd[3] = varl >> 0x08;
MMCCmd[4] = varl & 0xFF;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send(MMCCmd, MMC_CMD_SIZE );
/* if mmc_response returns 1 then we failed to get a 0x00
response */
if((mmc_response(0x00))==1)
{
MMCStatus = WRITE_BLOCK_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* Set bit 0 to 0 which indicates the beginning of the data block */
MMCCmd[0] = 0xFE;
SPI_Send( MMCCmd, 1 );
/* send data, pattern as 0x00,0x01,0x02,0x03,0x04,0x05 ...*/
SPI_Send( MMCWRData, MMC_DATA_SIZE );
/* Send dummy checksum */
/* when the last check sum is sent, the response should come back
immediately. So, check the SPI FIFO MISO and make sure the status
return 0xX5, the bit 3 through 0 should be 0x05 */
MMCCmd[0] = 0xFF;
MMCCmd[1] = 0xFF;
SPI_Send( MMCCmd, 2 );
Status = SPI_ReceiveByte();
if ( (Status & 0x0F) != 0x05 )
{
MMCStatus = WRITE_BLOCK_FAIL;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* if the status is already zero, the write hasn't finished
yet and card is busy */
if(mmc_wait_for_write_finish()==1)
{
MMCStatus = WRITE_BLOCK_FAIL;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
IOSET0 = SPI_SEL; /* set SPI SSEL */
SPI_ReceiveByte();
return 0;
}
/************************** MMC Read Block ****************************/
/*
* Reads a 512 Byte block from the MMC
* Send READ_SINGLE_BLOC
SD.rar_LPC2148 SD
版权申诉
148 浏览量
2022-09-21
07:51:22
上传
评论
收藏 48KB RAR 举报
weixin_42651887
- 粉丝: 76
- 资源: 1万+
最新资源
- 沈丘盛世龙门图纸符合规范化
- HM3400-VB一款N-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
- 基于python+streamlit联邦学习进行高校学生成绩预测研究python源码+项目说明+模型+数据.zip
- HM3400D-VB一款N-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
- HM3400B-VB一款N-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
- spring-boot示例
- 搜集火星资源.py
- JAR应用启动停止脚本化解决方案.zip
- 配合eclipse svn插件subclipse-4.3.4版本的javahl
- Bash脚本教程:如何优雅地停止JAR服务.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈