Hallo, was spricht denn gegen die Verwendung von SPI anstatt von shiftout. Das vereinfacht das ganz doch ganz erheblich. Und wenn man dann noch die fertigen Routinen von Bascom nutzt wirds noch einfacher.
Ich hänge mal meine Version der MMC-Routinen an die ich vor zwei Jahren geschrieben habe. Im zweiten Block mal die neue Version mit BASCOM-Bordmitteln.
Vielleicht hilfts dem ein oder anderem.

mfg.
Joachim

Code:
' ##############################################################################
' Connect AVR To MMC/SD with Bascom
'
' Copyright(c) 2005 Joachim Reiter
' based on code from Ulrich Radig
'
'
' Dieses Programm Ist Freie Software. Sie K�nnen Es Unter Den Bedingungen Der
' Gnu General Public License , Wie Von Der Free Software Foundation Ver�ffentlicht,
' Weitergeben Und / Oder Modifizieren , Entweder Gem�� Version 2 Der Lizenz Oder
' (nach Ihrer Option) Jeder Sp�teren Version.

' Die Ver�ffentlichung Dieses Programms Erfolgt In Der Hoffnung,
' Da� Es Ihnen Von Nutzen Sein Wird , Aber Ohne Irgendeine Garantie,
' Sogar Ohne Die Implizite Garantie Der Marktreife Oder Der Verwendbarkeit
' F�r Einen Bestimmten Zweck. Details Finden Sie In Der Gnu General Public License.
'
' Sie Sollten Eine Kopie Der Gnu General Public License Zusammen Mit Diesem
' Programm Erhalten Haben.
' Falls Nicht , Schreiben Sie An Die Free Software Foundation,
' Inc. , 59 Temple Place , Suite 330 , Boston , Ma 02111 -1307 , Usa.
' ##############################################################################
$regfile = "m32def.dat"
$crystal = 8000000
$baud = 19200

Const Attr_long_name = &H0F
Const Attr_read_only = &H01
Const Attr_hidden = &H02
Const Attr_system = &H04
Const Attr_volume_id = &H08
Const Attr_directory = &H10
Const Attr_archive = &H20

Config Portb = &B10110000
Mmc_miso Alias Portb.6
Mmc_mosi Alias Portb.5
Mmc_cs Alias Portb.4
Mmc_sck Alias Portb.7
Set Mmc_cs
Spsr = 0

Dim Direntry(32) As Byte 
Dim Dir_name(8) As Byte At Direntry Overlay                    ' 8 chars filename
Dim Dir_ext(3) As Byte At Direntry+&H08 Overlay                     ' 8 chars filename
Dim Dir_attr As Byte At Direntry+$0b Overlay                        ' file attributes RSHA, Longname, Drive Label, Directory
Dim Dir_dummy(10) As Byte At Direntry+$0c Overlay
Dim Dir_time As Word At Direntry+$16 Overlay                        ' creation time part in milliseconds
Dim Dir_date As Word At Direntry+$18 Overlay                        ' creation time
Dim Dir_cluster As Word At Direntry+$1a Overlay                     ' first cluster high word
Dim Dir_filesize As Long At Direntry+$1c Overlay
Dim Fat_adresse As Long
Dim Dir_adresse As Long
Dim Data_adresse As Long

Dim Buffer(512) As Byte
Dim Vbr_start As Long At Buffer+&H1C6 Overlay
Dim Bytespersektor As Word At Buffer+&H0B Overlay
Dim Sektorpercluster As Byte At Buffer+&H0D Overlay
Dim Reservedsektor As Byte At Buffer+&H0E Overlay
Dim Maxrootentry As Word At Buffer+&H11 Overlay
Dim Sektorprofat As Word At Buffer+&H16 Overlay


Dim Cmd(6) As Byte
Dim Count As Integer
Dim Count1 As Integer
Dim Timeout As Byte
Dim Timeout1 As Byte
Dim Tmp As Byte
Dim Anz_bytes As Word
Dim Fn_ergo As Byte
Dim Addr As Long
'Dim Tmpaddr As Long
Dim Databyte As Byte
Dim File_cluster As Word

Declare Sub Mmc_write_byte(databyte As Byte)
Declare Function Mmc_read_byte() As Byte
Declare Function Mmc_init() As Byte
Declare Function Mmc_write_command(cmd() As Byte) As Byte
Declare Function Mmc_write_sector(addr As Long) As Byte
Declare Sub Mmc_read_block(cmd() As Byte , Anz_bytes As Word)
Declare Sub Mmc_read_sector(byval Addr As Long)
Declare Sub Mmc_read_csd()
Declare Sub Mmc_read_cid()

