
#include <D:\cc5\16F877.H>
// Speihersutz121345=aus,Debug11=aus,ProgrammFlash9=an,EEpromRead8=an,NiendervoltProgr7=aus
// NiederVoltReset6=an,EinschaltTimer3=an,WachDogTimer2=aus,Oszilator01=XC
#pragma config |= 0b.11.111101.11.00.10

#pragma bit CS @ PORTC.2 	//Ausgang für Chip Select
#pragma bit SCK @ PORTC.3 	//Ausgang Clock
#pragma bit SDO @ PORTC.5 	//Ausgang Daten Output
#pragma bit SDI @ PORTC.4 	//Eingang Daten Input

#pragma origin 100			// Ab Adresse 100 im Programmspeicher
//*********************************************************************

void InitUSART()
{
BRGH=1;			// Hoche Gechwindigkeit fuer Datenuebertragung
//SPBRG=129;	// (9600   baud @ 20MHz input clock)
//SPBRG=64;		// (19200  baud @ 20MHz input clock)
//SPBRG=32;		// (38400  baud @ 20MHz input clock)
SPBRG=10;		// (115200 baud @ 20MHz input clock)
SPEN = 1; 		// Set_Serial_Pins;
SYNC = 0;		// Set_Async_Mode;
TX9 = 0; 		// Set_8bit_Tx;
RX9 = 0; 		// Set_8bit_Rx;
CREN = 1; 		// Enable_Rx;
TXEN = 1; 		// Enable_Tx;
RCIE=0;   		// Rx Interrupt aus
}
//**********************************************************************

void SerString(const char *str)	//Ein String seriell senden
{
char ps;
ps = *str;		// Pointer auf start des Strings ins ps
while(ps>0)		// Pruefen ob String zu ende ist
	{
	str++;				// Pointer auf nexte Zeihen erhoehen
	if (ps== 0) break;	// Pruefen ob String zu ende ist
	while(!TXIF);   	// Pruefen ob register TXREG leher ist
	TXREG =ps ;			// Datenbyte senden
    ps = *str;			// Inhalt des ponters ins ps
	}
}
//********************************************************************

char SPI(char out)		// SPI-Softwaremaesig Frequenz etwa 620 kHz
{
char in,i;
for (i=0;i<8;i++)
	{
	nop2();
	SCK=0;				// Abfahlende Flanke des Clocks
	nop();
	SDO=out.7;			// Daten vorbereiten
	nop();
	out=out<<1;
	nop2();				// Zeit lassen fuer Datenvorbereitung bei Slawe
	in=in<<1;
	SCK=1;				// Steigende Flanke des Clocks
	nop();
	in.0=SDI;			// Daten Einlesen
	}
return in;
}
//**********************************************************************

char Command(char befF,uns16 AdrH,uns16 AdrL,char befH )
{						// Ein Befehl zum MMC senden
char a;
SPI(0xFF);
SPI(befF);
SPI(AdrH.high8);
SPI(AdrH.low8);
SPI(AdrL.high8);
SPI(AdrL.low8);
SPI(befH);
SPI(0xFF);
return SPI(0xFF);		// Response als Rueckgabewert
}
//**************************************************************************

bit MMC_Init()
{
CS=1;		// MMC-Disabled

char i;		// Variablen

//MMC in SPI-Modus starten, Reset
for(i=0; i < 10; i++)SPI(0xFF);		// 10*8=80 mal takten
CS=0;								// MMC-Enabled

// CMD0
if (Command(0x40,0,0,0x95) !=1)goto Fehler ; 	// Reset

st:
// CMD1
if (Command(0x41,0,0,0xFF) !=0) goto st ;		// CMD1 solange wiederholen
/*
// CID auslesen
if (Command(0x4A,0,0,0xFF) !=0) goto Fehler;	// Karten ID nummer
for(i=0; i < 20; i++)
{
while(!TXIF);
TXREG =SPI(0xFF);
}

// CSD auslesen									// Kartenpezifische Daten
if (Command(0x49,0,0,0xFF) !=0) goto Fehler;
for(i=0; i < 20; i++)
{
while(!TXIF);
TXREG =SPI(0xFF);
}
*/
// Set Lenge (Default ist 512 Byte)
//if (Command(0x50,0,16,0xFF) !=0) goto Fehler;	// 16 Byte-Mode für Lesen

return 1;
Fehler:
return 0;
}
//**************************************************************************

void main(void)
{
INTCON=0;				// Interrupts aus
ADCON1=0x6;				// PortA Digital
TRISC=0b.1101.0011;		// sck rc3-0, sdo rc5-0, CS rc2-0.
TRISB=0b.0000.0010;   	// RB2>TX, RB1<RX
uns16 i;				// Variable 0...65535
InitUSART();			// Serielle Datenuebertragung Initialisieren
SerString("Ich bin ON ");					// Startmeldung

if (MMC_Init()) SerString("MMC ON ");		// MMC Initialisieren und Meldung fals OK!
//**********************************************************************

// Lesen  512 Byte-mode
if (Command(0x51,0,512,0xFF) !=0) SerString("Lese_resp_Fehler");
while(SPI(0xFF) != 0xFE);		// Warten auf 0xFE,anfang jeder Datenuebertragung
for(i=0; i < 512; i++)
	{
	while(!TXIF);   			// Pruefen ob register TXREG leher ist
	TXREG =SPI(0xFF);			// Datenbyte senden
	}
SPI(0xFF);						// Am ende 2 Byte's ohne Bedeutung
SPI(0xFF);
//************************************************************************


// Schreiben  512 Byte-Mode
if (Command(0x58,0,512,0xFF) !=0) SerString("Schreib_resp_Fehler ");
SPI(0xFF);
SPI(0xFF);
SPI(0xFE);
for(i=0; i < 512; i++)
	{
	SPI('K');
	}
SPI(255);						// Am ende 2 Byte's ohne Bedeutung senden
SPI(255);
i=SPI(0xFF);
i &=0b.0001.1111;
if (i != 0b.0000.0101) SerString("Schreib_Fehler ");
while(SPI(0xFF) !=0xFF);		// warten auf ende des Busy -zustandes.

//**********************************************************************
while(1);				//hier bleibt Programm stehen
}

