⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 自己写的SD卡读写程序。适用于初学者。是自己根据SD时序编写的代码。希望能对初学者有帮助。
💻 C
字号:
#include <hidef.h>      /* common defines and macros */
#include <mc9s12dg128.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dg128b"

uint Tcount;
uint displayi=0;
uchar RD_Succeed=0;
#define XTAL  352

void CRG_Init(void);
void Sd_CS(unsigned char);
unsigned char SdWrCmd(unsigned char *);
unsigned char Sd_Init(void);
unsigned char MMCCID(void);
unsigned char SdRdBlock1(unsigned long );
unsigned char SdWrBlock1(unsigned long );
void SPI0_Init(void);
void SPIHiSPD(void);  /*  用于SD初始化后提高MCU SPI速度 */
uchar SPI0_Transmit(uchar );
void delay_1ms(void);
void delay_nus(unsigned int);
void delay_nms(unsigned int);
void ECTinit(void);

/* 全局变量 */
unsigned char sector1[512];
unsigned char sector2[512];
/*******************************
*          主 函 数
*******************************/

void main(void) 
{
  /* put your own code here */
  unsigned int i;
  
  DDRJ=0Xff;
  DDRA=0XFF;
  DDRM=0X00;
  DDRS=0XFF;
  PORTA=0XFF;
  PTJ_PTJ6=1;
  PTJ_PTJ7=1;
  
  CRG_Init();
  ECTinit();
  SPI0_Init();
  EnableInterrupts;
  //for(;;) {} /* wait forever */
  /* please make sure that you never leave this function */
  delay_1ms();
  Sd_Init();
  //delay_1ms();
	for(i=0; i<512; i++)
	{
	  //if(i%2==0)
	    sector1[i]=i;
	  //else
	    //sector1[i]=i;
	}
	/*for(i=0; i<512; i++)
	{
	  if(i%2==0)
	    sector2[i]=0xaa;
	  else
	    sector2[i]=0x55;
	} */
//	delay_nms(100);  

	// 测试1:将数据写入第1个扇区
	SdWrBlock1(1);	       //but when write 512bytes to the second sector,the address must be the followint format:
	                       // example,write 512bytes to the second sector,the address is: 0 + (块号数 * 块长度) 
	                       // that is :0 + 1 * 512  
	delay_1ms(); 
	// 测试2:将第1个扇区的数据读出
	RD_Succeed=SdRdBlock1(1);  //
	//delay_nms(100); 
	
    //for(i=0; i<512; i++)
	    //uart1_send(sector[i]);     /* */
	for(;;)
	{
  //	SPI0_Transmit(0xff); 
	}
}

/************************************
*         Sd卡片选-0选中/1不选中
************************************/
void Sd_CS(unsigned char cs)
{
   if(cs==0)
      PTS_PTS3  = 0;  //TXD1 
   else
      PTS_PTS3  = 1;  //TXD1 
}

/*******************************
*        SD命令发送
*******************************/
unsigned char SdWrCmd(unsigned char *cmd)
{
  unsigned char i=0,k=0;
	unsigned char temp=0XFF;
  //MMCCS(0);		   			/* 片选无效 */
  Sd_CS(1);
	SPI0_Transmit(0XFF);				/* 发送8个时钟 */
	Sd_CS(0);		   			/* 片选有效 */
	
  // delay_nms(400);

	for(i=0; i<6; i++)
	{
	    SPI0_Transmit(*(cmd++));		/* 发送命令 */   
	}
	//SPI0_Transmit(0XFF);
	while(temp==0XFF)
	{
	  temp = SPI0_Transmit(0XFF);  /* 等待回复 */
		if(k++>200)             /* 超时返回 */
		{
		    return temp;
		}
	}
    return temp;
}