Declare Sub Scandisk()
Declare Function Readfile(byval Cluster As Word) As Word
Declare Sub Readdir(byval Nr As Word)
Declare Sub Outbuffer()


Main:
  Print "Press any Key"
  Do
  Loop Until Inkey() <> 0

  Fn_ergo = Mmc_init()
  If Fn_ergo <> 0 Then
    Print "Keine Karte gefunden " ; Fn_ergo
    Goto Main
  End If

  Print "Karte gefunden"

  Call Scandisk
  Print "DIR :" ; Dir_adresse
  Print "FAT :" ; Fat_adresse

  Print "DATA:" ; Data_adresse


  Call Mmc_read_sector(dir_adresse )
  Call Outbuffer()

  For Count = 1 To 32
    Direntry(count) = Buffer(32 + Count)
  Next X
  For Count = 1 To 8
    Print Chr(dir_name(count));
  Next Count

  Print ".";
  For Count = 1 To 3
    Print Chr(dir_ext(count));
  Next Count
  Print "  " ; Dir_filesize ; "   " ; Dir_cluster
  File_cluster = Readfile(dir_cluster)
  Print "xxxxx:" ; File_cluster
  Call Outbuffer()

Goto Main

Sub Outbuffer()
  Local Otmp As Word
  Local Otmp1 As Byte
  Local Ocount As Byte
  Local Ocount1 As Byte

  For Ocount = 0 To 31
    Otmp = Ocount * 16
    Print Hex(otmp) ; "  ";
    For Ocount1 = 1 To 16
      Incr Otmp
      Print Hex(buffer(otmp)) ; " ";
    Next Ocount1
    Otmp = Ocount * 16
    For Ocount1 = 1 To 16
      Incr Otmp
      Otmp1 = Buffer(otmp)
      If Otmp1 < 32 Then Otmp1 = 46
      Print Chr(otmp1);
    Next Ocount1
    Print
  Next Ocount
  Print
End Sub

Goto Main

  Call Mmc_read_csd()
  For Count = 1 To 16
    Print Hex(buffer(count)) ; " ";
  Next X
  Print

  Input "Blocknummer " , Addr

  Goto Main
End

' Lese Directoryeintrag
Sub Readdir(byval Nr As Word)
  Local X As Byte
  Local Y As Byte
  Local Rcount As Byte
  Local Rtmp As Word

  Call Mmc_read_sector(dir_adresse)
  For X = 1 To 15
    Rtmp = X * 32
    ' Leereintrag, das wars dann
    If Buffer(rtmp + 1) = 0 Then Exit For
    ' Gel�schter Eintrag
    If Buffer(rtmp + 1) <> &HE5 Then
      For Count = 1 To 32
        Incr Rtmp
        Direntry(count) = Buffer(rtmp)
      Next Count
      For Count = 1 To 8
        Print Chr(dir_name(count));
      Next Count

     Print ".";
     For Count = 1 To 3
        Print Chr(dir_ext(count));
      Next Count
      Print "  " ; Dir_filesize
    End If

  Next X

End Sub



' liest Cluster von File aus und gibt n�chsten Cluster zur�ck
' FFFF als R�ckgabe = Ende des Files
Function Readfile(byval Cluster As Word) As Word

  Local Nextcluster As Word
  Local Fatblock As Long
  Local Fatadresse As Long
  Local Tcl As Long

  Print "bbbbbb"
  Fatblock=Cluster*2
  Fatadresse = Fatblock Mod Bytespersektor
  Fatblock = Fatblock / Bytespersektor
  Fatblock = Fatblock + Fatadresse
  Call Mmc_read_sector(fatblock)

  Print "ccccc" ; Fatblock ; " " ; Fatadresse
  NextCluster=Buffer(Fatadresse)*256
  NextCluster=Nextcluster+Buffer(Fatadresse+1)

  Call Mmc_read_sector(tcl)
  ' Offset wegen Dateianfang
  Cluster = Cluster - 2
  Cluster = Cluster * Sektorpercluster
  ' und zu Anfang dazumachen
  Cluster = Cluster + Data_adresse
  ' und auslesen
  Tcl = Cluster
Print "aaa:" ; Tcl ; "  " ; Nextcluster
  Call Mmc_read_sector(tcl)
Print "vvvvv"
  ' Naechsten Cluster zurueckgeben
  ReadFile=NextCluster
End Function


