;/* ; Copyright: Simon Lehmayr mailto: lehmayr@web.de ; Author: -"- ; Remarks: ; known Problems: none ; Version: 28.07.2004 ; Description: Ansteuerung einer MMC/SD-Memory-Card ;*/ .equ MMC_Write =PORTB ;//Port an der die MMC/SD-Karte angeschlossen ist also des SPI .equ MMC_Read =PINB .equ MMC_Dir =DDRB .equ SPI_DI =4 ;//Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist .equ SPI_DO =3 ;//Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist .equ SPI_Clock =5 ;//Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk) .equ MMC_Chip_Select =2 ;//Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist ;.equ SPI_SS =0 ;//Prototypes ; char Read_Byte_MMC(void); ;void Write_Byte_MMC( char); ; char Init_MMC(void); ; char Read_Block_MMC ( unsigned long, char *Buffer); ; char Write_Block_MMC ( unsigned long, char *Buffer); ; char Write_Command_MMC ( char *CMD); .ORG 800 ;//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE) Init_MMC: ; char Init_MMC(void); push XL push XH ;//Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde cbi MMC_Dir, SPI_DI ;//Setzen von Pin MMC_DI auf Input sbi MMC_Dir, SPI_Clock ;//Setzen von Pin MMC_Clock auf Output sbi MMC_Dir, SPI_DO ;//Setzen von Pin MMC_DO auf Output sbi MMC_Dir, MMC_Chip_Select ;//Setzen von Pin MMC_Chip_Select auf Output ; sbi MMC_Dir, SPI_SS sbi MMC_Write, MMC_Chip_Select ;//Setzt den Pin MMC_Chip_Select auf High Pegel ;//Aktiviren des SPI - Bus, Clock = Idel High ;ldi work, (1< char Write_Command_MMC ( char *CMD); push XL push XH ;//sendet 8 Clock Impulse ldi work, 0xFF rcall Write_Byte_MMC ;//sendet 6 Byte Commando cbi MMC_Write, MMC_Chip_Select ;//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv) ldi cnt, 6 ;//sendet 6 Byte Commando zur MMC/SD-Karte ldi XL, LOW(CMD) ; SRAM Pointer auf CMD setzen ldi XH, HIGH(CMD) lp4: ld work, X+ rcall Write_Byte_MMC dec cnt brne lp4 clr cnt lp5: ldi work, 0xFF rcall Write_Byte_MMC ;//Wartet auf ein gültige Antwort von der MMC/SD-Karte in work, SPDR cpi work, 0xFF ; Antwort sollte 0x01 sein brne lp6 dec cnt brne lp5 lp6: pop XH pop XL ret ;//Abbruch da die MMC/SD-Karte nicht antwortet ;//Routine zum Empfangen eines Bytes von der MMC-Karte (SPI) Read_Byte_MMC: ; char Read_Byte_MMC(void); ldi work, 0xFF out SPDR, work lp6r: sbis SPSR, SPIF rjmp lp6r in work, SPDR ret ;//Routine zum Senden eines Bytes zur MMC-Karte (SPI) Write_Byte_MMC: ;void Write_Byte_MMC( char); out SPDR, work lp7: sbis SPSR, SPIF rjmp lp7 ret ;//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte Read_Block_MMC: ; char Read_Block_MMC ( unsigned long, char *Buffer); push XL push XH ;//Commando 17 zum lesen eines Blocks ldi cnt, 0x51 rcall prepcmd ;//Sendet Commando CMD17 an MMC/SD-Karte (Read 1 Block/512 Bytes) rcall Write_Command_MMC cpi work, 0 breq jp3 sbi MMC_Write, MMC_Chip_Select ldi work, 1 pop XH pop XL ret jp3: ;//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte) clr cnt lp8: ldi work, 0xFF rcall Write_Byte_MMC in work, SPDR cpi work, 0xFE breq jp4 dec cnt brne lp8 ldi work, 2 sbi MMC_Write, MMC_Chip_Select pop XH pop XL ret jp4: ;//Lesen des Blocks (512Bytes) von MMC/SD-Karte ldi XL, LOW(512) ldi XH, HIGH(512) lp9: ldi work, 0xFF rcall Write_Byte_MMC in work, SPDR st Z+, work sbiw XH:XL, 1 brne lp9 ;//CRC-Bytes auslesen ldi work, 0xFF rcall Write_Byte_MMC ldi work, 0xFF rcall Write_Byte_MMC sbi MMC_Write, MMC_Chip_Select clr work pop XH pop XL ret ;//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte Write_Block_MMC: ; char Write_Block_MMC ( unsigned long, char *Buffer); push XL push XH ;//Commando 24 zum schreiben eines Blocks ldi cnt, 0x58 rcall prepcmd ;//Sendet Commando CMD24 an MMC/SD-Karte (Write 1 Block/512 Bytes) rcall Write_Command_MMC cpi work, 0 breq jp5 sbi MMC_Write, MMC_Chip_Select ldi work, 1 pop XH pop XL ret jp5: ;//Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte ldi cnt, 15 lp10: ldi work, 0xFF rcall Write_Byte_MMC dec cnt brne lp10 ;//Sendet Start Byte an MMC/SD-Karte ldi work, 0xFE rcall Write_Byte_MMC ;//Schreiben des Blocks (512Bytes) auf MMC/SD-Karte ldi XL, LOW(512) ldi XH, HIGH(512) lp11: ld work, Z+ rcall Write_Byte_MMC sbiw XH:XL, 1 brne lp11 ;//CRC-Byte schreiben ldi work, 0xFF rcall Write_Byte_MMC ldi work, 0xFF rcall Write_Byte_MMC ;//CRC Code wird nicht benutzt ;//Wartet auf MMC/SD-Karte Busy clr cnt lp12: ldi work, 0xFF rcall Write_Byte_MMC in work, SPDR rcall delay rcall delay rcall delay dec cnt breq jp6 cpi work, 0xFF brne lp12 sbi MMC_Write, MMC_Chip_Select clr work pop XH pop XL ret jp6: ldi work, 2 sbi MMC_Write, MMC_Chip_Select pop XH pop XL ret prepcmd:; Prepares a command push XL push XH push scntl push scnth push scnts ldi XL, LOW(CMD) ; Im SRAM CMD ablegen ldi XH, HIGH(CMD) st X+, cnt ;/*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*/ clc rol scntl ; addr = addr << 9; //addr = addr * 512 rol scnth rol scnts st X+, scnts ;CMD24[1] = ((addr & 0xFF000000) >>24 ); st X+, scnth ;CMD24[2] = ((addr & 0x00FF0000) >>16 ); st X+, scntl ;CMD24[3] = ((addr & 0x0000FF00) >>8 ); st X+, null ldi work, 0xFF st X+, work pop scnts pop scnth pop scntl pop XH pop XL ret delay: clr r0 delay_: dec r0 brne delay_ ret ;dellong:ldi dcnt, 150 ; dl_: rcall delay ; dec dcnt ; brne dl_ ; ret READ_SECTOR_START:; Prepares reading of a sector (like Read_Block does but without getting the data) sbr mode, smMMCBS ;//Commando 17 zum lesen eines Blocks ldi cnt, 0x51 rcall prepcmd ;//Sendet Commando CMD17 an MMC/SD-Karte (Read 1 Block/512 Bytes) rcall Write_Command_MMC cpi work, 0 breq jp7 sbi MMC_Write, MMC_Chip_Select ldi work, 1 cbr mode, smMMCBS rjmp READERROR ; ret jp7: ;//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte) clr cnt lp13: ldi work, 0xFF rcall Write_Byte_MMC in work, SPDR cpi work, 0xFE breq jp8 dec cnt brne lp13 ldi work, 2 sbi MMC_Write, MMC_Chip_Select cbr mode, smMMCBS rjmp READERROR ; ret jp8: clr work cbr mode, smMMCBS ret READ_SECTOR_END:; Ends reading and disables card sbr mode, smMMCBS ;//CRC-Bytes auslesen ldi work, 0xFF rcall Write_Byte_MMC ldi work, 0xFF rcall Write_Byte_MMC clr work cbr mode, smMMCBS ret WRITE_SECTOR_START:;Prepares to write a sector (just like Write_Block does) sbr mode, smMMCBS ;//Commando 24 zum schreiben eines Blocks ldi cnt, 0x58 rcall prepcmd ;//Sendet Commando CMD24 an MMC/SD-Karte (Write 1 Block/512 Bytes) rcall Write_Command_MMC cpi work, 0 breq jp9 sbi MMC_Write, MMC_Chip_Select ldi work, 1 cbr mode, smMMCBS rjmp WRITEERROR ; ret jp9: ;//Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte ldi cnt, 15 lp14: ldi work, 0xFF rcall Write_Byte_MMC dec cnt brne lp14 WRITE_CONT: ;//Sendet Start Byte an MMC/SD-Karte ldi work, 0xFE rcall Write_Byte_MMC clr work cbr mode, smMMCBS ret WRITE_SECTOR_END:;Ends the write process for a sector sbr mode, smMMCBS ;//CRC-Byte schreiben ldi work, 0xFF rcall Write_Byte_MMC ldi work, 0xFF rcall Write_Byte_MMC ;//CRC Code wird nicht benutzt ; rcall dellong ;//Wartet auf MMC/SD-Karte Busy clr cnt lp15: ldi work, 0xFF rcall Write_Byte_MMC in work, SPDR rcall delay rcall delay dec cnt breq jp11 cpi work, 0xFF brne lp15 clr work cbr mode, smMMCBS ret jp11: ldi work, 2 cbr mode, smMMCBS rjmp WRITEERROR ; ret