⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc.asm

📁 用ATMEGA8开发的MMC程式,可用AVR-GCC开发
💻 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 + -