Sub Scandisk()
  Local Ltmp As Long

  Ltmp = 0
  ' Aus Sektor 0 an H1C6 Long auslesen = Volume-Boot Record
  Call Mmc_read_sector(ltmp )
  ' VBR lesen
  Ltmp = Vbr_start
  Call Mmc_read_sector(ltmp )

  Dir_adresse = 2 * Sektorprofat
  Dir_adresse = Dir_adresse + Ltmp
  Dir_adresse = Dir_adresse + Reservedsektor
  Fat_adresse = Ltmp + 1
  Data_adresse = Maxrootentry * 32
  Data_adresse = Data_adresse / Bytespersektor
  Data_adresse = Data_adresse + Dir_adresse

End Sub



Sub Mmc_write_byte(databyte As Byte)
  Spdr = Databyte
  Bitwait Spsr.spif , Set
End Sub


Function Mmc_read_byte() As Byte
  Spdr = &HFF
  Bitwait Spsr.spif , Set
  Mmc_read_byte = Spdr
End Function


' ############################################################################
' ###### Routine zur Initialisierung der MMC /SD - Karte (spi -mode)
' ############################################################################
Function Mmc_init() As Byte

  Config Portb = &B10110000
  Set Mmc_cs
  Spsr = 0
  Set Spcr.spe
  Set Spcr.mstr
  Set Spcr.spr0                                             ' CLK/128
  Set Spcr.spr1

  Set Mmc_cs                                                ' disable card

  ' Initialisiere MMC / SD - Karte in den SPI-Mode
  Databyte = &HFF
  For Count = 1 To 16                                       ' Sendet Min 74+ Clocks an die MMC/SD-Karte
    Call Mmc_write_byte(databyte)
  Next Count

  ' Sendet Kommando Cmd0 an MMC/SD-Kkarte
  Cmd(1) = &H40
  Cmd(2) = &H00
  Cmd(3) = &H00
  Cmd(4) = &H00
  Cmd(5) = &H00
  Cmd(6) = &H95
  Timeout = 0
  Do
    Fn_ergo = Mmc_write_command(cmd(1))
    Incr Timeout
    If Timeout > 200 Then
      Mmc_init = 1                                          ' Abbruch Bei Commando1
      Exit Function
    End If
  Loop Until Fn_ergo = 1

  Cmd(1) = &H41
  Cmd(2) = &HFF
  Timeout = 0
  Do
    Fn_ergo = Mmc_write_command(cmd(1))
    Incr Timeout
    If Timeout > 200 Then
      Mmc_init = 2                                          ' Abbruch Bei Commando 2
      Exit Function
    End If
  Loop Until Fn_ergo = 0

  ' SPI Bus auf maximale Ggeschwindigkeit
  Reset Spcr.spr0
  Reset Spcr.spr1
  Set Spsr.spi2x

  Set Mmc_cs                                                ' Set Mmc_chip_select To High(mmc / Sd -karte Inaktiv)
  Mmc_init = 0
End Function


' ############################################################################
' ###### Sendet ein Commando an die MMC/SD-Karte
' ############################################################################
Function Mmc_write_command(cmd() As Byte) As Byte

  Local Ldatabyte As Byte
  Ldatabyte = &HFF
  Local Ltimeout As Byte
  Ltimeout = 0


  ' Set Mmc_chip_select to high(MMC/SD-Karte Inaktiv)
  Set Mmc_cs

  ' Sendet 8 Clock Impulse
  Call Mmc_write_byte(ldatabyte)

  ' Set Mmc_chip_select to low(MMC/SD-Karte Aktiv)
  Reset Mmc_cs

  ' Sendet 6 Byte Commando
  For Count = 1 To 6
    Call Mmc_write_byte(cmd(count))
  Next Count

  Ldatabyte = &HFF
  ' Wartet Auf Ein G�ltige Antwort Von Der Mmc / Sd -karte
  While Ldatabyte = &HFF
    Ldatabyte = Mmc_read_byte()
    Incr Ltimeout
    If Ltimeout > 100 Then Exit While
  Wend

  Mmc_write_command = Ldatabyte
End Function


