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

📄 lqsdok.c

📁 mc9s12dg128b单片机操作SD的源码
💻 C
字号:
/**************************************************************************************
龙丘MC9S12(DG128)多功能开发板
编写:邱钊鹏
Designed by Chiu Sir
E-mail:chiusir@163.com
软件版本:V1.1
最后更新:2008年11月12日
相关信息参考下列地址:
博客:  http://longqiu.21ic.org
淘宝店:http://shop36265907.taobao.com
------------------------------------
Code Warrior 4.6
Target : MC9S12DG128B
Crystal: 16.000Mhz
busclock:16.000MHz
pllclock:32.000MHz
目录路径:F:\IVTech\  
*****************************************************************************************/

#include <mc9s12dg128.h>
#include "LQprintp.h"
#include "LQfun.h"

#define DDR_INI()         DDRT |= 0xFF          
#define SD_Sel()   PTS_PTS7=0        //低电平
#define SD_deSel() PTS_PTS7=1        //高电平

extern U8 RXBUF[];
extern U8 TXBUF[];

#pragma CODE_SEG DEFAULT     
void New_Buf8(U8 buffer[])
{
    //-- Tx & Rx Buffer initialize
    int i, j=0;
    for(i=0;i<512;i++)	//128[word]*16[blk]=8192[byte]
		*(buffer+i)='x';   
}

void CLS_Buf8(U8 buffer[])
{
    //-- Flushing Rx buffer 
    int i;     
    for(i=0;i<512;i++)	//128[word]*16[blk]=8192[byte]
		*(buffer+i)=0;
}
void View_Buf8(U8 buffer[])
{
    int i=0;
    for(i=0;i<512;i++)
    {          
        if((i%32)==0)	  printp( "\n" );
        printp("%02x,", buffer[i]);
    }    
}  
//写、读一个字节
U8 SPI_RdWr_Byte(U8 val)
{
	SPI0DR = val;
	while(!(SPI0SR_SPIF));
	return SPI0DR;
}
//sd卡初始化
void SD_Init(void)
{
	SPI_Init();
	SD_deSel();
}

//sd卡写命令
U8 SD_Send_Cmd(U8 cmd, U32 arg)
{
	U8 r1;
	U8 retry=0;
	
	SPI_RdWr_Byte(0xff);
	SD_Sel();
	
	SPI_RdWr_Byte(cmd | 0x40);//分别写入命令
	SPI_RdWr_Byte(arg>>24);
	SPI_RdWr_Byte(arg>>16);
	SPI_RdWr_Byte(arg>>8);
	SPI_RdWr_Byte(arg);
	SPI_RdWr_Byte(0x95);
	
	while((r1 = SPI_RdWr_Byte(0xff)) == 0xff)//等待响应,
		if(retry++ > 8) break;//超时退出

	SD_deSel();

	return r1;//返回状态值
}

//sd卡复位
U8 SD_Reset(void)
{
	U8 i;
	U8 retry;
	U8 r1=0;
	retry = 0;
	//SPI_Low();
	do
	{
		for(i=0;i<10;i++) SPI_RdWr_Byte(0xff);
		r1 = SD_Send_Cmd(0, 0);//发idle命令
		retry++;
		if(retry>10) return 1;//超时退出
	} while(r1 != 0x01);


	retry = 0;
	do
	{
		r1 = SD_Send_Cmd(1, 0);//发active命令
		retry++;
		if(retry>100) return 1;//超时退出
	} while(r1);
	//SPI_High();
	r1 = SD_Send_Cmd(59, 0);//关crc

	r1 = SD_Send_Cmd(16, 512);//设扇区大小512

	return 0;//正常返回
}
#pragma CODE_SEG DEFAULT 
//读一个扇区
U8 Rd_Block(U32 sector, U8* buffer)
{
	U8 r1;          
	U16 i;
	//U8 retry=0;

	r1 = SD_Send_Cmd(17, sector<<9);//读命令 	
	if(r1 != 0x00) 		return r1;

	SD_Sel();
	//等数据的开始
	while(SPI_RdWr_Byte(0xff) != 0xfe);//if(retry++ > 50){SD_deSel();return 1;}

	for(i=0; i<512; i++)//读512个数据
	{
		*buffer++ = SPI_RdWr_Byte(0xff);
	}

	SPI_RdWr_Byte(0xff);//伪crc
	SPI_RdWr_Byte(0xff);  	
	SD_deSel();

	return 0;
} 

