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

📄 hdd driver.c

📁 使用单片机 读写SD卡 带FAT16功能 PIC18f452
💻 C
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//	Name:			   HDD Driver.c                       					  //
//	Date:			   02/01/2004		                   					  //
//	Version:		   1.1											              //
//	Type:			   PIC C Driver for MMC										  //
//	Author:        Mike Luck & Douglas Kennedy				           //
//	Company:		   MPIC3.COM										           //
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//	Note:
// 		This code is a work in progress & not a finished fully working
//			project. Please check www.mpic3.com reguarly for updates.

/// PIN Assignments //////////////////////////////
#DEFINE _CS PIN_C2 // chip select for MMC
//#DEFINE SDO PIN_C5
//#DEFINE CLK PIN_C3
//#DEFINE SDI PIN_C4
// SPI hardware pins are
// SDO C5
// SDI C4
// SCK C3
///////////////////////////////////////////////////////////////

///// Note old values needed before all SPI modes could be set up using SPI_setup
/// for 16 parts ///////////
//#DEFINE SSPCON 0x14
//#DEFINE SSPSTAT 0x94
//#BIT SMP=SSPSTAT.7
//#BIT CKE=SSPSTAT.6
//#BIT CKP=SSPCON.4
//#BIT SSPEN=SSPCON.5
//////////////////////////////

// For 18F452
#DEFINE SSPSTAT 0x0FC7
#DEFINE SSPCON1 0x0FC6
#BIT SMP=SSPSTAT.7
#BIT CKE=SSPSTAT.6
#BIT CKP=SSPCON1.4

#DEFINE MAX_FILES 2 /// max number of open files
#DEFINE MMC_BUFF_SIZE 32 /// 32 for PCM
#DEFINE MMC_FILE_NAME_SIZE 32

#DEFINE ROOT_CLUSTER 0
#DEFINE NEXT_CLUSTER 1

#define MMC_INIT_TRACE FALSE
#define MMC_CMD_TRACE FALSE
#define MMC_CLUSTER_TRACE FALSE // if true prints to serial port
#define MMC_OPEN_TRACE FALSE // if true prints to serial port
#define MMC_READ_TRACE FALSE // if true prints file_addr,cluster index etc
#define MMC_WRITE_TRACE FALSE
#define MMC_READ_BLOCK_TRACE FALSE
#define MMC_SET_BLOCK_LEN_TRACE FALSE
#define MMC_WRITE_BLOCK_TRACE FALSE
#define MMC_NEW_CLUSTER FALSE
////// MMC prototypes
#separate
int init_MMC(int max_tries);
#separate
int open_file(int fnbr,char *fname,int16 rec_length);
#separate
int file_read(int8 fnbr,char *buff);
#separate
int file_write(int8 fnbr,int *buff);
#separate
int file_set(int fnbr,int32 offset);
#separate
int file_new_cluster(int8 fnbr,int8 mode); /// mode 1=fat1 2=fat2

int32 atoint32 (char *s );
signed int strncmp(char *s1, char *s2, int n);
///////////////////// MMC GLOBALS /////////////////////////////
int16 cluster_size_bytes; // bytes in a cluster
//int16 dir_cluster_chain_ptr; // link to the first cluster in the dir

int32 fat1_address; // physical address of fat1 cluster table assigned by INIT_MMC
int32 fat2_address; // physical address of fat1 cluster table assigned by INIT_MMC
int32 root_dir_address; // physical address of volume,file,folder tiles assigned by INIT_MMC
int32 data_area_address; // physical address of data area assigned by INIT_MMC
int32 winhex_adj; // Win hex hides the bytes in the reserved sectors
// this means Fat1 is address 512
// so adj is fat1-512

int32 block_size; // current MMC block size

int MMC_init=FALSE;

int MMC_dir_protected=TRUE;

////////// open file specific globals ///////////////////////
struct{
	char name[MMC_FILE_NAME_SIZE+1]; // fopen file name
	int32 dir_addr_ptr; // physical address of this files tile info
	int16 root_cluster_ptr; // location of first cluster in FAT
	int16 this_cluster_ptr; // location of current cluster in FAT
	int16 next_cluster_ptr; // location of the next cluster for a file or sub dir in FAT
	int32 addr_ptr; // physical address in the file the current
	// cluster points to
	// address=(this_chain_ptr-2)*cluster_size_bytes+data_area_address
	//
	// cluster_addr(THIS_CLUSTER) assigns it
	// cluster_addr(NEXT_CLUSTER) moves to the data the next
	// cluster points to
	int32 size; // size of open file in bytes
	int32 cluster_offset; // offset within the file representing the start of the current cluster
	// (0 is start and ends with the cluster contianing eof )
	// auto increased by cluster_size_bytes each time a new cluster is entered

	int32 offset; // current offset into the open file ( 0 is start size(file size) is end)
	// auto increased by rec size each time a rec is read
	// addr_prt+offset-cluster_offset is physical address of
	// the current position within the file
	// the physical positions are not always contiguous since the
	// clusters of the file are not always adjacent to each other
	int16 rec_size; // fopen record_size
	// char buff[MMC_BUFF_SIZE+1]; // used for open and for read write
	// init MMC uses file 0 buff to fetch the globals

} file[MAX_FILES];


#separate
int mmc_cmd(int8 cmd,int32 address,int8 tries,int8 valid,int8 invalid){
	int i,r1;
	for( i=0;i<16;i++) SPI_READ(0xFF);// digest prior operation
	// commands
	// 7 6 5 4 3 2 1 0
	// 0 1 b b b b b b bbbbbb=cmd
	// 16=0x50 set blocklength
	// 17=0x51 read block
	// 24=0x58 write block
	#if MMC_CMD_TRACE
	printf("\n\r cmd=%2X \n\r",cmd);
	#endif
	SPI_READ(cmd);
	SPI_READ(MAKE8(address,3));
	SPI_READ(MAKE8(address,2));
	SPI_READ(MAKE8(address,1));
	SPI_READ(MAKE8(address,0));
	SPI_READ(0x95); // valid crc for 0x40 only invalid for others but spi mode doesn't care
	for(i=0;i< tries;i++) {
		r1=SPI_READ(0xFF);
		#if MMC_CMD_TRACE
			printf(" %2X",r1);
		#endif
		if (r1==valid) break;
		if (r1==invalid) break;
	}
	return(r1);
}


#separate
int set_BLOCKLEN( int32 size){
	int r1;

	r1=mmc_cmd(0x50,size,16,0x00,0x40); /// cmd.data,tries,valid code,invlaid code
	if (r1==0x00) goto done ;
	if (r1==0x40) goto invalid;


	return(false);
	invalid:
	#IF MMC_SET_BLOCK_LEN_TRACE
		printf("\n\r para err\n\r");
	#ENDIF
done:
	block_size=size; //// assign global block size
	//printf("\n\r blk size=%lu",block_size);
	return(true);
}


#separate
int read_BLOCK( int32 address, char *buff){
	//// low level read ..requires block len to be called first to set global blocksize
	int r1;
	long i,iw; /// allows large gt 255 buff size addressing
	//int data[128];
	r1=mmc_cmd(0x51,address,16,0x00,0x40);

	if (r1==0x00) goto get_token ; // we can read data payload
	if (r1==0x40) goto invalid;

	#IF MMC_READ_BLOCK_TRACE
		printf("\n\r read block err 1 address=%lu \n\r",address);
	#ENDIF
	return(false);
	invalid:
	#IF MMC_READ_BLOCK_TRACE
		printf("\n\r read block err 2 adress=%lu \n\r",address);
	#ENDIF
	return(false);
	get_token:
	for(iw=0;iw<1024;iw++){
	r1=SPI_READ(0xFF);
	//data[iw]=r1;
	if (r1==0xFE) goto read_data; // read token $FE
	}
	#IF MMC_READ_BLOCK_TRACE
		printf("\n\r read block err 3 address=%lu \n\r",address);
	#ENDIF
	return(false);
	read_data:
	#IF MMC_READ_BLOCK_TRACE
		printf("\n\r read block tries for FE =%lu \n\r",iw);
	#ENDIF

	for (i=0;i<block_size;i++) buff[i]=SPI_READ(0xFF);
	SPI_READ(0xFF); // read crc
	SPI_READ(0xFF);

	return(true);
}

//////////////////////////////////////////////////////////////////
///////////////////////////////// INIT MMC ///////////////////////
//////////////////////////////////////////////////////////////////
#separate