' ############################################################################
' ###### Routine Zum Schreiben Eines Blocks(512byte) Auf Die Mmc / Sd -karte
' ############################################################################
Function Mmc_write_sector(addr As Long) As Byte

  Local Tmpaddr As Long
  ' Sende Kommando Cmd24 zum Schreiben an MMC/SD-Kkarte
  Cmd(1) = &H58
  Cmd(2) = &H00
  Cmd(3) = &H00
  Cmd(4) = &H00
  Cmd(5) = &H00
  Cmd(6) = &HFF

  ' Die Adressierung Der Mmc / Sd -karte Wird In Bytes Angegeben,
  ' Addr Wird Von Blocks Zu Bytes Umgerechnet Danach Werden
  ' Diese In Das Commando Eingef�gt * /
  Shift Addr , Left , 9                                     ' Addr = Addr * 512

  Tmpaddr = Addr And &HFF000000
  Shift Tmpaddr , Right , 24
  Cmd(2) = Tmpaddr
  Tmpaddr = Addr And &H00FF0000
  Shift Tmpaddr , Right , 16
  Cmd(3) = Tmpaddr
  Tmpaddr = Addr And &H0000FF00
  Shift Tmpaddr , Right , 8
  Cmd(4) = Tmpaddr

  ' Sendet Commando Cmd24 An Mmc / Sd -karte(write 1 Block / 512 Bytes)
  Fn_ergo = Mmc_write_command(cmd(1))
  If Fn_ergo <> 0 Then Return

  ' Wartet Einen Moment Und Sendet Einen Clock An Die Mmc / Sd -karte
  For Count = 1 To 100
    Databyte = Mmc_read_byte()
  Next

  ' Sendet Start Byte An Mmc / Sd -karte
  Databyte = &HFE
  Call Mmc_write_byte(databyte)

  ' Schreiben Des Bolcks(512bytes) Auf Mmc / Sd -karte
  For Count = 1 To 512
    Call Mmc_write_byte(buffer(count))
  Next Count

  ' Crc -byte Schreiben
  Databyte = &HFF
  Call Mmc_write_byte(databyte)
  Call Mmc_write_byte(databyte)

  ' Wartet Auf Mmc / Sd -karte Busy
  Do
    Databyte = Mmc_read_byte()
  Loop Until Databyte = &HFF

  ' Set Mmc_chip_select To High(mmc / Sd -karte Inaktiv)
  Set Mmc_cs
  Mmc_write_sector = 0
End Function


' ############################################################################
' ###### Routine Zum Lesen Des Cid Registers Von Der Mmc / Sd -karte(16bytes)
' ############################################################################
Sub Mmc_read_block(cmd() As Byte , Anz_bytes As Word)

  ' Sendet Commando Cmd An Mmc / Sd -karte
  Fn_ergo = Mmc_write_command(cmd(1))
  If Fn_ergo <> 0 Then Return

  ' Wartet Auf Start Byte Von Der Mmc / Sd -karte(feh / Start Byte)
  Do
    Databyte = Mmc_read_byte()
  Loop Until Databyte = &HFE

  ' Lesen Des Bolcks(normal 512bytes) Von Mmc / Sd -karte
  For Count = 1 To Anz_bytes
    Buffer(count) = Mmc_read_byte()
  Next Count

  ' Crc -byte Auslesen
  Databyte = Mmc_read_byte()
  Databyte = Mmc_read_byte()

  ' Set Mmc_chip_select To High(mmc / Sd -karte Inaktiv)
  Set Mmc_cs
End Sub


' ############################################################################
' ###### Routine Zum Lesen Eines Blocks(512byte) Von Der Mmc / Sd -karte
' ############################################################################
Sub Mmc_read_sector(byval Addr As Long )

  Local Tmpaddr As Long
  ' Kommando 17 Zum Lesen Eines Blocks Von Der Mmc / Sd - Karte
  Cmd(1) = &H51
  Cmd(2) = &H00
  Cmd(3) = &H00
  Cmd(4) = &H00
  Cmd(5) = &H00
  Cmd(6) = &HFF

  ' Die Adressierung Der Mmc / Sd -karte Wird In Bytes Angegeben,
  ' Addr Wird Von Blocks Zu Bytes Umgerechnet Danach Werden
  ' Diese In Das Commando Eingef�gt * /
  Shift Addr , Left , 9                                     ' Addr = Addr * 512

  Tmpaddr = Addr And &HFF000000
  Shift Tmpaddr , Right , 24
  Cmd(2) = Tmpaddr
  Tmpaddr = Addr And &H00FF0000
  Shift Tmpaddr , Right , 16
  Cmd(3) = Tmpaddr
  Tmpaddr = Addr And &H0000FF00
  Shift Tmpaddr , Right , 8
  Cmd(4) = Tmpaddr
Print "READSEC  ";
  Anz_bytes = 512
  Call Mmc_read_block(cmd(1) , Anz_bytes)
Print "retuor"
End Sub


' ############################################################################
' ###### Routine Zum Lesen Des Cid Registers Von Der Mmc / Sd -karte(16bytes)
' ############################################################################
Sub Mmc_read_cid()
  ' Kommando 10 zum Lesen des CID
  Cmd(1) = &H4A
  Cmd(2) = &H00
  Cmd(3) = &H00
  Cmd(4) = &H00
  Cmd(5) = &H00
  Cmd(6) = &HFF

  Anz_bytes = 16
  Call Mmc_read_block(cmd(1) , Anz_bytes)