//写一个扇区
U8 Wt_Block(U32 sector, U8* buffer)
{
	U8 r1;
	U16 i;
	//U8 retry=0;
  if(sector<1) return 0xff;     //为了保护SD卡引导区,跳过该区
	r1 = SD_Send_Cmd(24, sector<<9);//写命令
	if(r1 != 0x00) return r1;

	SD_Sel();
	
	SPI_RdWr_Byte(0xff);
	SPI_RdWr_Byte(0xff);
	SPI_RdWr_Byte(0xff);

	SPI_RdWr_Byte(0xfe);//发开始符
	
	for(i=0; i<512; i++)//送512字节数据
	{
		SPI_RdWr_Byte(*buffer++);
	}
	
	SPI_RdWr_Byte(0xff);
	SPI_RdWr_Byte(0xff);
	
	r1 = SPI_RdWr_Byte(0xff);
	
	if( (r1&0x1f) != 0x05)//等待是否成功
	{
	  SD_deSel();
		return r1;
	}
	//等待操作完
	while(!SPI_RdWr_Byte(0xff));//if(retry++ > 50){SPI_CS_Deassert();return 1;}

  SD_deSel();

	return 0;
} 

//相当的好用!
U8 WriteFile(U8* str,U16 lenth)
{ 
  U16 i=0,startaddr=0x209;                                          //第一个文件的地址开始于0X208
  U32 record_bytes=0,from_blkhead_2_here=0; 
  
  lenth<<=1;  
  if(Rd_Block(0x1FF,RXBUF)) return 1;                               //偏移字节存放在0X1FF块地址里面
  record_bytes=(RXBUF[510]) | (RXBUF[509]<<8) | (RXBUF[508]<<16);   //文件字写之前已经有的节数    
  startaddr+=(record_bytes/512);
  if(Rd_Block(startaddr,RXBUF)) return 1;
  //if((RXBUF[0]==0xff)||(RXBUF[1]==0xff)) record_bytes+=2;
  from_blkhead_2_here=record_bytes%512;
  if((from_blkhead_2_here+lenth)<=512)
  {
    for(i=0;i<lenth;i+=2)
      *(RXBUF + i + from_blkhead_2_here) = *(str + (i>>1));
    if(Wt_Block(startaddr,RXBUF)) return 1;
    View_Buf8(RXBUF);
  } 
  else
  {
    for(i=from_blkhead_2_here;i<512;i+=2)
      *(RXBUF+from_blkhead_2_here) = *(str+ (i>>1) -from_blkhead_2_here);
    if(Wt_Block(startaddr,RXBUF)) return 1;
    printp("\naddress is:0x%04x",startaddr);
    View_Buf8(RXBUF);
    //CLS_Buf8(RXBUF);
    if(Rd_Block(startaddr+1,RXBUF)) return 1;
    //if((RXBUF[0]==0xff)||(RXBUF[1]==0xff)) record_bytes+=2;
    for(i=0;i<(from_blkhead_2_here+lenth - 512);i +=2)
      *(RXBUF+i) = *(str + (i>>1) + 512 - from_blkhead_2_here);
    if(Wt_Block(startaddr+1,RXBUF)) return 1;
    printp("\naddress is:0x%04x",startaddr+1);
    View_Buf8(RXBUF);    
  }  
  if(Rd_Block(0x1FF,RXBUF)) return 1;
  RXBUF[510]=(U8)( record_bytes+lenth);
  RXBUF[509]=(U8)((record_bytes+lenth)>>8);
  RXBUF[508]=(U8)((record_bytes+lenth)>>16);    
  if(Wt_Block(0x1FF,RXBUF)) return 1; 
  //View_Buf8(RXBUF);
  printp("\nfile bytes is:0x%02x%02x%02x",RXBUF[508],RXBUF[509],RXBUF[510]);
  return 0; 
}