int init_MMC(int max_tries){
	int32 start_lsec;
	int16 sec_resv,sec_for_FAT,bytes_per_sector,root_dir_entries,
	sec_for_data,count_of_clusters,root_dir_sectors,total_sectors;
	int i,tries,sec_per_cluster,c;
	char buff[32];
	tries=0;
	cmd0:
	///////////////////// place null treminators in globals fname and buff
	for(i=0;i<MAX_FILES;i++){
		file[i].name[0]=0;
		file[i].rec_size=32; //// default rec_size = 32 byte tile size of FAT16
	}
	//buff[MMC_BUFF_SIZE]=0;
	//frec_size=32; //// default rec_size = 32 byte tile size of FAT16
	output_high(_CS); /// reset chip hardware !!! required
	delay_ms(20);
	for(i=0;i<20;i++) SPI_READ(0xFF); // min 80 clocks to get MMC ready
	output_low(_CS); /// !!! required
	delay_ms(20);
	#if MMC_INIT_TRACE
		printf("cmd0");
	#ENDIF
	c=mmc_cmd(0x40,0x00000000,128,0x01,0x99);

	if (c==0x01) goto exit_cmd1;

	// note: i must cycle at least 8 times (16 is safe )

	if (tries++<max_tries) goto cmd0; /// restart
	else return (10);
	exit_cmd1:
	// CPDMOD - This SOMETIMES seems to be necessary
	// output_high(_CS);
	// SPI_READ(0xFF); // min 8 clocks to get MMC ready
	// output_low(_CS);
	//CPDMOD End


	tries=0;
	cmd1:

	/// now try to switch to idle mode
	/// Note: cmd1(idle) is the only command allowed after a cmd0(reset)
	//

	c=mmc_cmd(0x41,0x00000000,128,0x00,0x99);
	if (c==0x00) { goto ready;}


	if( tries++<max_tries) { printf("cmd1"); goto cmd1;}
	else return(11);
	ready:
	//for( i=0;i<32;i++) SPI_READ(0xFF);// digest operation
	/// MMC is inialized and in idle state ready for commands
	////
	//// we need to first access the master boot sector physical address=0
	///
	if(set_BLOCKLEN((int32)32)==false) return(12); /// sets global block_size to 32

	if (read_block(0x00000000,buff)==false) return (99); /// read the first few bytes
	#if MMC_INIT_TRACE
		printf("\n\r sector0=");
		for(i=0;i<32;i++)printf("%2X ",buff[i]);
	#ENDIF
	if (buff[0]==0xEB || buff[0]==0xE9){
		/// sector 0 is the boot sector
		#if MMC_INIT_TRACE
			printf("\n\r boot sector= 0");
		#ENDIF
	}
	else{
		//// partition

		/// access the master boot sector physical address 0 at offset 1BE
		if (read_BLOCK(0x000001BE,buff)==false) return(13);
		#if MMC_INIT_TRACE
			for(i=0;i<32;i++)printf("%2X ",buff[i]);
		#ENDIF
		// start_lsec is address of the partion boot sector
		start_lsec=make32(buff[11],buff[10],buff[9],buff[8]);
		#if MMC_INIT_TRACE
			printf("\n\r boot sector= %lu",start_lsec);
		#ENDIF
		if (read_BLOCK(start_lsec*512,buff)==false) return(14);
	}

	bytes_per_sector=make16(buff[12],buff[11]);
	if(bytes_per_sector!=512) return(15);
	sec_per_cluster=buff[13];
	cluster_size_bytes=(int16)sec_per_cluster*bytes_per_sector;


	sec_resv=make16(buff[15],buff[14]);

	root_dir_entries=make16(buff[18],buff[17]);// number of 32 byte tiles

	total_sectors=make16(buff[20],buff[19]);

	sec_for_FAT=make16(buff[23],buff[22]);
	//branch to file directory
	fat1_address=(start_lsec+sec_resv)*bytes_per_sector;
	fat2_address=fat1_address+bytes_per_sector*sec_for_FAT;
	root_dir_address=(sec_for_FAT*2+start_lsec+sec_resv)*bytes_per_sector;
	data_area_address=root_dir_address+root_dir_entries*32;
	///// check for FAT16
	root_dir_sectors=root_dir_entries>>4;

	sec_for_data=total_sectors - sec_resv -sec_for_fat*2 -root_dir_sectors;

	count_of_clusters=sec_for_data/sec_per_cluster;

	if (count_of_clusters <4085 || count_of_clusters>65525) return(17);

	winhex_adj=fat1_address-bytes_per_sector;

	#if MMC_INIT_TRACE

		printf("Files:/n/r");
		for(i=0;i<MAX_FILES;i++){
			printf("/n/r",file[i].name[i]);
		}

	#ENDIF

	return(0);
}


#separate
int get_CID(char s){
	int i,r1;
	r1=mmc_cmd(0x4A,0x00000000,16,0x00,0x99);


	if (r1==0x00) goto get_token ; // we can read data payload

	return(false);
	get_token:
	for(i=0;i<16;i++)if (SPI_READ(0xFF)==0xFE) goto read_CID; // read token $FE
	return(false);
	read_CID:
	//for (i=0;i<18;i++) s[i]=SPI_READ(0xFF);

	return(true);
}


#separate
int get_CSD(char s){
	int i,r1;
	r1=mmc_cmd(0x4A,0x00000000,16,0x00,0x99);

⌨️ 快捷键说明

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