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

📄 spi_sd.c

📁 WAV 数字输出播放器
💻 C
字号:
#include <p33FJ64GP306.h>
#include "delay.h"
#include "SPI_SD.h"

// This source handles SPI, and SD Card Command level.
// File structure is managed by upper layer.

BYTE temp;

void init_SPI(void)
{
	PORTGbits.RG9 = 1;
	TRISGbits.TRISG9 = 0;
	
	// setup the SPI peripheral
	SPI2STAT = 0x0;  // disable the SPI module (just in case)
	SPI2CON1 = 0x013E;
	// bit 12 DISSCK = 0. SCK enabled.
	
	// bit 11 DISSDO = 0. SDO enabled.
	// bit 10 MODE16 = 0. Byte(8bit) Mode.
	// bit 9  SMP = 0.    input sampled at middle of data output time.
	// bit 8  CKE = 1.    SPI Clock Edge is active to idle.
	
	// bit 7  SSEN = 0.   slave select is disabled.(master mode)
	// bit 6  CKP = 0.    Clock Polarity is, High/Active, Low/Idle.
	// bit 5  MSTEN = 1.  Master Mode.
	// bit 4-2  SPRE=111. Second Prescale bit = 1:1.
	// bit 1-0  PPRE=10.  Primary Prescale = 4:1.
	// SCK = Fcy 33.864MHz / 4 / 1 = 8.47MHz
	SPI2STAT = 0x8000; // enable the SPI module

	//Wait SD Card
	Delay_Us(10);
	SD_CLK();
	Delay_Us(10);
	
}

//send CLOCK for SD card, let it sample clock
void SD_CLK(void)
{
	int i;
	BYTE ret;
	
	PORTGbits.RG9 = 1;
	Delay8Tcy();
	for (i = 0; i < 100; i++)
	{
		ret = SPI_read(0);
	}
	PORTGbits.RG9 = 1;
}	

BYTE SD_InitializeCard(void)
{
	BYTE stat;
	DWORD Count;
	
	Count = 0;
	PORTGbits.RG9 = 0;
	Delay8Tcy();
	// index 0: GO_IDLE_STATE command
	stat = SD_CardCommand(0, 0);
	// repeat until get 0x01 (In Idle State) answer.
	while( (stat != 1) && (stat != 0xFF) )
	{
		stat = SD_CardCommand(0, 0);
		Count++;
		if ( Count > 8000)
		{
			return 1;	//failed
		}
	}
	
	// index 1: SEND_OP_COMMAND, card initializing
	// repeat until get 0x00 (In Idle State bit cleared).
	while ( stat == 1 )
	{
		Delay_Us(1);
		stat = SD_CardCommand(1, 0);
	}
	PORTGbits.RG9 = 1;
	
	return 0;
}	


BYTE SD_Read_Single_Block(LONG Address, BYTE * Buffer)
{
	BYTE stat;
	BYTE ret;
	int i;

	stat = 0;
	ret = 0;
	
	PORTGbits.RG9 = 0;
	
	//Send command (single read) and wait response
	stat = SD_Read_Single_Block_Phase1(Address);
	
	if (stat == 0)
	{
		//store return value to buffer
		for(i = 0; i < 512; i++)
		{
			*Buffer = SPI_read(0);
			Buffer++;	
		}
		ret = 0;

		stat = SPI_read(0);
		stat = SPI_read(0);
		
		//Check transaction finished
		for (i = 0; i < 800; i++)
		{
			stat = SPI_read(0);
			if (stat == 0xFF) break;
		}
	}
	else
	{ ret = 1; }

	return ret;			
}	

BYTE SD_Read_Single_Block_Phase1(LONG Address)
{
	int RetryCount;
	BYTE ret;
	int i;
	
	ret = 0;

	for (RetryCount = 0; RetryCount < 100; RetryCount++)
	{
		ret = SD_CardCommand(17,Address);
		if (ret == 0)
		{
			//Not ready. wait for Data token.
			for (i = 0; i < 5000; i++)
			{
				ret = SPI_read(0);
				
				if (ret == 0xFE) return 0;	//got token
			}	
		}
		else if (ret == 0xFE)
		{
			//Got Token.
			return 0;
		}
	}
		
	return 1; // can not opened.
}	


// Initialize SD Card to SPI Mode
BYTE SD_CardCommand(BYTE cmd, LONG Argument)
{
	BYTE ret;
	int i;

	//Confirm card nop, before send command
	// if no command sent, should return 0xFF.
	for (i = 0; i < 800; i++)
	{
		ret = SPI_read(0);
		if (ret == 0xFF) 
		{
			break;
		}
	}

	// failed. upper layer will handle.
	if (ret != 0xFF) return 1;

	// SD Card Command	
	SPI_write(0x40 | cmd,0);	//command, 0x40 + index
	SPI_write((Argument >> 24) & 0xFF,0);	//Argument 0
	SPI_write((Argument >> 16) & 0xFF,0);	//Argument 1
	SPI_write((Argument >>  8) & 0xFF,0);	//Argument 2
	SPI_write((Argument      ) & 0xFF,0);		//Argument 3
	SPI_write(0x95,0);	//CRC for GO_STATE_IDLE only. others, don't care

	// Some command take long time to answer.
	for (i = 0; i < 512; i++)
	{
		ret = SPI_read(0);
		if (ret == 0xFE) 
		{
			break;	//data token
		}
		if ( (ret & 0x80) == 0x00 )
		{
			break; 	//got response
		}
	}
		
	return ret;	
}	


void SPI_write(BYTE data, BYTE flag)
// data: to send. flag(SS): not used.
{
	
	temp = SPI2BUF;			// dummy read of the SPI1BUF register
							// to clear the SPIRBF flag
	SPI2BUF = data;			// write the data out to the SPI peripheral
	
	while(!SPI2STATbits.SPIRBF)
	{
		Nop(); 
	}
}

BYTE SPI_read(BYTE flag)
// retrun: read value. flag(SS): not used.
{
		
	temp = SPI2BUF;			// dummy read of the SPI1BUF register
							// to clear the SPIRBF flag
	SPI2BUF = 0xFF;			// write the data out to the SPI peripheral
		
	while(!SPI2STATbits.SPIRBF)
	{
		Nop(); 
	}
	
	temp = 0xFF & SPI2BUF;			// read result

	return temp;	
}	

⌨️ 快捷键说明

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