/*
//总是覆盖
U8 WriteFile(U8* str,U16 lenth)
{ 
  U16 i=0,startaddr=0x209,from_blkhead_2_here=0;                    //第一个文件的地址开始于0X208
  U32 record_bytes=0; 
    
  if(Rd_Block(0x1FF,RXBUF)) return 1;                               //偏移字节存放在0X1FF块地址里面
  record_bytes=(RXBUF[510]) | (RXBUF[509]<<8) | (RXBUF[508]<<16);   //文件写之前已经有的节数         
  
  if(Rd_Block(startaddr,RXBUF)) return 1;
  startaddr += (record_bytes/256);
  if((RXBUF[0]==0xff)||(RXBUF[1]==0xff)) record_bytes++;  
  from_blkhead_2_here = record_bytes%256;  
  if((from_blkhead_2_here+lenth)<=256)
  {
    for(i=0; i<lenth; i++)
      *(RXBUF + ((i+ from_blkhead_2_here)<<1)) = *(str + i);
    if(Wt_Block(startaddr,RXBUF)) return 1;
    View_Buf8(RXBUF);
  } 
  else
  {
    for(i=0; i<(256-from_blkhead_2_here); i++)
      *(RXBUF + ((i + from_blkhead_2_here)<<1)) = *(str + i);
    if(Wt_Block(startaddr,RXBUF)) return 1;
    //View_Buf8(RXBUF);
    //CLS_Buf8(RXBUF);     
    if(Rd_Block(startaddr+1,RXBUF)) return 1;
    if((RXBUF[0]==0xff)||(RXBUF[1]==0xff))
    {
      record_bytes++;
      for(i=1; i<(from_blkhead_2_here+lenth - 255); i++)        // +1
      *(RXBUF + (i<<1)) = *(str + i + 255 - from_blkhead_2_here);  // -1
      if(Wt_Block(startaddr+1,RXBUF)) return 1;
    }
    else
    {
      for(i=0; i<(from_blkhead_2_here+lenth - 256); i++)        
      *(RXBUF + (i<<1)) = *(str + i + 256 - from_blkhead_2_here);  
      if(Wt_Block(startaddr+1,RXBUF)) return 1;
    }    
    printp("\n current address is:0x%04x",startaddr+1);
    View_Buf8(RXBUF);    
  }  
  if(Rd_Block(0x1FF,RXBUF)) return 1;
  RXBUF[510]=(U8)( record_bytes+lenth);
  RXBUF[509]=(U8)((record_bytes+lenth)>>8);
  RXBUF[508]=(U8)((record_bytes+lenth)>>16);    
  if(Wt_Block(0x1FF,RXBUF)) return 1; 
  //View_Buf8(RXBUF);
  printp("\nfile bytes is:0x%02x%02x%02x",RXBUF[508],RXBUF[509],RXBUF[510]);
  return 0; 
}


//相当的好用!
U8 WriteFile(U8* str,U16 lenth)
{ 
  U16 i=0,startaddr=0x209;                                          //第一个文件的地址开始于0X208
  U32 record_bytes=0,from_blkhead_2_here=0; 
  
  lenth<<=1;  
  if(Rd_Block(0x1FF,RXBUF)) return 1;                               //偏移字节存放在0X1FF块地址里面
  record_bytes=(RXBUF[510]) | (RXBUF[509]<<8) | (RXBUF[508]<<16);   //文件字写之前已经有的节数    
  startaddr+=(record_bytes/512);
  if(Rd_Block(startaddr,RXBUF)) return 1;
  //if((RXBUF[0]==0xff)||(RXBUF[1]==0xff)) record_bytes+=2;
  from_blkhead_2_here=record_bytes%512;
  if((from_blkhead_2_here+lenth)<=512)
  {
    for(i=0;i<lenth;i+=2)
      *(RXBUF + i + from_blkhead_2_here) = *(str + (i>>1));
    if(Wt_Block(startaddr,RXBUF)) return 1;
    View_Buf8(RXBUF);
  } 
  else
  {
    for(i=from_blkhead_2_here;i<512;i+=2)
      *(RXBUF+from_blkhead_2_here) = *(str+ (i>>1) -from_blkhead_2_here);
    if(Wt_Block(startaddr,RXBUF)) return 1;
    printp("\naddress is:0x%04x",startaddr);
    View_Buf8(RXBUF);
    //CLS_Buf8(RXBUF);
    if(Rd_Block(startaddr+1,RXBUF)) return 1;
    //if((RXBUF[0]==0xff)||(RXBUF[1]==0xff)) record_bytes+=2;
    for(i=0;i<(from_blkhead_2_here+lenth - 512);i +=2)
      *(RXBUF+i) = *(str + (i>>1) + 512 - from_blkhead_2_here);
    if(Wt_Block(startaddr+1,RXBUF)) return 1;
    printp("\naddress is:0x%04x",startaddr+1);
    View_Buf8(RXBUF);    
  }  
  if(Rd_Block(0x1FF,RXBUF)) return 1;
  RXBUF[510]=(U8)( record_bytes+lenth);
  RXBUF[509]=(U8)((record_bytes+lenth)>>8);
  RXBUF[508]=(U8)((record_bytes+lenth)>>16);    
  if(Wt_Block(0x1FF,RXBUF)) return 1; 
  //View_Buf8(RXBUF);
  printp("\nfile bytes is:0x%02x%02x%02x",RXBUF[508],RXBUF[509],RXBUF[510]);
  return 0; 
}

U8 WriteFile(U8* str,U16 lenth)
{
  U32 startaddr=0x208,record_bytes=0;
  U16 i=0,from_blkhead_2_here=0; 
    
  if(Rd_Block(0x1FF,RXBUF)) return 1;                     //偏移字节存放在0X1FF块地址里面
  record_bytes=(RXBUF[508])|(RXBUF[509]<<8)|(RXBUF[510]<<16);  //文件字写之前已经有的节数    
  startaddr+=(record_bytes/512);
  if(Rd_Block(startaddr,RXBUF)) return 1;
  from_blkhead_2_here=record_bytes%512;
  if((from_blkhead_2_here+lenth)<512)
  {
    for(i=0;i<lenth;i++)
      *(RXBUF+i+from_blkhead_2_here)=*(str+i);
    if(Wt_Block(startaddr,RXBUF)) return 1;
    View_Buf8(RXBUF);
  } 
  else
  {
    for(i=from_blkhead_2_here;i<512;i++)
      *(RXBUF+from_blkhead_2_here)=*(str+i-from_blkhead_2_here);
    if(Wt_Block(startaddr,RXBUF)) return 1;
    View_Buf8(RXBUF);
    CLS_Buf8(RXBUF);
    for(i=0;i<(from_blkhead_2_here+lenth-512);i++)
      *(RXBUF+i)=*(str+i+512-from_blkhead_2_here);
    if(Wt_Block(startaddr+1,RXBUF)) return 1;
    View_Buf8(RXBUF);    
  }  
  if(Rd_Block(0x1FF,RXBUF)) return 1;
  RXBUF[508]=(U8) startaddr;
  RXBUF[509]=(U8)(startaddr>>8);
  RXBUF[510]=(U8)(startaddr>>16);  
  if(Wt_Block(0x1FF,RXBUF)) return 1; 
  View_Buf8(RXBUF);
  return 0; 
}
*/

⌨️ 快捷键说明

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