📄 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 = 0x5e; //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,UINT8 u8SDResponse)
{
UINT8 u8Counter;
volatile UINT8 u8Temp=0;
/* Send Start byte */
SPI_SendByte(u8SDCommand);
/* Send Argument */
for(u8Counter=0;u8Counter<4;u8Counter++)
SPI_SendByte(gu8SD_Argument.bytes[u8Counter]);
/* Send CRC */
SPI_SendByte(0x95); //这个校验位仅仅适用于2G以下!HOW TO SOLVE?
/* Response RHandler */
u8Counter=SD_WAIT_CYCLES;
do
{
u8Temp=SPI_RecByte(0xff);
u8Counter--;
}while((u8Temp != u8SDResponse) && u8Counter > 0);
if(u8Counter) return(0);//正确返回0,错误返回1
else return(1);
}
/***************************************************************
*sd的初始化 非常关键!
*
****************************************************************/
UINT8 SD_Init(void)
{
UINT8 i;
SPI_Init(); // SPI Initialization
SD_deSel();
for(i=0;i<12;i++)
SPI_RecByte(0xff); // Send 12*8=96 clocks
SD_Sel();
gu8SD_Argument.lword=0;
SPI_RecByte(0xff);
SPI_RecByte(0xff);
/* IDLE Command */
SD_Sel();
if(SD_SendCommand(CMD0|0x40,SD_IDLE)) //发送CMD0
{
SD_deSel();
return(1); // Command IDLE fail
}
SD_deSel();
SPI_RecByte(0xff); // Dummy SPI cycle
/* Initialize SD Command */
SD_Sel();
while(SD_SendCommand(1|0x40,SD_OK)); //发送CMD1
SD_deSel();
SPI_RecByte(0xff); // Dummy SPI cycle
/* Block Length */
SD_Sel();
gu8SD_Argument.lword=SD_BLOCK_SIZE;
if(SD_SendCommand(CMD16|0x40,SD_OK)) //发送CMD0
{
SD_deSel();
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|0x40,SD_OK))
{
SD_deSel();
return(4); // Command IDLE fail
}
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=496; //存储设置在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 + -