📄 main.c
字号:
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
/***************************************************************
*这个程序可以实现读取SD卡中的数据
*存在的问题:只能2G以下,以上就不能支持了!
****************************************************************/
/***************************************************************
*变量的初始化及宏定义
*
****************************************************************/
typedef unsigned char UINT8; /*unsigned 8 bit definition */
typedef unsigned short UINT16; /*unsigned 16 bit definition*/
typedef unsigned long UINT32; /*unsigned 32 bit definition*/
typedef signed char INT8; /*signed 8 bit definition */
typedef short INT16; /*signed 16 bit definition*/
typedef long int INT32; /*signed 32 bit definition*/
typedef union
{
UINT8 bytes[4];
UINT32 lword;
}T32_8;
#define BYTE unsigned char
#define UL unsigned long
#define UINT unsigned int
#define SD_Sel() PTM_PTM3=0 //低电平
#define SD_deSel() PTM_PTM3=1 //高电平
#define SD_BLOCK_SIZE (0x00000200)
#define SD_BLOCK_SHIFT (9)
#define BLOCK_SIZE 512
//命令指令!
#define CMD0 0 //卡复位
#define CMD8 8 /* SEND_IF_COND */
#define CMD9 9 //命令9 ,读CSD数据
#define CMD10 10 //命令10,读CID数据
#define CMD12 12 //命令12,停止数据传输
#define CMD16 16 //命令16,设置SectorSize 应返回0x00
#define CMD17 17 //命令17,读sector
#define CMD18 18 //命令18,读Multi sector
#define ACMD23 23 //命令23,设置多sector写入前预先擦除N个block
#define CMD24 24 //命令24,写sector
#define CMD25 25 //命令25,写Multi sector
#define ACMD41 0x80+41 //命令41,应返回0x00
#define CMD55 55 //命令55,应返回0x01
#define CMD58 58 //命令58,读OCR信息
#define CMD59 59 //命令59,使能/禁止CRC,应返回0x00
#define SD_WAIT_CYCLES 200
/***************************************************************
*变量的声明定义
*
****************************************************************/
T32_8 gu8SD_Argument;
UINT8 gu8SD_CID[16];//联合体
volatile BYTE data_buff[512];
enum
{
SD_OK,
SD_IDLE
};
//所有的子函数
/***************************************************************
*spi的初始化
*
****************************************************************/
void SPI_Init(void)
{
MODRR =0;
MODRR_MODRR4=1; //使用PM口
DDRM|=0x38; //SCK0=1,MOSI=1,SS0=1
SPI0CR1 = 0x52; //CPOL=0,CPHA=0;//CPOL=1,CPHA=1;
SPI0CR2 = 0x10;
SPI0BR = 0x37; // 80M / 256 = 312.5k
}
/***************************************************************
*spi的high设置
*
****************************************************************/
void SPI_High()
{
// SPI0BR = 0x00; //BR=busclk/((SPPR + 1)· 2^(SPR + 1))=// 60M / 16 = 3.75M
SPI0BR = 0x05; //BR=busclk/((SPPR + 1)· 2^(SPR + 1))=// 60M / 64 = 0.9M
}
/***************************************************************
*SPI读取一个字节
*
****************************************************************/
byte SPI_RecByte(byte val) //SPI读一个字节
{
while(!SPI0SR_SPTEF);
SPI0DRL=0xFF;
while(!SPI0SR_SPIF);
return(SPI0DRL);
}
/***************************************************************
*SPI发送一个字节
*
****************************************************************/
void SPI_SendByte(byte data) //SPI写一个字节,其中is_init为1时,写的速度放慢
{
while(!SPI0SR_SPTEF);
(void)SPI0SR; //清除标志位的一种特殊写法!
SPI0DRL=data;
while(!SPI0SR_SPIF);
(void)SPI0DR;
}
/***************************************************************
*设定总线时钟80M
*
****************************************************************/
void SetBusCLK_80M(void)
{
CLKSEL=0X00; //disengage PLL to system
PLLCTL_PLLON=1; //turn on PLL
SYNR =0xc0 | 0x09; // 已知:fOSC=16m 按照上面的设置 SYNDIV=9 REFDIV=1 则 fVCO= 2*16*10/2 = 160m
// 则 VCOFRQ[7:6]= 11 即 SYNR=0xc0 | 中0xc0的由来
// 这里面得问题是 80MHz < fVCO <= 120MHz 11他到底可不可行?还是最高120m?
REFDV=0x80 | 0x01; // 已知:fOSC=16m 按照上面的设置 REFDIV=1 则 fREF= 16/2 = 8m
// 则 REFFRQ[7:6]= 10 即 REFDV=0x80 |中0x80的由来
POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV) = 2*16*10/2 =160MHz
_asm(nop); //BUS CLOCK=80M
_asm(nop);
while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it;
CLKSEL_PLLSEL =1; //engage PLL to system;
}
/***************************************************************
*SD卡发送协议命令
*
****************************************************************/
UINT8 SD_SendCommand(UINT8 u8SDCommand,UINT32 ARG)
{
UINT8 u8Counter;
volatile UINT8 u8Temp=0;
SD_Sel();
/* Send Start byte */
SPI_SendByte(u8SDCommand|0x40);
/* Send Argument */
//for(u8Counter=0;u8Counter<4;u8Counter++)
// SPI_SendByte(gu8SD_Argument.bytes[u8Counter]);
SPI_SendByte(ARG>>24);
SPI_SendByte(ARG>>16);
SPI_SendByte(ARG>>8);
SPI_SendByte(ARG);
/* Send CRC */
SPI_SendByte(0x95);
/* Response RHandler */
u8Counter=SD_WAIT_CYCLES;
do
{
u8Temp=SPI_RecByte(0xff);
u8Counter--;
}while((u8Temp == 0xff) && u8Counter > 0);
SD_deSel();
SPI_RecByte(0xff); // Dummy SPI cycle
return u8Temp;
}
/***************************************************************
*SD卡发送协议命令(没有片选无效信号)
*
****************************************************************/
UINT8 SD_SendCommand_Nodesert_Crc(UINT8 u8SDCommand,UINT32 ARG,UINT8 crc)
{
UINT8 u8Counter;
volatile UINT8 u8Temp=0;
SD_Sel();
/* Send Start byte */
SPI_SendByte(u8SDCommand|0x40);
/* Send Argument */
//for(u8Counter=0;u8Counter<4;u8Counter++)
// SPI_SendByte(gu8SD_Argument.bytes[u8Counter]);
SPI_SendByte(ARG>>24);
SPI_SendByte(ARG>>16);
SPI_SendByte(ARG>>8);
SPI_SendByte(ARG);
/* Send CRC */
SPI_SendByte(crc);
/* Response RHandler */
u8Counter=SD_WAIT_CYCLES;
do
{
u8Temp=SPI_RecByte(0xff);
u8Counter--;
}while((u8Temp == 0xff) && u8Counter > 0);
return u8Temp;
}
/***************************************************************
*sd的初始化 非常关键
*2G以下和4G以上的SD_Init()是有区别的!
****************************************************************/
UINT8 SD_Init(void)
{
UINT8 i,buf[4];
UINT8 res;
UINT32 arg;
SPI_Init(); // SPI Initialization
SD_deSel();
for(i=0;i<12;i++)
SPI_RecByte(0xff); // Send 12*8=96 clocks
SD_Sel();
SPI_RecByte(0xff);
SPI_RecByte(0xff);
/* IDLE Command */
arg=0;
if(SD_SendCommand(CMD0,arg)!=0x01)
{
return(1); // Command IDLE fail
}
arg=0x1aa;
res = SD_SendCommand_Nodesert_Crc(CMD8,arg,0x87);
if(res ==0x01)//sdv2
{
buf[0]= SPI_RecByte(0xff);
buf[1]= SPI_RecByte(0xff);
buf[2]= SPI_RecByte(0xff);
buf[3]= SPI_RecByte(0xff);
SD_Sel();
SPI_RecByte(0xff);
if(buf[2]==0x01&&buf[3]==0xaa) //accmd 41
{
for(i=0;i<200;i++)
{
res = SD_SendCommand(CMD55,0X00);
arg = 0x40000000;
res = SD_SendCommand(41,arg);
if(res==0x00) break;
}
res = SD_SendCommand_Nodesert_Crc(58,0x00,0x95);
if(res==0x00)
{
buf[0]= SPI_RecByte(0xff);
buf[1]= SPI_RecByte(0xff);
buf[2]= SPI_RecByte(0xff);
buf[3]= SPI_RecByte(0xff);
SD_Sel();
SPI_RecByte(0xff);
}
}
}
else //sdv1
{
/* Initialize SD Command */
while(SD_SendCommand(1,arg));
/* Block Length */
if(SD_SendCommand(CMD16,512))
{
return(1); // Command IDLE fail
}
}
SD_deSel();
SPI_High();
SPI_SendByte(0xFF);
SPI_SendByte(0xFF);
// // SPI_RecByte(0xff); // Dummy SPI cycle
return(0);
}
/***************************************************************
*对SD卡进行读写操作????
*
****************************************************************/
UINT8 SD_Read_Block(UINT32 u16SD_Block,UINT8 *pu8DataPointer)
{
UINT8 u8Temp=0;
UINT16 u16Counter;
SD_Sel();
//以下两行限制了存储卡的容量!
// gu8SD_Argument.lword=u16SD_Block;
// gu8SD_Argument.lword=gu8SD_Argument.lword<< SD_BLOCK_SHIFT;
if(SD_SendCommand(CMD17,u16SD_Block<<9))
{
SD_deSel();
return(4); // Command IDLE fail
}
SD_Sel();
while(u8Temp!=0xFE)
u8Temp= SPI_RecByte(0xff);
for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++)
*pu8DataPointer++=SPI_RecByte(0xff);
SPI_RecByte(0xff); // Dummy SPI cycle
SPI_RecByte(0xff); // Dummy SPI cycle
SD_deSel();
SPI_RecByte(0xff); // Dummy SPI cycle
return(0);
}
/***************************************************************
*主函数
*
****************************************************************/
void main(void) {
/* put your own code here */
UL SECTOR=15064; //存储设置在80扇区
UINT8 res;
DDRB =0XFF;
SetBusCLK_80M();
//Init_Dev() ;//设置总线频率以及串口连接PC的初始化
EnableInterrupts;
// SD_Reset();
res= SD_Init();
if(res==0) //成功的应答信号是0
{
PORTB = 0X00; //如果SD卡初始化成功,就会点亮所有的灯!
SD_Read_Block(SECTOR,data_buff); //对SD卡进行读操作!
//从SD卡中读取数据回S12中
}
/* *///
for(;;) {
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -