本帖最后由 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
|