End Sub


' ############################################################################
' ###### Routine Zum Lesen Des Csd Registers Von Der Mmc / Sd -karte(16bytes)
' ############################################################################
Sub Mmc_read_csd()
  ' Kommando 9 zum Lesen des CSD
  Cmd(1) = &H49
  Cmd(2) = &H00
  Cmd(3) = &H00
  Cmd(4) = &H00
  Cmd(5) = &H00
  Cmd(6) = &HFF

  Anz_bytes = 16
  Call Mmc_read_block(cmd(1) , Anz_bytes)
End Sub
Und nun die neue Version mit der mmc-lib.
Code:
$regfile = "m32def.dat"
$crystal = 16000000
$baud = 9600
Baud = 9600

Dim Abuffer(512) As Byte
Dim Wsrampointer As Word

'-------------------------------------------------------------------------------
'                         Config_MMC.BAS
'               Config File for MMC Flash Cards Driver
'        (c) 2003-2005 , MCS Electronics / V�gel Franz Josef
'-------------------------------------------------------------------------------
' Place MMC.LIB in the LIB-Path of BASCOM-AVR installation
'
'Connection as following
'MMC    M128/M103
'1      MMC_CS PORTB.0
'2      MOSI PORTB.2
'3      GND
'4      +3.3V
'5      CLOCK PORTB.1
'6      GND
'7      MISO, PORTB.3

' you can vary MMC_CS on HW-SPI and all pins on SOFT-SPI, check settings
' ========== Start of user definable range =====================================

' you can use HW-SPI of the AVR (recommended) or a driver build in Soft-SPI, if
' the HW-SPI of the AVR is occupied by an other SPI-Device with different settings

' Declare here you SPI-Mode
' using HW-SPI:     cMMC_Soft = 0
' not using HW_SPI: cMMC_Soft = 1
Const Cmmc_soft = 0


' define Chip-Select Pin
Config Pinb.0 = Output                                      ' define here Pin for CS of MMC/SD Card
Max_cs Alias Portb.0
Set Max_cs

Config Pinb.1 = Output                                      ' define here Pin for CS of MMC/SD Card
Mmc_cs Alias Portb.1
Set Mmc_cs

' Define here SS Pin of HW-SPI of the CPU (f.e. Pinb.0 on M128)
Config Pinb.4 = Output                                      ' define here Pin of SPI SS
Spi_ss Alias Portb.4
Set Spi_ss                                                  ' Set SPI-SS to Output and High por Proper work of
                                                  ' SPI as Master

' HW-SPI is configured to highest Speed
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = high , Phase = 1 , Clockrate = 64 , Noss = 1
'Spsr = 1                                                    ' Double speed on ATMega128
Spiinit                                                     ' Init SPI

' ========== End of user definable range =======================================


' Error
Const Cperrdrivereset = 225                                 ' Error response Byte at Reset command
Const Cperrdriveinit = 226                                  ' Error response Byte at Init Command
Const Cperrdrivereadcommand = 227                           ' Error response Byte at Read Command
Const Cperrdrivewritecommand = 228                          ' Error response Byte at Write Command
Const Cperrdrivereadresponse = 229                          ' No Data response Byte from MMC at Read
Const Cperrdrivewriteresponse = 230                         ' No Data response Byte from MMC at Write
Const Cperrdrive = 231
Const Cperrdrivenotsupported = 232                          ' return code for DriveGetIdentity, not supported yet

Waitms 1                                                    ' Wait some time before initialising MMC/SD
Dim Gbdriveerror As Byte                                    ' General Driver Error register
Dim Gbdriveerrorreg As Byte                                 ' Driver load Error-Register of HD in case of error
Dim Gbdrivestatusreg As Byte                                ' Driver load Status-Register of HD on case of error
Dim Gbdrivedebug As Byte
$lib "MMC.LIB"                                              ' link driver library
$external _mmc

Dim I As Word
Dim Sectornr As Long
Wsrampointer = Varptr(abuffer(1))

Print
Input "Start?" , I
Gbdriveerror = Driveinit()                                  ' Init MMC/SD Card

Print "Init ";
Print Gbdriveerror

Do
  Print
  Input "Sector:" , Sectornr
  Gbdriveerror = Drivereadsector(wsrampointer , Sectornr)
  Print "Read" ; Gbdriveerror
  For I = 1 To 512
    Print Abuffer(i) ;
    Print " ";
  Next I
  Waitms 1000
Loop

End                                                         'end program