📄 mmc.asm
字号:
;/*
; 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
;<work> char Read_Byte_MMC(void);
;void Write_Byte_MMC(<work> char);
;<work> char Init_MMC(void);
;<work> char Read_Block_MMC (<Y, work> unsigned long, <Z: SRAM @Buffer> char *Buffer);
;<work> char Write_Block_MMC (<Y, work> unsigned long, <Z: SRAM @Buffer> char *Buffer);
;<work> char Write_Command_MMC (<SRAM @CMD> char *CMD);
.ORG 860
;//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
Init_MMC: ;<work> 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<<SPE)|(1<<MSTR)|(1<<SPR0) ;//Enable SPI, SPI in Master Mode
ldi work, 0x53
out SPCR, work
out SPSR, null
;//Initialisiere MMC/SD-Karte in den SPI-Mode
ldi cnt, 15
lp1: ldi work, 0xFF
rcall Write_Byte_MMC ;//Sendet min 74+ Clocks an die MMC/SD-Karte
dec cnt
brne lp1
;//Sendet Commando CMD0 an MMC/SD-Karte
ldi XL, LOW(CMD) ; Im SRAM CMD0 ablegen
ldi XH, HIGH(CMD)
ldi work, 0x40
st X+, work
st X+, null
st X+, null
st X+, null
st X+, null
ldi work, 0x95
st X+, work
rcall Write_Command_MMC
;//printf ("Return Code from MMC/SD Init CMD0 %x\n",tmp);
push work
sbi MMC_Write, MMC_Chip_Select
ldi work, 0xFF
rcall Write_Byte_MMC
pop work
cpi work, 0x01
breq jp1
ldi work, 1 ;//Abbruch bei Commando1 (Return Code1)
pop XH
pop XL
ret
jp1: ;//Sendet Commando CMD1 an MMC/SD-Karte
ldi XL, LOW(CMD) ; Im SRAM CMD1 ablegen
ldi XH, HIGH(CMD)
ldi work, 0x41;//Commando 1
st X+, work
st X+, null
st X+, null
st X+, null
st X+, null
ldi work, 0xFF
st X+, work
clr cnt
lp3: push cnt
rcall Write_Command_MMC
pop cnt
;//printf ("Return Code from MMC/SD Init CMD1 %x\n",tmp);
cpi work, 0
breq jp2
sbi MMC_Write, MMC_Chip_Select
ldi work, 0xFF
rcall Write_Byte_MMC
dec cnt ; Timeout++;
brne lp3
ldi work, 2 ;//Abbruch bei Commando2 (Return Code2)
pop XH
pop XL
ret
jp2: sbi MMC_Write, MMC_Chip_Select
ldi work, 0x50
out SPCR, work
sbi SPSR, SPI2X
clr work
pop XH
pop XL
ret
;//Sendet ein Commando an die MMC/SD-Karte
Write_Command_MMC: ;<work> char Write_Command_MMC (<SRAM @CMD> 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黮tige 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: ;<work> 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(<work> 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: ;<work> char Read_Block_MMC (<Y, work> unsigned long, <Z: SRAM @Buffer> 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: ;<work> char Write_Block_MMC (<Y, work> unsigned long, <Z: SRAM @Buffer> 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黦t*/
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -