找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2229|回复: 4
收起左侧

SD卡CRC7查表法计算出字串的CRC值,有问题

[复制链接]
ID:283954 发表于 2021-4-16 18:36 | 显示全部楼层 |阅读模式
本帖最后由 dalaoshi 于 2021-4-16 18:41 编辑

最近用STC8G去读取SD卡,用SPI界面,读得出,就是比较慢,因为MCU的频率只达33.1771MHz,SPI的时钟最高是系统频率/4=8mhz, 距离SD卡可用的25MHZ还差一大截,很可惜,没有再快的8BIT单片机了,因为这样,就打算改用SD模式,有四条输出线,快4倍,很吸引人,但SD模式要用到CRC,否Z则发给SD卡指令后,卡懒得理你,无反应,这也是为何SD卡也叫安全卡的理由,没有这个功能,带电拔进拔出时资料可能会消失,可是这CRC对业余爱好者确是铁板一块。

还好有了网络,经过三天三夜的搜寻与学习,终于也明白了个大概,也收集了不少例程,但CRC7的文章比较少,CRC7应该是SD卡专用的格式,其种子(多项式)的二进值是10001001,这个种子是用来除别的数来获得该数的CRC,这个过程很繁杂,要一位一位地比较运算,听说要90多个时钟才算完一个字,如果是一个长字串,那就是个天文数字的时钟数,最后只得了个7位的数字,很浪费时间,因此有聪明人就发明了查表法,就是把0-255的CRC都先算出来,制成一个表,放在程序内某个区,需要知道一个BYTE的CRC,就到相应位置去查就可,51单片机就用MOVC A, @A+DPTR,至于字串的CRC怎么算呢?网上文章的说法是:

“特别需要关注的是,对传输的每一个字节的与CRC多项式校验完以后的校验值,要和下一个需要的校验的字节先异或,然后再与CRC多项式执行校验。当最后一个数据校验完以后,需左移一位,即获得CRC7的校验结果。”

我的理解是:“用字串的第一个字查表取出该子的CRC, 再与第二个字XRL,用XRL后的值去查表取出CRC, 以此类推直到最后一个字,就是该字串的CRC了”。

我根据这一理解用STC8G来检验SD卡的CMD0,“40H,00H, 00H, 00H, 00H”,答案应该是4AH,结果是51H,显然是我对上面的论述理解不对,观察程序每个步骤的结果,查表取值都对,但XRL对于00H没有变化,附上完整代码请前辈们帮忙看看,主要程序从74行开始,其他都是支持除错的代码。

运行结果为(HEX):“55 1B  64 64 72 72 5D 5D 18 18 51”,答案51。


;CRC7 测试
HEADBUFFER1 EQU 0A0H
LASTBUFFER1 EQU 0FFH   ;第一组缓冲区,共32位
IE2 EQU 0AFH      ;ETKSUI, ET4, ET3, ES4, ES3, ET2, ESPI, ES2

S2CON EQU 9AH          ;S2SM0, S2SM1(RESRVE, MUST BE 1), S2SM2, S2R_ENABLE, S2TB8, S2RB8, S2TI, S2RI
S3CON EQU 0ACH         ;SAME AS S2CON
S4CON EQU 84H
S2BUF EQU 9BH
S3BUF EQU 0ADH
S4BUF EQU 85H

P4 EQU 0C0H
P5 EQU 0C8H
P6 EQU 0E8H
P7 EQU 0F8H

T3L EQU 0D5H
T3H EQU 0D4H
T4L EQU 0D3H
T4H EQU 0D2H

MD0 EQU 0FCF3H
MD1 EQU 0FCF2H
MD2 EQU 0FCF1H
MD3 EQU 0FCF0H
MD4 EQU 0FCF5H
MD5 EQU 0FCF4H
ARCON EQU 0FCF6H
OPCON EQU 0FCF7H


T4T3M EQU 0D1H
P_SW2 EQU 0BAH
P_SW1 EQU 0A2H

T2H EQU 0D6H           
T2L EQU 0D7H
RELOAD_COUNT EQU 253 ;247(11.0592, 38400BPS) FOR TIMER_1 251=115200(18.4320M 115200BPS) 253(11.0592M 115200BPS)

AUXR EQU 8EH
AUXR1 EQU 0A2H ;7,6=PCA-P4,5=SPI-P4,4=S2-P4,3=GF2,2=ADRJ,1,0=DPS
AUXR2 EQU 08FH
WAKE_CLKO EQU 08FH    ;WAKEUP AND CLOCK OUTPUT CONTROL REGISTER 8GNEWNAME:INTCLKO x,EX4,EX3,EX2,xT2CLKO, T1CLKO, T0CLKO
AUXINTIF EQU 0EFH     ;EXTRA INT


ORG 0000H
LJMP MAIN
ORG 0023H
LJMP UART1    ;UART1 RECEIVED INTERRUPT

MAIN:
LCALL DELAY3
;MOV 97H, #00000001; SLOW DOWN
MOV R0, #HEADBUFFER1 ;INIT THE BTYE TO SENT IN BUFFER POINTER
MOV R1, #HEADBUFFER1 ;INIT THE POINTER FOR BYTE CAN STORE IN BUFFER
MOV WAKE_CLKO,#00000001B     ;ENABLE T2(=4),T1(=2) T0(=1) HAVE CLOCK OUTPUT T2@P1.0 T1@P3.5 T0@P3.4
MOV AUXR,#11111100B          ;T0X12,T1X12,UART_M0X6,T2RUN,S2SMOD,T2X12,EXTRAM,S1BRS
MOV AUXR2, #00000000B        ;#00010000B=SHIFT UART2
MOV TMOD, #00100010B         ;TIMER0, TIMER1 AS MOD2(8 BYTE AUTO RELOAD TIMER)
                             ;GATE, C/T,M1,M0(T1) GATE, C/T,M1,MO(T0)
MOV PCON, #00000000B         ;THIS DOUBLE THE T2 AND T0 T1 RATE; SMOD IS AT PCON.7 249(3.64=32US) 219 AT P3.5)

LCALL IOSET8G                ;8G初始时IO脚全为高阻,必须设定LED才会亮

LCALL INITIAL_UART1      ;USE T1 AS SERIAL BAUD GENERATE FOR UART1

CLR TI
CLR RI
SETB  EA                 ;ENABLE ALL INTERRUPT


;================这里开始========================


MOV A, #55H              ;这个测定串口正常
LCALL SENTONEBYTE1

MOV DPTR, #2000H         ;这个取码表第03H位显示1BH, 证实取码位置正确
MOV A, #03H
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

MOV A, #40H              ;第一字节查表正确,显示64H
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

MOV B, #00H                ;第二字节
XRL A, B                       ;根据网上指导,要先与原来前面获得的CRC值(64H)异或
LCALL SENTONEBYTE1       ;但与00H异或后还是原来的值

MOVC A, @A+DPTR
LCALL SENTONEBYTE1

MOV B, #00H
XRL A, B
LCALL SENTONEBYTE1
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

MOV B, #00H
XRL A, B
LCALL SENTONEBYTE1
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

MOV B, #00H
XRL A, B
LCALL SENTONEBYTE1
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

LED:                  ;停机
CLR P1.0
LED1:
MOV A, R0
XRL A, R1
JZ LEDEXIT
LEDEXIT:
JMP LED1

INITIAL_UART1: ;
MOV SCON, #01010000B     ;SET AS BAUD VERIABLE, NO ODD/EVEN CHECK
MOV TH1, #247            ;247(11.0592, 38400BPS) FOR TIMER_1 251=115200(18.4320M 115200BPS) 253(11.0592M 115200BPS) IF PCON.7=0   
MOV TL1, #247            ;247(33.1771, 115200 255-253=2 2x2=4=22M, 4X2=33.1771) PCON.7=0
SETB PS                         ;SERIAL PORT PRORITY HIGH
SETB TR1                       ;RUN TIMER_1
SETB ES                        ;ENABLE UART1 INTERRUPT
RET

SENTONEBYTE1:                ;SENT OUT A
CHECKBUSY1:
JB 40H, CHECKBUSY1
SETB 40H
MOV SBUF, A
RET

UART1:      
PUSH ACC
PUSH PSW
JNB RI, UART1CHECKTI
MOV A, SBUF ;READ THE CHARACTER FROM THE SERIAL PORT
CLR RI      ;CLEAR RECEICED FLAG
MOV @R1, A  ;SAVE TO BUFFER
CJNE R1, #LASTBUFFER1, NEXTREADBUFFER
MOV R1, #HEADBUFFER1
JMP UART1EXIT
NEXTREADBUFFER:
INC R1  ;POINT TO NEXT BUFFER
JMP UART1EXIT
UART1CHECKTI:
CLR TI
CLR 40H      
UART1EXIT:
POP PSW
POP ACC
RETI

DELAY2:
MOV 40H, #255
SLOWDOWN0:
MOV 41H, #170
SLOWDOWN:
MOV 42H, #2
SLOWDOWN2:
DJNZ 42H, SLOWDOWN2
DJNZ 41H, SLOWDOWN
DJNZ 40H, SLOWDOWN0
RET

DELAY3:
LCALL DELAY2
LCALL DELAY2
LCALL DELAY2
LCALL DELAY2
LCALL DELAY2
LCALL DELAY2
LCALL DELAY2
LCALL DELAY2
LCALL DELAY2
LCALL DELAY2
RET

IOSET8G:
;-----------I/O CONFIGUE
MOV 93H, #00000000B      ;SET P0 0,0=I/0, 0,1=HIGH CURRENT OUTPUT, 1,0=HIGH IMPEDENY INPUT 1,1=OPEN COLLECTIVE OUTPUT
MOV 94H, #00000000B      ;SET P0 (CONMAIN WITH 93H THIS IS SENCOND BIT)
MOV 91H, #00000000B      ;SET P1
MOV 92H, #00000000B      ;SET P1
MOV 95H, #00000000B      ;SET P2
MOV 96H, #00000000B      ;SET P2
MOV 0B1H, #00000000B     ;SET P3
MOV 0B2H, #00000000B     ;SET P3
MOV 0B3H, #00000000B     ;SET P4
MOV 0B4H, #00000000B     ;SET P4
MOV 0C9H, #00000000B     ;SET P5
MOV 0CAH, #00000000B     ;SET P5
MOV 0CBH, #00000000B     ;SET P6
MOV 0CCH, #00000000B     ;SET P6
;MOV 0E1H, #00000000B     ;SET P7
;MOV 0E2H, #00000000B     ;SET P7
RET

ORG 2000H
;G(X)=X7+X3+1
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
DB    0X41, 0X48, 0X53, 0X5A, 0X65, 0X6C, 0X77, 0X7E, 0X09, 0X00, 0X1B, 0X12, 0X2D, 0X24, 0X3F, 0X36
DB    0X58, 0X51, 0X4A, 0X43, 0X7C, 0X75, 0X6E, 0X67, 0X10, 0X19, 0X02, 0X0B, 0X34, 0X3D, 0X26, 0X2F
DB    0X73, 0X7A, 0X61, 0X68, 0X57, 0X5E, 0X45, 0X4C, 0X3B, 0X32, 0X29, 0X20, 0X1F, 0X16, 0X0D, 0X04
DB    0X6A, 0X63, 0X78, 0X71, 0X4E, 0X47, 0X5C, 0X55, 0X22, 0X2B, 0X30, 0X39, 0X06, 0X0F, 0X14, 0X1D
DB    0X25, 0X2C, 0X37, 0X3E, 0X01, 0X08, 0X13, 0X1A, 0X6D, 0X64, 0X7F, 0X76, 0X49, 0X40, 0X5B, 0X52
DB    0X3C, 0X35, 0X2E, 0X27, 0X18, 0X11, 0X0A, 0X03, 0X74, 0X7D, 0X66, 0X6F, 0X50, 0X59, 0X42, 0X4B
DB    0X17, 0X1E, 0X05, 0X0C, 0X33, 0X3A, 0X21, 0X28, 0X5F, 0X56, 0X4D, 0X44, 0X7B, 0X72, 0X69, 0X60
DB    0X0E, 0X07, 0X1C, 0X15, 0X2A, 0X23, 0X38, 0X31, 0X46, 0X4F, 0X54, 0X5D, 0X62, 0X6B, 0X70, 0X79


END




回复

使用道具 举报

ID:822755 发表于 2021-4-17 23:27 | 显示全部楼层
40 00 00 00 00 的SD crc确实是4A。传输格式是CRC7+stop bit,所以最后一字节应该是95h,不知道你的51h,从哪来的。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:283954 发表于 2021-4-18 16:17 | 显示全部楼层
40 00 00 00 00  crc=4A, 这是SD卡手册的标准答案,但我还没有学会如何自己运算CRC, 想抄捷径用查表法,但答案是51H,不对。
回复

使用道具 举报

ID:822755 发表于 2021-4-18 22:28 | 显示全部楼层
dalaoshi 发表于 2021-4-18 16:17
40 00 00 00 00  crc=4A, 这是SD卡手册的标准答案,但我还没有学会如何自己运算CRC, 想抄捷径用查表法,但 ...

MOV A, #40H              ;第一字节查表正确,显示64H
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

CLR C
RLC A

MOV B, #00H                ;第二字节
XRL A, B                       ;根据网上指导,要先与原来前面获得的CRC值(64H)异或
LCALL SENTONEBYTE1       ;但与00H异或后还是原来的值

MOVC A, @A+DPTR
LCALL SENTONEBYTE1

CLR C
RLC A

MOV B, #00H
XRL A, B
LCALL SENTONEBYTE1
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

CLR C
RLC A

MOV B, #00H
XRL A, B
LCALL SENTONEBYTE1
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

CLR C
RLC A

MOV B, #00H
XRL A, B
LCALL SENTONEBYTE1
MOVC A, @A+DPTR
LCALL SENTONEBYTE1

评分

参与人数 2黑币 +55 收起 理由
admin + 40 回帖助人的奖励!
dalaoshi + 15 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:283954 发表于 2021-4-19 00:30 | 显示全部楼层
果然对了,非常谢谢!这方法好。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表