Version:0.9 StartHTML:0000000105 EndHTML:0000034604 StartFragment:0000001153 EndFragment:0000034588 Untitled
{*************************************
***            MMC/SD-LIB          ***
**************************************
***     Autor: Ulrich Radig        ***
***    Übersetzung in Pascal:      ***
***       Marco Bajerski           ***
**************************************
***     Email: marco@soft-land.de  ***
**************************************}

// PB7 SCK Output
// PB6 SDI Input
// PB5 SDO Output
// PB4 CS  Output

program SD_Lib;
var
buffer : array[512] of byte;

Procedure SD_Disable;
begin
setbit(PORTB,4);      //Chipselect auf High
end;

Procedure SD_Enable;
begin
ClearBit(PORTB,4);      //Chipselect auf Low
end;

//*********************************
//**   Byte an die Karte senden  **
//*********************************
Procedure SD_Send_Byte(data: byte);
begin
SPDR := data;
while testbit(SPSR,7) <> 1 do begin
delay_ms(3);

SPDR := data;
end;
SetBit(PORTB,5); //DO wieder auf High
end;

//*********************************
//**   Byte von der Karte lesen  **
//*********************************
function SD_Read_Byte:byte;
begin
SPDR:=0xff;
while testbit(SPSR,7) <> 1 do begin
end;
result:=SPDR;
end;

//*********************************
//** Komando an die Karte senden **
//*********************************
function SD_Send_Cmd(var cmd: array[6] of byte):byte;
var
temp : byte;
i : byte;
timeout : integer;
str : string[8];
begin
temp := 0xff;
timeout := 0;
SD_Disable;  //Chipselect auf High (Karte inaktiv)
SD_Send_Byte(0xff);
SD_Enable;   //Chipselect auf low (Karte aktiv)
//Sendet 6 Byte Befehl
for i:=0 to 6 do begin
SD_Send_Byte(cmd[i]);
end;
//Auf antwort der MMC warten

while temp = $ff do begin
temp := SD_Read_Byte;
inc(timeout);
if timeout > 500 then begin
result:=temp;
exit;
end;
end;
result:=temp;
bytetostr(SPDR,str);
usart1_write_text(str);
end;

//*********************************
//**   Karte initialisieren      **
//*********************************
function SD_Init:byte;

var
i : Byte;
timeout : integer;
command : array[6] of byte;
begin
command[0] := 0x40;
command[1] := 0x00;
command[2] := 0x00;
command[3] := 0x00;
command[4] := 0x00;
command[5] := 0x95;

timeout := 0;


{ClearBit(DDRB,6);
SetBit(DDRB,7);
SetBit(DDRB,5);
SetBit(DDRB,4);
SetBit(DDRB,3);
SetBit(PORTB,7);}
{DDRB.5 := 1;
DDRB.4 := 1;
DDRB.3 := 1; }
DDRB := %10111000;
PORTB.4:=1 ;

delay_ms(10);

//SPI-Bus aktivieren clock durch 128 geteilt
setbit(SPCR, 6); //SPE
clearbit(SPCR, 5);   //DORD
setbit(SPCR, 4);   //MSTR
clearbit(SPCR, 3);   //CPOL
clearbit(SPCR, 2);   //CPHA
setbit(SPCR, 0);   //SPR0
setbit(SPCR, 1);   //SPR1
clearbit(SPSR, 0);  //SPI2X

for i:=0 to 14 do begin
//Sendet min 74 Clocks an die Karte
SD_Send_Byte(0xff);
//Sendet Commando CMD0 an MMC/SD-Karte
end;

usart1_write_text('16 Commands gesendet ');

while SD_Send_CMD(command) <> 1 do begin
inc(timeout);
if timeout > 200 then begin
SD_Disable;
result := 1; // Timeout Fehlercode 1
usart1_write_text('Timeout1');
if result=1 then begin
SD_Disable;
exit;
end;
end;
end;
 usart1_write_text(' COmmand2 ');
timeout := 0;
command[0] := 0x41;
command[5] := 0xFF;
while SD_Send_CMD(command)<> 0 do begin
if timeout > 400 then begin
SD_Disable;
result := 2; // Timeout Fehlercode 2
usart1_write_text('Timeout2');
if result=2 then begin
SD_Disable;
exit;
end;
end;
end;
//SPI auf Highspeed setzen
clearBit(SPCR, 0);
SetBit(SPCR, 1);
Setbit(SPSR,0);
SD_Disable;
result:=0;
usart1_write_text('ende');
end;

//******************************************
//** Routine zum lesen eines Blocks       **
//******************************************
procedure SD_Read_Block(var cmd : array[6] of byte; bytes:integer);
var
i : integer;
timeout : integer;
begin


if sd_send_CMD(cmd) <> 0  then begin
return;
end;

while sd_read_byte <> 0xfe do begin
end;

for i := 0 to bytes-1 do begin
buffer[i]:=sd_read_byte;
end;

sd_read_byte;
sd_read_byte;
SD_Disable;
end;

//******************************************
//** Routine zum lesen des CID Registers  **
//******************************************
procedure SD_Read_CID;
var
cmd : array[6] of byte;
begin
cmd[0] := 0x4A;
cmd[1] := 0x00;
cmd[2] := 0x00;
cmd[3] := 0x00;
cmd[4] := 0x00;
cmd[5] := 0xFF;
SD_Read_Block(cmd,16);
end;
///////////////////////////////////////////////////////////////////////////////
//Test-Procedures
procedure CID_Ausgabe;
var
i : byte;
str : string[4];
begin
i:=0;
SD_Read_CID;
for i:=0 to 15 do begin
bytetohex(buffer[i],str);
usart1_write_text(str);
end;
end;

Procedure read_sector;
var
cmd : array[6] of byte;
i:integer;
str:string[20];
begin
cmd[0] := 0x51;
cmd[1] := 0x00;
cmd[2] := 0x00;
cmd[3] := 0x200;
cmd[4] := 0x00;
cmd[5] := 0xFF;
SD_Read_Block(cmd,512);

for i:=0 to 511 do begin
bytetohex(buffer[i],str);
usart1_write_text(str);
end;
end;

//Main
var x:integer;
begin
usart1_init(9600);
for x:=0 to 511 do begin

buffer[x]:=0;
end;
Usart1_write_Text('-->While-Einsprung<--');
while SD_Init <> 0 do begin
Usart1_write_Text('...suche...');
end;
Usart1_write_Text('MMC-Initialisiert');
Usart1_write_Text('CID:');
CID_Ausgabe;
Usart1_write_Text('Sektor0:');
read_sector;
end.