/*******************************
*        SD复位及初始化
*******************************/
unsigned char Sd_Init(void)
{
  unsigned int timeout;
	unsigned char i=0,temp=2;
  unsigned char cmd[]={0x40,0x00,0x00,0x00,0x00,0x95};  
  
	//delay_nms(500);
	/* 发送一定数量的时钟脉冲 */
    for(i=0;i<0x10;i++) 
    {
        SPI0_Transmit(0xff);
    }
  //Sd_CS(0);		   			/* 片选有效 */
	/* 发送CMD0复位命令*/
	if(SdWrCmd(cmd)!=0X01) 	/* 发送CMD0复位命令 */
	{
	  PORTA_BIT0=0;//复位不成功则led1亮
	  delay_nms(5);
	  PORTA_BIT0=1;
	  return 0;
	} 
	/* 发送CMD1初始化命令 */
	cmd[0]=0X41;
	cmd[5]=0XFF;
	while(SdWrCmd(cmd)!=0X00)   	/* 发送CMD1初始化命令 */
	{
    if(timeout++ > 0XFFFE)     /* 等待初始化完成 */
    {
      PORTA_BIT1=0;
      delay_nms(5);
      PORTA_BIT1=1;
      return 0;            /* 容量大的MMC卡需要用比较长时间 */
    }
	}  
	SPIHiSPD();   				 /*  提高MCU SPI速度 */
    return 1;
}

/*******************************
*        读取MMC-CID寄存器
*******************************/
unsigned char MMCCID(void)
{
   unsigned char i;
   unsigned char cmd[]={0x40,0x00,0x00,0x00,0x00,0xff};  
	 cmd[0]=0X40+10;
	 if(SdWrCmd(cmd)!=0X00)     /* 发送CMD9 */
	   return 0;                /* 读取失败 */
	 for(i=0;i<16;i++)
	    //uart1_send(spi_send(0XFF));
		SPI0_Transmit(0XFF);
	 return 1;
}

/*******************************
*        读取ONE BLOCK数据
*         address-扇区地址
*******************************/
unsigned char SdRdBlock1(unsigned long address)
{
     unsigned int i;
	 //unsigned char temp;
     unsigned char cmd[]={0x40,0x00,0x00,0x00,0x00,0xff}; 
                        /*0x51                     0xff*/ 
     cmd[0]=0X40+17;	/* 0X40+17=0x51;     READ SINGLE BLOCK */
	 address=address<<9;         /* address*512,取512的整数倍 */
	 cmd[1]=(address>>24);
	 cmd[2]=(address>>16);
	 cmd[3]=(address>>8);
	 cmd[4]=(address>>0);
	 if(SdWrCmd(cmd)!=0X00)     /* 发送CMD17 */
	     return 0;               /* 读取失败 */
     while(SPI0_Transmit(0XFF)!=0XFE)
	 {
	     //asm("nop");			 /* 等待数据接受开始,受到0XFE表示开始 */
	 }
	 for(i=0;i<512;i++)          /* 读取数据 */
	 {
	     sector2[i]=SPI0_Transmit(0XFF);
	 }
	 SPI0_Transmit(0XFF);			 /* 取走CRC字节 */
	 SPI0_Transmit(0XFF);
	 return 1; 
}
	
/*******************************
*        写ONE BLOCK数据
*        address-扇区地址
*******************************/
unsigned char SdWrBlock1(unsigned long address)
{
     unsigned int i;
	 unsigned char temp;
     unsigned char cmd[]={0x40,0x00,0x00,0x00,0x00,0xff};  
	 cmd[0]=0x40+24;              /* WRITE SINGLE BLOCK */
	 address=address<<9;          /* address*512,取512的整数倍 */
	 cmd[1]=(address>>24);
	 cmd[2]=(address>>16);
	 cmd[3]=(address>>8);
	 cmd[4]=(address>>0);
	 if(SdWrCmd(cmd)!=0X00)     /* 发送CMD24 */
	     return 0;               /* 写入失败 */
	 SPI0_Transmit(0XFF);             /* 发送填冲字节 */
	 SPI0_Transmit(0XFE);             /* 发送数据开始标志0XFE */
	 for(i=0;i<512;i++)          /* 写入数据 */
	 {
	     SPI0_Transmit(sector1[i]);
	 }
	 SPI0_Transmit(0XFF);			 /* 写入CRC字节 */
	 SPI0_Transmit(0XFF);
	 temp=SPI0_Transmit(0XFF);		 /* 读取XXX0 0101字节 */
	 temp=temp&0X1F;
	 if(temp!=0X05) 
	 {
	    PORTA_BIT2=0;
	    delay_nms(5);
	    PORTA_BIT2=1;
	    return 0; 				 /* 写入失败 */
	 }
	 while(SPI0_Transmit(0XFF)==0X00)
	 {
	     //asm("nop");			 /* BUSY等待 */
	 }
	 return 1;
}
	
