SD卡用CRC7和CRC16校验程序(汇编)
在开发我的MP3时,花了不少时间和参考了不少CRC的程序写了以下的CRC程,用的是查表法,对于SPI接口的SD卡,在发送数据后的等待时间中可以完成CRC校验计算,可以说得上是零等待的CRC校验了.并付上SD卡的写命令和读扇区程序.
/////////////////////////////////
//SD卡CRC保存在R16,数据入口R17//
/////////////////////////////////
CRC7:
LDI R18, 0x09 ;CRC7多项式
LSL R16
SBRC R16, 7
EOR R16, R18
SBRC R17, 7
EOR R16, R18
ANDI R16, 0x7F
ANDI R17, 0x7F
EOR R16, R17
CLR R19
LDI R30, LOW(CRC7DAT*2)
LDI R31, HIGH(CRC7DAT*2)
ADD R30, R16
ADC R31, R19
LPM R16, Z
RET
CRC7DAT: /* CR7C余式表 */
.DB 0x00,0x09,0x12,0x1B,0x24,0x2D,0x36,0x3F,0x48,0x41,0x5A,0x53,0x6C,0x65,0x7E,0x77
.DB 0x19,0x10,0x0B,0x02,0x3D,0x34,0x2F,0x26,0x51,0x58,0x43,0x4A,0x75,0x7C,0x67,0x6E
.DB 0x32,0x3B,0x20,0x29,0x16,0x1F,0x04,0x0D,0x7A,0x73,0x68,0x61,0x5E,0x57,0x4C,0x45
.DB 0x2B,0x22,0x39,0x30,0x0F,0x06,0x1D,0x14,0x63,0x6A,0x71,0x78,0x47,0x4E,0x55,0x5C
.DB 0x64,0x6D,0x76,0x7F,0x40,0x49,0x52,0x5B,0x2C,0x25,0x3E,0x37,0x08,0x01,0x1A,0x13
.DB 0x7D,0x74,0x6F,0x66,0x59,0x50,0x4B,0x42,0x35,0x3C,0x27,0x2E,0x11,0x18,0x03,0x0A
.DB 0x56,0x5F,0x44,0x4D,0x72,0x7B,0x60,0x69,0x1E,0x17,0x0C,0x05,0x3A,0x33,0x28,0x21
.DB 0x4F,0x46,0x5D,0x54,0x6B,0x62,0x79,0x70,0x07,0x0E,0x15,0x1C,0x23,0x2A,0x31,0x38
CRC32DAT: /* CRC32余式表 */
.DW 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7
.DW 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
.DW 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6
.DW 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de
.DW 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485
.DW 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d
.DW 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4
.DW 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc
.DW 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823
.DW 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b
.DW 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12
.DW 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a
.DW 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41
.DW 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49
.DW 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70
.DW 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78
.DW 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f
.DW 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067
.DW 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e
.DW 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256
.DW 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d
.DW 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405
.DW 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c
.DW 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634
.DW 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab
.DW 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3
.DW 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a
.DW 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92
.DW 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9
.DW 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1
.DW 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8
.DW 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
////////////////////////////////////
//SD卡CRC保存在R24R25,数据入口R16//
////////////////////////////////////
CRC32:
PUSH R30
PUSH R31
MOV R30, R25
EOR R30, R16
CLR R31
LSL R30
ROL R31
SUBI R30, LOW(-CRC32DAT*2)
SBCI R31, HIGH(-CRC32DAT*2)
LPM R0, Z+
LPM R1, Z+
EOR R1, R24
MOVW R24, R0
POP R31
POP R30
RET
/////////////////////////////////////////////////////
//写SD卡命令,R16为命令,R0,1,2,3为参数,反回参数R16//
/////////////////////////////////////////////////////
SD_Write_CMD:
PUSH R30
PUSH R31
PUSH R24
LDI R17, 0xFF
OUT SPDR, R17
SBIS SPSR, SPIF
RJMP PC-1
SD_CS_L
ORI R16, 0x40
MOV R17, R16
OUT SPDR, R16
CLR R16 ;CRC7的初值为0
RCALL CRC7
SBIS SPSR, SPIF
RJMP PC-1
OUT SPDR, R3
MOV R17, R3
RCALL CRC7
SBIS SPSR, SPIF
RJMP PC-1
OUT SPDR, R2
MOV R17, R2
RCALL CRC7
SBIS SPSR, SPIF
RJMP PC-1
OUT SPDR, R1
MOV R17, R1
RCALL CRC7
SBIS SPSR, SPIF
RJMP PC-1
OUT SPDR, R0
MOV R17, R0
RCALL CRC7
LSL R16
SUBI R16, -1
SBIS SPSR, SPIF
RJMP PC-1
OUT SPDR, R16
SBIS SPSR, SPIF
RJMP PC-1
LDI R17, 0xFF
CLR R24
_SD_WCOM_0:
OUT SPDR, R17
SBIS SPSR, SPIF
RJMP PC-1
IN R16, SPDR
INC R24
SBRS R16, 7
RJMP _SD_WCOM_1
CPI R24, 255
BRNE _SD_WCOM_0
_SD_WCOM_1:
SD_CS_H
POP R24
POP R31
POP R30
RET
/////////////////////////////////////////////////////
//从SD卡中读出一个扇区数据,存到R16,R17所指的数据区//
/////////////////////////////////////////////////////
SD_ReadBlock:
PUSH R24
PUSH R25
PUSH R30
PUSH R31
MOVW R30, R16
LDI R16, 9
_SD_READ_BLOCK_1:
LSL R0
ROL R1
ROL R2
ROL R3
DEC R16
BRNE _SD_READ_BLOCK_1
LDI R16, 17
RCALL SD_Write_CMD
SD_CS_L
LDI R24, 255
LDI R18, 0xFF
OUT SPDR, R18
_SD_READ_BLOCK_2:
SBIS SPSR, SPIF
RJMP PC-1
IN R16, SPDR
OUT SPDR, R18
CPI R16, 0xFE
BREQ _SD_READ_BLOCK_3
DEC R24
BRNE _SD_READ_BLOCK_2
LDI R16, 0xFF
RJMP _SD_READ_BLOCK_END
_SD_READ_BLOCK_3:
CLR R17
CLR R24
CLR R25
_SD_READ_BLOCK_4:
SBIS SPSR, SPIF
RJMP PC-1
IN R16, SPDR
OUT SPDR, R18
ST Z+, R16
RCALL CRC32
SBIS SPSR, SPIF
RJMP PC-1
IN R16, SPDR
OUT SPDR, R18
ST Z+, R16
RCALL CRC32
DEC R17
BRNE _SD_READ_BLOCK_4
SBIS SPSR, SPIF
RJMP PC-1
IN R19, SPDR
OUT SPDR, R18
SBIS SPSR, SPIF
RJMP PC-1
IN R18, SPDR
LDI R16, 5
_SD_READ_BLOCK_5:
LDI R17, 0xFF
OUT SPDR, R17
SBIS SPSR, SPIF
RJMP PC-1
DEC R16
BRNE _SD_READ_BLOCK_5
CP R18, R24
CPC R19, R25
BREQ _SD_READ_BLOCK_END
;CRC16不正确,反回错误码0x80
LDI R16, 0x80
_SD_READ_BLOCK_END:
SD_CS_H
POP R31
POP R30
POP R25
POP R24
RET 自己顶一下 LSL R0
ROL R1
ROL R2
ROL R3
楼主的R0-R3是参数为什么要移动这个数值呢? 其实mp3一般不用校验的,基本没有出错 【2楼】
在这里R0-3是SD卡的扇区号,但SD卡的读写起始要指定到字节的,所以R0-3要移动9位(即乘上512).所以SD卡的理论最大容量是4G. 感谢了知道了 LDI R18, 0x09 ;CRC7多项式
为什么不是0x89呢? CRC7多只有7位有较值,第八位是1时才和多项式异或,也可写成0x89不过没有意义 恐怖,太汇编了。 赞赏一个 标记 O(∩_∩)O谢谢楼主 mark!!!!!!!!!!!!!!!!!!!!!! 楼主很强大……考完试把SD读写加字库加5110显示搞出来
页:
[1]