新手入门
- 积分
- 18
- 金钱
- 18
- 注册时间
- 2019-7-4
- 在线时间
- 3 小时
|
1金钱
本帖最后由 ljyzzy 于 2019-7-4 12:38 编辑
我是从原子哥的历程修改过去的,因为原子哥的历程是spi方式读取flash和SDIO方式读取SD卡,然后挂载USB读卡器。而我们的SDIO口因为IO口被占用掉了,所以选择的是SPI方式读取SD卡,然后通过USB挂载读卡器。现在问题是 1:用USB+SPI读取板载flash,可以实现电脑读取flash,因此usb和spi应该都是没有问题。 2:用SPI读取SD卡,实现fatfs文件系统读写sd卡也是没有问题的,因此我们的spi读取SD卡部分也是没有问题的。
3:我在原子哥的《实验51 USB读卡器(Slave)实验》里面把usbd_storage_msd.c文件中关于SDIO读取SD的部分换成spi SD卡读取函数,然后把板载flash的那些全部注释掉,结果连接电脑上之后没有什么反应,也没有进入sd卡的读取部分,所以我想问除了usbd_storage_msd.c之外,是不是还有哪里需要修改的,有没有什么我没注意到的部分。
请大家指点,感激不尽!!!
稍后上程序。
#include "usbd_msc_mem.h"
#include "usb_conf.h"
//#include "w25qxx.h"
#include "sdio_sdcard.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F407开发板
//USB读卡器 驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2014/7/21
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//*******************************************************************************
//修改信息
//无
//////////////////////////////////////////////////////////////////////////////////
//最大支持的设备数,2个
#define STORAGE_LUN_NBR 2
////////////////////////////自己定义的一个标记USB状态的寄存器///////////////////
//bit0:表示电脑正在向SD卡写入数据
//bit1:表示电脑正从SD卡读出数据
//bit2:SD卡写数据错误标志位
//bit3:SD卡读数据错误标志位
//bit4:1,表示电脑有轮询操作(表明连接还保持着)
vu8 USB_STATUS_REG=0;
////////////////////////////////////////////////////////////////////////////////
//USB Mass storage 标准查询数据(每个lun占36字节)
const int8_t STORAGE_Inquirydata[] = {
/* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(USBD_STD_INQUIRY_LENGTH - 4),
0x00,
0x00,
0x00,
/* Vendor Identification */
'A', 'L', 'I', 'E', 'N', 'T', 'E', 'K', ' ',//9字节
/* Product Identification */
'S', 'P', 'I', ' ', 'F', 'l', 'a', 's', 'h',//15字节
' ','D', 'i', 's', 'k', ' ',
/* Product Revision Level */
'1', '.', '0', ' ', //4字节
/* LUN 1 */
0x00,
0x80,
0x02,
0x02,
(USBD_STD_INQUIRY_LENGTH - 4),
0x00,
0x00,
0x00,
/* Vendor Identification */
'A', 'L', 'I', 'E', 'N', 'T', 'E', 'K',' ', //9字节
/* Product Identification */
'S', 'D', ' ', 'F', 'l', 'a', 's', 'h', ' ',//15字节
'D', 'i', 's', 'k', ' ', ' ',
/* Product Revision Level */
'1', '.', '0' ,' ', //4字节
};
int8_t STORAGE_Init (uint8_t lun);
int8_t STORAGE_GetCapacity (uint8_t lun,uint32_t *block_num,uint32_t *block_size);
int8_t STORAGE_IsReady (uint8_t lun);
int8_t STORAGE_IsWriteProtected (uint8_t lun);
int8_t STORAGE_Read (uint8_t lun,uint8_t *buf,uint32_t blk_addr,uint16_t blk_len);
int8_t STORAGE_Write (uint8_t lun,uint8_t *buf,uint32_t blk_addr,uint16_t blk_len);
int8_t STORAGE_GetMaxLun (void);
//USB Device 用户回调函数接口
USBD_STORAGE_cb_TypeDef USBD_MICRO_SDIO_fops =
{
STORAGE_Init,
STORAGE_GetCapacity,
STORAGE_IsReady,
STORAGE_IsWriteProtected,
STORAGE_Read,
STORAGE_Write,
STORAGE_GetMaxLun,
(int8_t *)STORAGE_Inquirydata,
};
USBD_STORAGE_cb_TypeDef *USBD_STORAGE_fops=&USBD_MICRO_SDIO_fops;//指向USBD_MICRO_SDIO_fops结构体.
//初始化存储设备
//lun:逻辑单元编号,0,SD卡;1,SPI FLASH
//返回值:0,成功;
// 其他,错误代码
int8_t STORAGE_Init (uint8_t lun)
{
SD_Init();
;//W25QXX_Init();
return 0;
}
//获取存储设备的容量和块大小
//lun:逻辑单元编号,0,SD卡;1,SPI FLASH
//block_num:块数量(扇区数)
//block_size:块大小(扇区大小)
//返回值:0,成功;
// 其他,错误代码
int8_t STORAGE_GetCapacity (uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
if(lun==1)
{
*block_size=512;
//*block_num=SDCardInfo.CardCapacity/512;
*block_num=30405*1024/512;
}else
{
*block_size=512;
*block_num=1024*1024*12/512; //SPI FLASH的前面12M字节,文件系统用
}
return 0;
}
//查看存储设备是否就绪
//lun:逻辑单元编号,0,SD卡;1,SPI FLASH
//返回值:0,就绪;
// 其他,未就绪
int8_t STORAGE_IsReady (uint8_t lun)
{
USB_STATUS_REG|=0X10;//标记轮询
return 0;
}
//查看存储设备是否写保护
//lun:逻辑单元编号,0,SD卡;1,SPI FLASH
//返回值:0,没有写保护;
// 其他,写保护(只读)
int8_t STORAGE_IsWriteProtected (uint8_t lun)
{
return 0;
}
//从存储设备读取数据
//lun:逻辑单元编号,0,SD卡;1,SPI FLASH
//buf:数据存储区首地址指针
//blk_addr:要读取的地址(扇区地址)
//blk_len:要读取的块数(扇区数)
//返回值:0,成功;
// 其他,错误代码
int8_t STORAGE_Read (uint8_t lun,uint8_t *buf,uint32_t blk_addr,uint16_t blk_len)
{
int8_t res=0;
USB_STATUS_REG|=0X02;//标记正在读数据
if(lun==1)
{
res=SD_ReadDisk(buf,blk_addr,blk_len);
if(res)USB_STATUS_REG|=0X08;//SD卡读错误!
}else
{
;//W25QXX_Read(buf,blk_addr*512,blk_len*512);
}
return res;
}
//向存储设备写数据
//lun:逻辑单元编号,0,SD卡;1,SPI FLASH
//buf:数据存储区首地址指针
//blk_addr:要写入的地址(扇区地址)
//blk_len:要写入的块数(扇区数)
//返回值:0,成功;
// 其他,错误代码
int8_t STORAGE_Write (uint8_t lun,uint8_t *buf,uint32_t blk_addr,uint16_t blk_len)
{
int8_t res=0;
USB_STATUS_REG|=0X01;//标记正在写数据
if(lun==1)
{
res=SD_WriteDisk (buf,blk_addr,blk_len);
if(res)USB_STATUS_REG|=0X04;//SD卡写错误!
}else
{
;//W25QXX_Write(buf,blk_addr*512,blk_len*512);
}
return res;
}
//获取支持的最大逻辑单元个数
//返回值:支持的逻辑单元个数-1
int8_t STORAGE_GetMaxLun (void)
{
return (STORAGE_LUN_NBR - 1);
}
以下spi_sdcard.c
//#include "delay.h"
#include "stm32f4xx.h"
#include <stdio.h>
#include "usart.h"
#include "spi2.h"
#include "spi_sdcard.h"
#include "string.h"
#include "delay.h"
u8 SD_Type;
__align(4) u8 SPISD_DATA_BUFFER[512];
void testxx(void)
{
;}
//@brief: SD卡初始化
//@param :
//@retval: 1:错误 r1:命令响应
u8 SD_Init(void)
{
u16 i;
u8 r1;
u16 retry;
u8 buff[6];
SPI2_Init(); //初始化SPI2
SPI2_SetSpeed(SPI_BaudRatePrescaler_256); //SD卡初始化时钟不能超过400KHz
SPI_SD_CS_HIGH(); //打开SD卡片选引脚
delay_ms(5); //等待SD卡上电稳定,完成初始化
for(i=0;i<10;i++)
{
SPI2_ReadWriteByte(0xff); //产生80个时钟脉冲
}
//将SD卡复位至idle状态
SPI_SD_CS_LOW();
retry = 0;
do
{
r1 = SD_SendCommand(CMD0,0,0X95); //发送CMD0
SPI2_ReadWriteByte(0xff);
retry++;
}while((r1!=0x01)&&(retry<200)); //收到正确响应或超时后退出
if(retry==200) //如果退出原因为超时
{
printf("chaoshi!");
return 1;
}
r1= SD_SendCommand(CMD8,0x01aa,0x87); //如果退出原因为SD卡复位至idle并收到正确响应,继续发送CMD8获取SD卡版本信息
//如果是v2.0版本的SD卡
if(r1==0x01) //接收到CMD8的正确响应接收CMD8响应后续传送的4字节数据
{
printf("59!");
buff[0] = SPI2_ReadWriteByte(0xff); //接收CMD8响应后续传送的4字节数据
buff[1] = SPI2_ReadWriteByte(0xff);
buff[2] = SPI2_ReadWriteByte(0xff);
buff[3] = SPI2_ReadWriteByte(0xff);
// SD_CS = 1;
// SPI2_ReadWriteByte(0xff); //多发送8个时钟信号
//开始初始化SD卡
SPI_SD_CS_LOW();//SD_CS = 0;
retry = 0;
do
{
r1 = SD_SendCommand(CMD55,0,0xff); //发送CMD55,通知SD卡下一条命令为应用相关命令而非通用命令
SPI2_ReadWriteByte(0xff);
if(r1!=0x01) //如果主机未接收到CMD55的正确响应
{
//printf("81!");
return r1;
}
r1 = SD_SendCommand(ACMD41,0x40000000,1); //否则继续发送ACMD41
SPI2_ReadWriteByte(0xff);
retry++;
if(retry>200)
{
//printf("89!r=%d!",r1);
//return r1; //超时退出
}
}while(r1!=0); //接收到ACMD41的正确响应退出
SPI_SD_CS_HIGH();
SPI2_ReadWriteByte(0xff);
SPI_SD_CS_LOW();
//初始化指令发送完成,继续获取OCR信息
//识别SD2.00版本的SD卡类型
r1 = SD_SendCommand_NoDeassert(CMD58,0,0); //发送CMD58
if(r1!=0x00)
{
printf("101!");
return r1; //未接收到CMD58的正确响应退出
}
buff[0] = SPI2_ReadWriteByte(0xff); //否则接收CMD58响应后续传回的4字节COR信息
buff[1] = SPI2_ReadWriteByte(0xff);
buff[2] = SPI2_ReadWriteByte(0xff);
buff[3] = SPI2_ReadWriteByte(0xff);
SPI_SD_CS_HIGH();//SD_CS =1;
SPI2_ReadWriteByte(0xff);
//分析OCR信息中的bit30(CCS)判断卡的类型
//CCS=1,SDHC;CCS=0;SD2.0;
printf("here!");
if(buff[0]&0x40)
{
printf("SDHC!");
SD_Type = SD_TYPE_V2HC; //类型为SDHC
}
else
{
printf("SD2.0!");
SD_Type = SD_TYPE_V2; //类型为SD2.0
}
SPI2_SetSpeed(SPI_BaudRatePrescaler_2 ); //SPI4时钟频率配置为45MHz
}
return 0;
}
//@brief:向SD卡发送命令(发送结束后关闭片选信号)
//@param:cmd start bit+transmission bit+command index
//@param:arg
//@param :crc CRC7+end bit
//@retval: r1:命令响应
u8 SD_SendCommand(u8 cmd,u32 arg,u8 crc)
{
unsigned char r1;
unsigned int Retry = 0;
SPI_SD_CS_HIGH();//SD_CS = 1;
SPI2_ReadWriteByte(0xff);
SPI_SD_CS_LOW();//SD_CS = 0;
SPI2_ReadWriteByte(cmd|0x40); //将CMD命令中的传输位设置为1
SPI2_ReadWriteByte((u8)(arg>>24)); //写入CMD命令的32位参数
SPI2_ReadWriteByte((u8)(arg>>16));
SPI2_ReadWriteByte((u8)(arg>>8));
SPI2_ReadWriteByte((u8)(arg));
SPI2_ReadWriteByte(crc); //写入CRC校验和
while((r1 = SPI2_ReadWriteByte(0xff))==0xff) //接收到相关命令的正确响应后退出
{
Retry++;
if(Retry>800)
{
printf("time!!");
break; //超时退出
}
}
SPI_SD_CS_HIGH();//SD_CS = 1;
SPI2_ReadWriteByte(0xff); //额外发送8个时钟信号,使SD卡完成剩余工作
return r1;
}
//@brief:向SD卡发送命令(发送结束后持续打开片选信号)
//@param:cmd start bit+transmission bit+command index
//@param:arg
//@param :crc CRC7+end bit
//@retval:r1:命令响应
u8 SD_SendCommand_NoDeassert(u8 cmd,u32 arg,u8 crc)
{
unsigned char r1;
unsigned int Retry = 0;
SPI_SD_CS_HIGH();//SD_CS = 1;
SPI2_ReadWriteByte(0xff);
SPI_SD_CS_LOW();//SD_CS = 0;
SPI2_ReadWriteByte(cmd|0x40);
SPI2_ReadWriteByte((u8)(arg>>24));
SPI2_ReadWriteByte((u8)(arg>>16));
SPI2_ReadWriteByte((u8)(arg>>8));
SPI2_ReadWriteByte((u8)(arg));
SPI2_ReadWriteByte(crc);
while((r1 = SPI2_ReadWriteByte(0xff))==0xff)
{
Retry++;
if(Retry >800) break;
}
return r1;
}
//@brief:从SD卡中读取指定长度的数据
//@param:*data 指向存储读回数据的缓冲区的指针
//@param:len 数据长度
//@param:release 读取结束后是否释放总线
//@retval:1:错误 0:正确
u8 SD_ReceiveData(u8 *data,u16 len,u8 release)
{
u16 retry;
u8 r1;
SPI_SD_CS_LOW();//SD_CS = 0;
retry = 0;
do
{
r1 = SPI2_ReadWriteByte(0xff);
retry++;
if(retry>4000)
{
SPI_SD_CS_HIGH();//SD_CS = 1;
return 1; //超时退出
}
}while(r1!=0xfe); //主机收到SD卡传回的正确数据读取响应退出
//接收到正确响应后,开始接收数据
while(len--)
{
*data = SPI2_ReadWriteByte(0xff);
//printf("0x%02x ", *data);
data++;
}
SPI2_ReadWriteByte(0xff); //发送2个无效CRC
SPI2_ReadWriteByte(0xff);
if(release == RELEASE) //是否需要释放总线
{
SPI_SD_CS_HIGH();//SD_CS = 1;
SPI2_ReadWriteByte(0xff);
}
return 0;
}
//@brief:获取CID寄存器数据
//@param:*cid_data 指向存储CID寄存器数据的缓冲区的指针
//@retval:0:正确 r1:命令响应
u8 SD_GetCID(u8 *cid_data)
{
u8 r1;
r1 = SD_SendCommand(CMD10,0,0xff); //发送CMD10命令以获取CID寄存器数据
if(r1!=0x00)
return r1; //主机未接收到正确响应退出
SD_ReceiveData(cid_data,16,RELEASE); //接收CID寄存器数据并释放总线
return 0;
}
//@brief:获取CSD寄存器数据
//@param:*csd_data 指向存储CSD寄存器数据的缓冲区的指针
//@retval:0:正确 r1:命令响应
u8 SD_GetCSD(u8 *csd_data)
{
u8 r1;
r1 = SD_SendCommand(CMD9,0,0xff); //发送CMD9命令以获取CSD寄存器数据
if(r1!=0x00)
return r1; //主机未接收到正确响应退出
SD_ReceiveData(csd_data,16,RELEASE); //接收CSD寄存器数据并释放总线
return 0;
}
/*检查sd卡是否正常*/
u8 SD_is_Ready(void)
{
u8 cid[36];
return SD_GetCSD( cid );
}
//@brief:获取SD卡容量信息
//@param:
//@retval:Capacity:SD卡容量
u32 SD_GetCapacity(void)
{
u8 csd[16];
u32 Capacity;
u8 r1;
u16 i;
u16 temp;
if(SD_GetCSD(csd)!=0)
return 0; //未成功获取CSD寄存器数据退出
if((csd[0]&0xC0)==0x40) //如果CSD寄存器版本为v2.0
{
Capacity=((u32)csd[8])<<8;
Capacity+=(u32)csd[9]+1;
Capacity = ((u32)Capacity)/2;
//Capacity = (Capacity)*1024; //得到扇区数
//Capacity*=512; //得到字节数
}
else //如果CSD寄存器版本是v1.0
{
i = csd[6]&0x03;
i<<=8;
i += csd[7];
i<<=2;
i += ((csd[8]&0xc0)>>6);
r1 = csd[9]&0x03;
r1<<=1;
r1 += ((csd[10]&0x80)>>7);
r1+=2;
temp = 1;
while(r1)
{
temp*=2;
r1--;
}
Capacity = ((u32)(i+1))*((u32)temp);
i = csd[5]&0x0f;
temp = 1;
while(i)
{
temp*=2;
i--;
}
Capacity *= (u32)temp; //得到字节数
}
return (u32)Capacity; //返回SD卡容量(字节)
}
//@brief:singleblock读取
//@param:sector 数据地址(扇区地址)
//@param:*buffer 指向存储读回数据的缓冲的指针
//@retval:0:正确 r1:命令响应
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer)
{
u8 r1;
SPI2_SetSpeed(SPI_BaudRatePrescaler_256 ); //SPI4时钟频率配置为45MHz
if(SD_Type!=SD_TYPE_V2HC) //如果不是SDHC卡
{
sector = sector<<9; //512*sector即物理扇区的边界对齐地址
}
r1 = SD_SendCommand(CMD17,sector, 1); //发送CMD17 读单块命令
if(r1 != 0x00) return r1; //未接收到CMD17的正确响应退出
r1 = SD_ReceiveData(buffer, 512, RELEASE); //一个扇区为512字节 读取数据并释放总线
if(r1 != 0)
return r1; //读取数据失败退出
else
return 0; //读取数据成功
}
//@brief:multiblock读取
//@param:sector 数据地址(扇区地址)
//@param:*buff 指向存储读回数据的缓冲的指针
//@param:count 要读取的扇区数量
//@retval:0:正确 count:未处理完扇区数 r1:命令响应
u8 SD_ReadMultiBlock(u8 *buffer, u32 sector, u32 count)
{
u8 r1; //u8 buffer;
SPI2_SetSpeed(SPI_BaudRatePrescaler_2); //SPI4时钟频率配置为45MHz
if(SD_Type != SD_TYPE_V2HC)
{
sector = sector<<9;
}
sector = sector;
r1 = SD_SendCommand(CMD18, sector, 1); //发送CMD18 读多块命令
if(r1 != 0x00) return r1;
do //开始接收数据
{
if(SD_ReceiveData((u8 *)buffer, 512, NO_RELEASE) != 0x00) //读取数据完成后不释放总线
{
break; //读取数据失败退出
}
buffer += 512;
}while(--count); //数据接收全部完成
SD_SendCommand(CMD12, 0, 1); //全部传输完成,发送停止命令
SPI_SD_CS_HIGH();//SD_CS=1; //释放总线
SPI2_ReadWriteByte(0xFF);
if(count != 0)
return count; //如果数据传输中途因错误退出,返回剩余扇区个数
else
return 0;
}
//@brief:SD卡繁忙检测
//@param:
//@retval:0:空闲 1:繁忙
u8 SD_WaitReady(void)
{
u8 r1;
u16 retry=0;
do
{
r1 = SPI2_ReadWriteByte(0xFF); //当SD卡繁忙,数据线会被拉低;当SD卡结束繁忙后,数据线会被拉高
retry++;
if(retry==0xfffe)
return 1;
}while(r1!=0xFF);
return 0;
}
//@brief:singleblock写入
//@param:sector 数据地址(扇区地址)
//@param:*data 指向存储要写入SD卡的数据的缓冲区的指针
//@retval:0:正确 1:超时 r1:命令响应
u8 SD_WriteSingleBlock(u32 sector, const u8 *data)
{
u8 r1;
u16 i;
u16 retry;
SPI2_SetSpeed(SPI_BaudRatePrescaler_2); //SPI4时钟频率配置为45MHz
if(SD_Type!=SD_TYPE_V2HC) //如果不是SDHC卡,将sector地址转为byte地址
{
sector = sector<<9;
}
r1 = SD_SendCommand(CMD24, sector, 0x00); //发送CMD24 写扇区命令
if(r1 != 0x00)
{
return r1;
}
SPI_SD_CS_LOW();//SD_CS = 0; //开始准备写入数据
SPI2_ReadWriteByte(0xff); //先发3个空数据,等待SD卡准备好
SPI2_ReadWriteByte(0xff);
SPI2_ReadWriteByte(0xff);
SPI2_ReadWriteByte(0xFE); //发送数据发送起始符号
for(i=0;i<512;i++) //发送一个sector的数据
{
SPI2_ReadWriteByte(*data++);
}
SPI2_ReadWriteByte(0xff); //发送2个无效CRC校验
SPI2_ReadWriteByte(0xff);
r1 = SPI2_ReadWriteByte(0xff); //等待SD卡的数据响应符号
if((r1&0x1F)!=0x05) //如果为r1=0x05则数据写入成功
{
SPI_SD_CS_HIGH();//SD_CS = 1;
return r1; //否则释放总线并退出
}
retry = 0; //等待操作完成
while(!SPI2_ReadWriteByte(0xff)) //SD卡自编程时,数据线被拉低
{
retry++;
if(retry>65534) //如果超时写入未完成,退出报错
{
SPI_SD_CS_HIGH();//SD_CS = 1;
return 1; //写入超时,返回1
}
}
SPI_SD_CS_HIGH();//SD_CS = 1; //写入完成,片选置1
SPI2_ReadWriteByte(0xff);
return 0;
}
//@brief:multiblock写入
//@param:sector 数据地址(扇区地址)
//@param:*data 指向存储要写入SD卡的数据的缓冲区的指针
//@param:count 要写入的扇区数量
//@retval:0:正确 1:超时 count:未处理完扇区数 r1:命令响应
u8 SD_WriteMultiBlock(const u8 *data, u32 sector, u8 count)
{
u8 r1;
u16 i;
SPI2_SetSpeed(SPI_BaudRatePrescaler_2); //SPI4时钟频率配置为45MHz
if(SD_Type != SD_TYPE_V2HC)
{
sector = sector<<9;
}
/*if(SD_Type != SD_TYPE_MMC)
{
r1 = SD_SendCommand(ACMD23, count, 0x01); //启用ACMD23指令使能预擦除
}*/
r1 = SD_SendCommand(CMD25, sector, 0x01); //发送CMD25 写多块命令
if(r1 != 0x00) return r1;
SPI_SD_CS_LOW();//SD_CS = 0; //开始准备数据传输
SPI2_ReadWriteByte(0xff); //发送3个空数据让SD卡准备好
SPI2_ReadWriteByte(0xff);
SPI2_ReadWriteByte(0xff);
do //下面是N个sector循环写入的部分
{
SPI2_ReadWriteByte(0xFC); //发送数据传输起始符号0xFC,表明是多块写入
for(i=0;i<512;i++) //发1个sector的数据
{
SPI2_ReadWriteByte(*data++);
}
SPI2_ReadWriteByte(0xff); //发2个伪CRC
SPI2_ReadWriteByte(0xff);
r1 = SPI2_ReadWriteByte(0xff); //等待SD卡回应
if((r1&0x1F)!=0x05) //如果r1=0x05则表示数据写入成功
{
SPI_SD_CS_HIGH();//SD_CS = 1; //写入失败则释放总线退出
return r1;
}
if(SD_WaitReady()==1) //检测SD卡忙信号
{
SPI_SD_CS_HIGH();//SD_CS = 1; //如果长时间写入未完成,释放总线并退出
return 1;
}
}while(--count);
SPI2_ReadWriteByte(0xFD); //发送数据传输结束符号0xFD
if(SD_WaitReady()) //等待准备好
{
SPI_SD_CS_HIGH();//SD_CS = 1; //超时未退出繁忙则释放总线并退出
return 1;
}
SPI_SD_CS_HIGH();//SD_CS = 1; //写入完成,片选置1
SPI2_ReadWriteByte(0xff);
return count; //返回count值,如果写完,则count=0,否则count=未写完的sector数
}
//读SD卡
//buf:读数据缓存区
//sector:扇区地址
//cnt:扇区个数
//返回值:错误状态;0,正常;其他,错误代码;
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
u8 sta=0;
long long lsector=sector;
u8 n;
lsector<<=9;
if((u32)buf%4!=0)
{
for(n=0;n<cnt;n++)
{
sta=SD_ReadSingleBlock(lsector+512*n, SPISD_DATA_BUFFER);//单个sector的读操作
memcpy(buf,SPISD_DATA_BUFFER,512);
buf+=512;
}
}else
{
if(cnt==1)sta=SD_ReadSingleBlock(lsector, buf); //单个sector的读操作
else sta=SD_ReadMultiBlock(buf,lsector,cnt);//多个sector
}
return sta;
}
//写SD卡
//buf:写数据缓存区
//sector:扇区地址
//cnt:扇区个数
//返回值:错误状态;0,正常;其他,错误代码;
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{
u8 sta=0;
u8 n;
long long lsector=sector;
lsector<<=9;
if((u32)buf%4!=0)
{
for(n=0;n<cnt;n++)
{
memcpy(SPISD_DATA_BUFFER,buf,512);
sta=SD_WriteSingleBlock(lsector+512*n, SPISD_DATA_BUFFER);//单个sector的写操作
buf+=512;
}
}else
{
if(cnt==1)sta=SD_WriteSingleBlock(lsector, buf); //单个sector的写操作
else sta=SD_WriteMultiBlock(buf,lsector,cnt); //多个sector
}
return sta;
}
|
最佳答案
查看完整内容[请看2#楼]
额,把系统时钟初始化的部分改了终于好了。。。要不是我从其他地方找了个程序可以用,一点点对比发现时钟不一样。。。靠我自己一点点找死也找不出来这个原因。。。
还是不明白单独的用着是好的,合并为啥就坏了。。
|