mmc bascom command
I have got a few requests for the BASCOM Code for interfacing MMC to AVR. So, I am posting it here.
It uses the hardware SPI of ATMEGA162.
I only use 212 bytes of each sector, you can modify it for 512 bytes.
For all the commands, store adr (address) and call the routine.
Readsector reads the sector specified in adr into indat
write sector writes Indat to specified adr.
No FAT support only direct reading and writing.
Refer to sandisk application note for further commands.
Use appropriate level converters if you run the micro at 5 volt as MMC only runs on 3.3 volts. A 100 pF bypass cap on the clock line works like wonder for intermittant init problems.
I havn't used this code since a long time. If anybody has corrections/modifications/suggestions pleas post it.
Regards.
Cs Alias Portb.4
Ddrb.1 = 1
Ddrb.4 = 1
Ddrb.5 = 1
Ddrb.6 = 0
Ddrb.7 = 1
Dim Indat(212) As Byte At 256
'MMC commnd
Dim Command(6) As Byte At 470 ' 358 '&H100
Dim Comm As Byte At 470 Overlay '358 &H100 Overlay
Dim Adr As Long At 471 Overlay '359&H101 Overlay
Dim Trail As Byte At 475 Overlay '363 &H105 Overlay
**************************************************************************
'**************************************************************************
'Spcr = &B01011100 'This is the MMC power spi
Spcr = &B01011101 'last 01 = f/16 00 =f/4
Spsr = 0
Declare Sub Getresp
Declare Sub Spiwait
Declare Sub Sendbyte
Declare Sub Sendcmd
Declare Sub Readbyte
Declare Sub Readsector
Declare Sub Writesector
Declare Sub Mmcinit
Declare Sub Cardformat()
Declare Sub Checkfat
Declare Sub Clearbuffer
Declare Sub Gpsinit
Declare Sub Query
Declare Sub Sendmsg
'Set Mmcpower
call mmcinit
do
'Here put all the commands for mmc.
loop
'======= SUB ROUTINES AND FUNCTIONS for MMC=======
'____________________________________________________________________
Sub Cardformat()
#if Debug = 1
Print #1 , "Formatting"
#endif
'mark the start sector
' Input #1 , "Start" , Adr
Adr = &H0000
Comm = &H40 + 35
Sendcmd
Aresp = 00
Getresp
#if Debug = 1
If Aresp <> Rbyte Then
Print #1 , "ADD1 error"
End If
#endif
'mark the end sector
' Input #1 , "end" , Adr
Adr = 15360000
'THIS IS 30,000 SECTORS AND 29,999 RECORDS.
Comm = &H40 + 36
Sendcmd
Getresp
#if Debug = 1
If Aresp <> Rbyte Then
Print #1 , "ADD2 error"
End If
#endif
'erase
Comm = &H40 + 38
Sendcmd
Getresp
If Aresp <> Rbyte Then
#if Debug = 1
Print #1 , "Format Failed"
#endif
Cls
Lcd "Format Error"
Lowerline
Lcd "Send for Repair"
Do
Loop
End If
'Busy check
#if Debug = 1
Print #1 , "Busy check"
#endif
Readbyte
While Rbyte = 0
Readbyte
Wend
#if Debug = 1
Print #1 , "free"
#endif
'Now formatting is done. write the signature in 0th sector
Div = "TOTAL SOLUTIONS."
Adr = 0
Writesector
'Format done
End Sub
'____________________________________________________________________
Sub Getresp()
Responsewait:
Readbyte
' for DEBUG
#if Debug = 1
Print #1 , "RES IS " ; Hex(rbyte) ; "," ; 'DEBUG
#endif
For I = 1 To 255
If Rbyte = Aresp Then
Goto Responsedone
End If
Readbyte
#if Debug = 1
Print #1 , Hex(rbyte) ; "," ; 'DEBUG
#endif
Next I
Responseerror:
#if Debug = 1
Print #1 , "Error in resp"
#endif
Responsedone:
End Sub
'____________________________________________________________________
Sub Spiwait()
Spiwait1:
'#if Debug = 1
' Print #1 , "W"
'#endif
sbis spsr,7
rjmp spiWAIT1
Dbyte = Spdr
End Sub
'____________________________________________________________________
Sub Sendbyte()
Spdr = Spichar
'#if Debug = 1
' Print #1 , "S"
'#endif
Spiwait
End Sub
'____________________________________________________________________
Sub Sendcmd()
Set Cs
Spichar = &HFF
Sendbyte
Reset Cs
'COMMAND
'COMMAND
Spichar = Command(1)
Sendbyte
Spichar = Command(5)
Sendbyte
Spichar = Command(4)
Sendbyte
Spichar = Command(3)
Sendbyte
Spichar = Command(2)
Sendbyte
Spichar = Command(6)
Sendbyte
End Sub
'____________________________________________________________________
Sub Readbyte()
Spichar = &HFF
'#if Debug = 1
' Print #1 , "R"
'#endif
Sendbyte
Rbyte = Spdr
End Sub
'____________________________________________________________________
Sub Readsector
'cmd17
Comm = &H40 + 17
Sendcmd
Aresp = &H00
Getresp
If Rbyte <> Aresp Then
#if Debug = 1
Print #1 , "error in read command"
#endif
Goto Readerror
End If
Aresp = &HFE
Getresp
If Rbyte <> Aresp Then
#if Debug = 1
Print #1 , "error in read command"
#endif
Goto Readerror
End If
' K = 0
For K = 1 To 212
Readbyte
Indat(k) = Rbyte
Next K
For K = 213 To 512
Readbyte
Next
' Print
Exit Sub
Readerror:
Cls
Lcd "READ PROBLEM"
Lowerline
Lcd "Send for Repair"
Do
Loop
End Sub
'____________________________________________________________________
Sub Writesector()
Comm = &H40 + 24
Sendcmd
Aresp = &H00
Getresp
If Aresp <> Rbyte Then
#if Debug = 1
Print #1 , "write command not accepted"
#endif
Goto Writeerror
End If
'now send fe
Reset Cs
Spichar = &HFE
Sendbyte
For K = 1 To 212
Spichar = Indat(k)
Sendbyte
Next K
For K = 213 To 512
Spichar = &HFF
Sendbyte
Next K
Spichar = &HFF
Sendbyte
Sendbyte
Readbyte
' Print
Dbyte = Rbyte And &H0F
#if Debug = 1
Print #1 , "the responce of write is Rbyte=" ; Bin(rbyte)
Print #1 , "Dbyte=" ; Bin(dbyte)
#endif
If Dbyte <> &H05 Then
#if Debug = 1
Print #1 , "write is unsuccessful"
#endif
Goto Writeerror
End If
Exit Sub
Writeerror:
'The problem is in writing! dont accept any more records.
Cls
Lcd "SAVE PROBLEM"
Lowerline
Lcd "Send for Repair"
Do
Loop
End Sub
'____________________________________________________________________
Sub Mmcinit()
#if Debug = 1
Print #1 , "initializing MMC"
#endif
Mmcinitdone = 0
Cmda = 0 : Cmdb = 0
Set Cs
'Spichar = &HFF
For I = 1 To 100
Readbyte
Next I
Reset Cs
'cmd0
Comm = &H40
Adr = &H00000000
Trail = &H95
'COMMAND
Spichar = Command(1)
Sendbyte
Spichar = Command(5)
Sendbyte
Spichar = Command(4)
Sendbyte
Spichar = Command(3)
Sendbyte
Spichar = Command(2)
Sendbyte
Spichar = Command(6)
Sendbyte
Aresp = &H01
Getresp
If Rbyte = Aresp Then
Cmda = 1
#if Debug = 1
Print #1 , "init error in cmd0 resp is" ; Hex(rbyte)
#endif
End If
#if Debug = 1
Print #1 , "done cmd0, resp is " ; Hex(rbyte)
#endif
'cmd1
For K = 1 To 255
Comm = &H41
Trail = &HFF
Sendcmd
Aresp = &H00
Getresp
If Rbyte = Aresp Then
Cmdb = 1
Goto Cmd1done:
End If
Next K
#if Debug = 1
Print #1 , "error in cmd1 resp=" ; Hex(rbyte)
#endif
Cmd1done:
'Print "done cmd1, resp is " ; Hex(rbyte)
' Print "cmda=" ; Cmda
' Print "cmdb=" ; Cmdb
Mmcinitdone = Cmda And Cmdb
#if Debug = 1
Print #1 , "mmcinitdone=" ; Mmcinitdone
#endif
End Sub