sd_drive.s
来自「Atmega64单片机程序(完整工程)」· S 代码 · 共 1,636 行 · 第 1/3 页
S
1,636 行
.module SD_Drive.c
.area lit(rom, con, rel)
_time_unit::
.word 51712,15258
.word 57600,1525
.word 38528,152
.word 16960,15
.word 34464,1
.word 10000,0
.word 1000,0
.word 100,0
_time_value::
.byte 0,10
.byte 12,13
.byte 15,20
.byte 25,30
.byte 35,40
.byte 45,50
.byte 55,60
.byte 'F,'P
_r2w_fator::
.byte 1,2
.byte 4,8
.byte 16,32
.area text(rom, con, rel)
; recbuf -> y+0
; ret -> R10
.even
_SD_Initialize::
xcall push_gset3
sbiw R28,4
; /*--------------File Info-------------------------------------------------------
; ** 文 件 名: SD_Driver.c
; ** 最后修改日期: 2008.3.28
; ** 版 本: V1.0
; ** 描 述: sd 卡驱动软件包: 用户API函数
; **------------------------------------------------------------------------------
; ** Created by:
; ** Created date:
; *******************************************************************************/
;
; #include "SYS_Config.h"
; #include "SD_Config.h"
; #include "SD_Hal.h"
; #include "SD_Cmd.h"
; #include "SD_Drive.h"
;
;
; extern INT8U Data_Buf[SD_BLOCKSIZE];//在main函数中定义
;
;
; sd_struct sds ;/* SD卡信息结构体变量 */
;
; /* 超时时间单位表(单位:0.000000001ns) timeout unit table */
; const INT32U time_unit[8]=
; {
; 1000000000,100000000,10000000,
; 1000000,100000,10000,1000,100
; };
;
; /* 超时时间表 timeout value table */
; const INT8U time_value[16]=
; {
; 0,10,12,13,15,20,25,30,35,40,45,50,55,60,70,80
; };
;
; /* 超时时间因数表 timeout factor table */
; const INT8U r2w_fator[6]=
; {
; 1,2,4,8,16,32
; };
;
;
; /*
; ********************************************************************************
; 用户API函数: 初始化,读,写,擦 SD卡
;
; /******************************************************************************
; ** 函数名称: INT8U SD_Initialize()
; ** 功能描述: 初始化SD卡
; ** 输 入: 无
; ** 输 出: 0: 正确 >0: 错误码
; *******************************************************************************/
; INT8U SD_Initialize(void)
; {
; INT8U recbuf[4],ret ;
;
; SD_HardWareInit(); //初始化读写SD卡的硬件条件
xcall _SD_HardWareInit
;
; if(!SD_ChkCard()) // 检查卡是否插入
xcall _SD_ChkCard
tst R16
brne L2
; return SD_ERR_NO_CARD ;
ldi R16,1
xjmp L1
L2:
;
; SPI_CS_Assert(); /* 1. 置CS为低 assert CS */
xcall _SPI_CS_Assert
;
; SD_SPIDelay(100); /* 2. 至少延时 74 */
ldi R16,100
xcall _SD_SPIDelay
;
; SPI_CS_Deassert(); /* 3. 置CS为高 dessert CS */
xcall _SPI_CS_Deassert
;
; SD_SPIDelay(20); /* 4. 延时2(8 clock) */
ldi R16,20
xcall _SD_SPIDelay
;
; ret=SD_ResetSD(); /* 5. 发出CMDO命令复位SD卡 */
xcall _SD_ResetSD
mov R10,R16
; if(ret!=SD_NO_ERR)
tst R16
breq L4
; return ret ;
xjmp L1
L4:
;
; ret=SD_ActiveInit(); /* 6. 激活卡进入初始化过程. */
xcall _SD_ActiveInit
mov R10,R16
; if(ret!=SD_NO_ERR)
tst R16
breq L6
; return ret ;
xjmp L1
L6:
;
; ret=SD_ReadOCR(4,recbuf);/* 7. 读OCR寄存器,查询卡支持的电压值 */
movw R18,R28
ldi R16,4
xcall _SD_ReadOCR
mov R10,R16
; if(ret!=SD_NO_ERR)
tst R16
breq L8
; return ret ;
xjmp L1
L8:
;
; if((recbuf[1]&MSK_OCR_33)!=MSK_OCR_33)
ldd R24,y+1
andi R24,192
cpi R24,192
breq L10
; return SD_ERR_VOL_NOTSUSP ;/* 不支持3.3V,返回错误码 */
ldi R16,4
xjmp L1
L10:
;
; SPI_Clk_MAX(); /* 8. 设置SPI时钟到最大值 */
in R24,0xd
andi R24,252
out 0xd,R24
sbi 0xe,0
;
; #if SD_CRC_EN
; ret=SD_EnableCRC(1); /* 使能CRC校验 enable CRC check */
; if(ret!=SD_NO_ERR)
; return ret ;
; #endif
;
; ret=SD_SetBlockLen(SD_BLOCKSIZE);/* 9. 设置块的长度: 512Bytes */
ldi R16,0
ldi R17,2
ldi R18,0
ldi R19,0
xcall _SD_SetBlockLen
mov R10,R16
; if(ret!=SD_NO_ERR)
tst R16
breq L13
; return ret ;
xjmp L1
L13:
;
; return(SD_GetCardInfo()); /* 10. 读CSD寄存器,获取SD卡信息 */
xcall _SD_GetCardInfo
L1:
adiw R28,4
xcall pop_gset3
.dbline 0 ; func end
ret
; ret -> R10
; recbuf -> y+12
; blockaddr -> y+8
.even
_SD_ReadBlock::
xcall push_arg4
xcall push_gset3
sbiw R28,2
; }
;
; /*******************************************************************************
; ** 函数名称: INT8U SD_ReadBlock()
; ** 功能描述: 从SD卡中读一个块
; ** 输 入: INT32U blockaddr: 块地址
; INT8U *recbuf : 接收缓冲区,长度512Bytes
; ** 输 出: 0: 正确 >0: 错误码
; *******************************************************************************/
; INT8U SD_ReadBlock(INT32U blockaddr,INT8U *recbuf)
; {
; INT8U ret ;
;
; if(blockaddr>sds.block_num)
lds R4,_sds+2
lds R5,_sds+2+1
lds R2,_sds
lds R3,_sds+1
movw R30,R28
ldd R6,z+8
ldd R7,z+9
ldd R8,z+10
ldd R9,z+11
cp R2,R6
cpc R3,R7
cpc R4,R8
cpc R5,R9
brsh L16
; return SD_ERR_OVER_CARDRANGE ;
ldi R16,5
xjmp L15
L16:
; /* 操作超出卡容量范围 operate over the card range */
;
; ret=SD_ReadSingleBlock(blockaddr);
movw R30,R28
ldd R16,z+8
ldd R17,z+9
ldd R18,z+10
ldd R19,z+11
xcall _SD_ReadSingleBlock
mov R10,R16
; /* 读单块命令 read single blocks command */
; if(ret!=SD_NO_ERR)
tst R16
breq L18
; return ret ;
xjmp L15
L18:
;
; return(SD_ReadBlockData(SD_BLOCKSIZE,recbuf));
ldd R0,y+12
ldd R1,y+13
std y+1,R1
std y+0,R0
ldi R16,0
ldi R17,2
ldi R18,0
ldi R19,0
xcall _SD_ReadBlockData
L15:
adiw R28,2
xcall pop_gset3
adiw R28,4
.dbline 0 ; func end
ret
; tmp -> y+4
; ret -> R10
; sendbuf -> y+16
; blockaddr -> y+12
.even
_SD_WriteBlock::
xcall push_arg4
xcall push_gset3
sbiw R28,6
; /* 读出数据 read data from sd card */
; }
;
;
; /*******************************************************************************
; ** 函数名称: SD_Read_word
; ** 功能描述: 块偏移为offset 的长整形数据
; ** 输 入: INT32U blockaddr: 块地址
; INT16U offset : 块内偏移
; ** 输 出: INT32U
; 0xFFFF: 错误码
; *******************************************************************************/
; #if SD_Read_Word_EN
; INT16U SD_Read_Word(INT32U blockaddr,INT16U offset)
; {
; INT8U *buff;
; INT16U resp;
;
; buff=Data_Buf;
;
; if( SD_ReadBlock(blockaddr,buff)==0 )
; {
; resp=buff[offset+1];
; resp=(resp<<8)+buff[offset];
; return resp;
; }
; return 0xFFFF;
; }
; #endif
;
; /*******************************************************************************
; ** 函数名称: SD_Read_Dword
; ** 功能描述: 块偏移为offset 的长整形数据
; ** 输 入: INT32U blockaddr: 块地址
; INT16U offset : 块内偏移
; ** 输 出: INT32U
; 0xFFFFFFFF: 错误码
; *******************************************************************************/
; #if SD_Read_Dword_EN
; INT32U SD_Read_Dword(INT32U blockaddr,INT16U offset)
; {
; INT8U *buff;
; INT32U resp;
;
; buff=Data_Buf;
;
; if( SD_ReadBlock(blockaddr,buff)==0 )
; {
; resp=buff[offset+3];
; resp=(resp<<8)+buff[offset+2];
; resp=(resp<<8)+buff[offset+1];
; resp=(resp<<8)+buff[offset];
; return resp;
; }
; return 0xFFFFFFFF;
; }
; #endif
;
;
; /*******************************************************************************
; ** 函数名称: INT8U SD_ReadMultiBlock()
; ** 功能描述: 从SD卡中读多个块
; ** 输 入: INT32U blockaddr: 块地址
; INT32U blocknum : 块数量
; INT8U *recbuf : 接收缓冲区,每块512字节
; ** 输 出: 0: 正确 >0: 错误码
; *******************************************************************************/
; #if SD_ReadMultiBlock_EN
; INT8U SD_ReadMultiBlock(INT32U blockaddr,INT32U blocknum,INT8U*recbuf)
; {
; INT32U i ;
; INT8U ret ;
;
; if((blockaddr+blocknum)>sds.block_num)
; return SD_ERR_OVER_CARDRANGE ;
; /* 操作超出卡容量范围 operate over the card range */
;
; ret=SD_ReadMultipleBlock(blockaddr);
; /* 读多块命令 read multiple blocks command */
; if(ret!=SD_NO_ERR)
; return ret ;
;
; for(i=0;i<blocknum;i++)
; {
; /* 读出数据 read data from sd card */
; ret=SD_ReadBlockData(SD_BLOCKSIZE,recbuf);
; if(ret==SD_NO_ERR)
; recbuf=recbuf+SD_BLOCKSIZE ;
; else
; return ret ;
; }
; return(SD_StopTransmission());
; /* 结束数据传输 stop transmission operation */
; }
; #endif
;
; /*******************************************************************************
; ** 函数名称: INT8U SD_WriteBlock()
; ** 功能描述: 向SD卡中写入一个块
; ** 输 入: INT32U blockaddr: 块地址
; INT8U *sendbuf : 发送缓冲区,长度512Bytes
; ** 输 出: 0: 正确 >0: 错误码
; *******************************************************************************/
; INT8U SD_WriteBlock(INT32U blockaddr,INT8U *sendbuf)
; {
; INT8U ret,tmp[2];
;
; if(blockaddr>sds.block_num)
lds R4,_sds+2
lds R5,_sds+2+1
lds R2,_sds
lds R3,_sds+1
movw R30,R28
ldd R6,z+12
ldd R7,z+13
ldd R8,z+14
ldd R9,z+15
cp R2,R6
cpc R3,R7
cpc R4,R8
cpc R5,R9
brsh L21
; return SD_ERR_OVER_CARDRANGE ;
ldi R16,5
xjmp L20
L21:
; /* 操作超出卡容量范围 operate over the card range */
;
; if(SD_ChkCardWP()==1)
xcall _SD_ChkCardWP
cpi R16,1
brne L23
; return SD_ERR_WRITE_PROTECT ;
ldi R16,66
xjmp L20
L23:
; /* 卡有写保护 */
;
; ret=SD_WriteSingleBlock(blockaddr);
movw R30,R28
ldd R16,z+12
ldd R17,z+13
ldd R18,z+14
ldd R19,z+15
xcall _SD_WriteSingleBlock
mov R10,R16
; /* 写单块命令 write single block */
; if(ret!=SD_NO_ERR)
tst R16
breq L25
; return ret ;
xjmp L20
L25:
;
; ret=SD_WriteBlockData(0,SD_BLOCKSIZE,sendbuf);
ldd R0,y+16
ldd R1,y+17
std y+3,R1
std y+2,R0
ldi R20,0
ldi R21,2
ldi R22,0
ldi R23,0
std y+0,R22
std y+1,R23
movw R18,R20
clr R16
xcall _SD_WriteBlockData
mov R10,R16
; /* 写入数据 write data */
; /* 读Card Status寄存器, 检查写入是否成功 */
; if(ret==SD_NO_ERR)
tst R16
brne L27
; {
; /* read Card Status register to check write wheather sucessfully */
; ret=SD_ReadCard_Status(2,tmp);
movw R18,R28
subi R18,252 ; offset = 4
sbci R19,255
ldi R16,2
xcall _SD_ReadCard_Status
mov R10,R16
; if(ret!=SD_NO_ERR)
tst R16
breq L29
; return ret ;
xjmp L20
L29:
; /* 读寄存器失败 read register fail */
;
; if((tmp[0]!=0)||(tmp[1]!=0))
ldd R2,y+4
tst R2
brne L34
ldd R2,y+5
tst R2
breq L31
L34:
; ret=SD_ERR_WRITE_BLK ;
ldi R24,64
mov R10,R24
L31:
; /* 响应指示写失败 response indicate write fail */
; }
L27:
; return ret ;/* 返回写入结果 return the result of writing */
mov R16,R10
L20:
adiw R28,6
xcall pop_gset3
adiw R28,4
.dbline 0 ; func end
ret
; tmp -> y+0
; ret -> R10
; blocknum -> y+14
; startaddr -> y+10
.even
_SD_EraseBlock::
xcall push_arg4
xcall push_gset3
sbiw R28,4
; }
;
; /*******************************************************************************
; ** 函数名称: INT8U SD_WriteMultiBlock()
; ** 功能描述: 向SD卡中写入多个块
; ** 输 入: INT32U blockaddr: 块地址
; INT32U blocknum : 块数量
; INT8U *sendbuf : 发送缓冲区每块512字节
; ** 输 出: 0: 正确 >0: 错误码
; *******************************************************************************/
; #if SD_WriteMultiBlock_EN
; INT8U SD_WriteMultiBlock(INT32U blockaddr,INT32U blocknum,INT8U *sendbuf)
; {
; INT32U i ;
; INT8U ret ;
;
; if((blockaddr+blocknum)>sds.block_num)
; return SD_ERR_OVER_CARDRANGE ;
; /* 操作超出卡容量范围 operate over the card range */
;
; if(SD_ChkCardWP()==1)
; return SD_ERR_WRITE_PROTECT ;
; /* 卡有写保护 */
;
; ret=SD_WriteMultipleBlock(blockaddr);
; /* 写多块命令 write multiple blocks command */
; if(ret!=SD_NO_ERR)
; return ret ;
;
; for(i=0;i<blocknum;i++)
; {
; ret=SD_WriteBlockData(1,SD_BLOCKSIZE,sendbuf);
; /* 写入数据 write data */
; if(ret==SD_NO_ERR)
; sendbuf=sendbuf+SD_BLOCKSIZE ;
; else
; {
; /* 写失败 write fail */
; SD_StopTransmission();
; /* 停止数据传输 stop data transmission */
; SD_WaitBusy(SD_WAIT_WRITE);
; /* 等待 waiting */
; return ret ;
; }
; }
;
; SD_StopMultiToken();
; /* 发送数据停止令牌 send data stop token */
;
; ret=SD_WaitBusy(SD_WAIT_WRITE);
; /* 等待写入的完成 wait for finishing writing */
; if(ret!=SD_NO_ERR)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?