/************************************
*          SPI初始化
************************************/
// SPI0 initialization
void SPI0_Init(void)
{
  uchar temp;
  
  //Design for 80pin Device
  MODRR |= MODRR_MODRR4_MASK; //Setup PIM, Reroute SPI0 to PORTM
  DDRM |= 0x30;               //Set MOSI0(PM4),SCK0(PM5) as Output Pin
  PERM |= 0x38;               //MOSI0 SCK0 Pull up/down Enable
  //Design for 80pin Device
  SPI0BR = 0x03;    //BaudRate = BusClock/(SPPR+1)/(2^(SPR+1))  2分频
                    //[7]N/C[6]SPPR2[5]SPPR1[4]SPPR0[3]N/C[2]SPR2[1]SPR1[0]SPR0
  SPI0CR1 = 0x52;   //Enable SPI, Master, Disable SPI Interrupt, SPI Mode 0, MSB first
  SPI0CR2 = 0x10;   //此寄存器的bit4=1与SPI0CR1的bit1=1就配置!SS为输出
  temp = SPI0SR;
  temp = SPI0DR;    //Claer SPI Flags
}

// SPI0 Transmit Function
uchar SPI0_Transmit(uchar Data)
{
  SPI0DR = Data;
  while(!(SPI0SR & 0x80));
  return SPI0DR;
}

/************************************
*        SPI转入高速模式
************************************/
void SPIHiSPD(void)
{
    SPI0BR = 0x02;    //BaudRate = BusClock/(SPPR+1)/(2^(SPR+1))  0分频
}
/******************************************
* 名称:  DelayMs
* 描述:  软件延时函数,单位ms
******************************************/
void delay_nus(unsigned int n)
{
  unsigned int i,j;
  for(i=0;i<n;i++)
  {
    for(j=0;j<(XTAL/90);j++);
  }
}

void delay_nms(unsigned int n)
{
  unsigned int i;
  for(i=0;i<n;i++)  delay_1ms();
}

void delay_1ms(void)
{
  unsigned int  i;
  for(i=0;i<(XTAL*17);i++);
}


#pragma CODE_SEG NON_BANKED
interrupt 8 void near Timer0(void)  //用于检测灯
{
   TFLG1|=0X01;//清标志                           
   TC0+=1000;   //每隔1ms中断一次 Time0count=1000
   Tcount++;
   if(Tcount==4400)    //count to 1s
   {
      Tcount=0;
      if (RD_Succeed==1) //read the block succeed
      {
        displayi++;
        if(displayi==512)
        displayi=0;
        PORTA=~sector2[displayi]; // 取反给porta
      }
      PTJ_PTJ7=0; 
      delay_nms(5);
      PTJ_PTJ7=1;     
   }
}
#pragma CODE_SEG DEFAULT

void ECTinit(void)
  {
    TSCR2=0X03;  //禁止定时溢出中断 
    TIOS_IOS0=1; //输出比较
    TFLG1=0Xff;//清标志

    TIE=0X01; //通道 0、4中断使能
    TSCR1_TEN=1;  //timer enable
  }
  
/****************CRG initial*****************/
void CRG_Init(void)
{   
  //BusFreq = Fosc*(SYNR+1)/(REFDV+1)
  
  SYNR=0x0A;           //Set Bus Clock is 35.2MHz.      Fosc=16Mhz
  REFDV=0x04;          //Set for Serial Communication.
  
  //SYNR=0x0A;           //Set Bus Clock is 22MHz. 
  //REFDV=0x07;          //Set for Serial Communication.
  
  //SYNR=0x09;           //Set Bus Clock is 32.0MHz
  //REFDV=0x04;
  
  //SYNR=0x09;           //Set Bus Clock is 40.0MHz
  //REFDV=0x03;
  
  for(;;)              //wait for the frq of the desired tolerance
  {
    if(CRGFLG_LOCK==1)
    {			
      CLKSEL=0X80;											
      break;
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -