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

📄 mp3player2.c

📁 读取sd card中的mp3资料,并播放.
💻 C
📖 第 1 页 / 共 3 页
字号:
				if (--PlayMusic == 0){					PlayMusic = MusicCount;				}			}			Cluster = 0;	// 妒の呵介から		} else {	// FF or その妒の浩栏姜位			PlayMusic++;	// 肌の妒			Cluster = 0;		}		if (BattVolt < BATT_START){			beep(1, BEEP_LOW);	// 弹瓢排暗笆布になったら妒粗に焚桂不		}	}}//*********************************************************//	スイッチが澄悸に庶されるまで略つ//*********************************************************void switch_wait(void){	sei();	for (;;) {		WDR;		SLEEP;		SLEEP;		if (!(SwitchFlag & ((1<<SW_FF)|(1<<SW_REW)|(1<<SW_STOP)))){			SLEEP;			SLEEP;			if (!(SwitchFlag & ((1<<SW_FF)|(1<<SW_REW)|(1<<SW_STOP)))){				break;			}		}	}}//*********************************************************//	MMC/SDカ〖ドの介袋步//*********************************************************uchar InitCard(void){	uchar	c;	outp(0x52, SPCR);	// SPIマスタ, CPOL=0, クロック 8MHz/64=125kHz	sbi(PORTB, SPI_CS);	// CS=H	// MMC/SD SPIモ〖ド败乖涟のクロック流慨	for (c=0; c < 10; c++){		SPI_in();	}	// SPIモ〖ド败乖コマンド	cbi(PORTB, SPI_CS);		// CS=L	c = SPI_command(0, 0);	while ((c != 1)&&(c != 0xFF)){		SLEEP;		c = SPI_command(0, 0);	}	while (c == 1){		c = SPI_command(1, 0);	}	sbi(PORTB, SPI_CS);	// CS=H	outp(0x50, SPCR);	// SPIマスタ, CPOL=0, クロック 8MHz/4=2MHz	sbi(SPSR, SPI2X);	// クロックを2擒 4MHz	return c;}//*********************************************************//	VFAT攫鼠粕み艰り//*********************************************************uchar read_VFAT_info(void){	ulong	sec;	uint	bpb;	uint	n;	// VFAT攫鼠粕み艰り。セクタ墓は 512bytesで疯め虑ちしている	read_32(446);										// MBR粕み哈み	bpb = (uint)DataBuff[8] + ((uint)DataBuff[9]<<8);	// BPB黎片セクタ	read_32((ulong)bpb * 512);							// 粕み哈み	n = (uint)DataBuff[11] + ((uint)DataBuff[12] << 8);	// セクタ墓	if (n != 512){		return 2;	// 1セクタが 512bytesでない	}	SectorsPerCluster = DataBuff[13];		// クラスタあたりのセクタ眶	FATstart = bpb + (uint)DataBuff[14]		+ ((uint)DataBuff[15] << 8);		// 徒腆セクタ眶	RootDirEntriesCount = (uint)DataBuff[17]		+ ((uint)DataBuff[18] << 8);		// ル〖トディレクトリエントリ眶	n = (uint)DataBuff[22] + ((uint)DataBuff[23] << 8);	// FATのセクタ眶	if (n == 0){		return 1;	// FAT32らしい	}	DIRstart = (uint)FATstart + (uint)DataBuff[16] * n;	// FATの眶∵セクタ眶	n = RootDirEntriesCount / 16;	// ル〖トディレクトリに涩妥なセクタ眶	if (RootDirEntriesCount % 16){		n++;	// 前のため、途りが叫たら磊り惧げ。奶撅は稍妥だと蛔うが	}	DataStart = (ulong)DIRstart + (ulong)n;		// デ〖タ呈羌挝拌	sec = (ulong)DataBuff[19] + ((ulong)DataBuff[20] << 8);	// 另セクタ眶	if (sec == 0){		read_32((ulong)bpb * 512 + 32);		// 粕み哈み		sec = (ulong)DataBuff[0] + ((ulong)DataBuff[1] << 8)			+ ((ulong)DataBuff[2] << 16) + ((ulong)DataBuff[3] << 24);	}	sec -= FATstart;	sec /= SectorsPerCluster;	if (sec >= 0x1000){		FATtype = 1;	// FAT16	} else {		FATtype = 0;	// FAT12	}	return 0;}//*********************************************************//	MP3ファイルを淋す//	苞眶¨//		num	この眶だけ斧つけたら提る//		この眶笆布であってもディレクトリエントリを链て拇べ姜わったら提る//	提り猛¨//		斧つけた眶//		DataBuff[0×31]	呵稿に斧つかった MP3のディレクトリ攫鼠//*********************************************************uint search_MP3(uint num){	uint	ent;	ulong	sec;	uchar	i, j;	uint	n;	n = 0;	sec = (ulong)DIRstart * 512;	for (ent = 0; ent < RootDirEntriesCount; ){		if (SPI_read_open(sec))	return n;		for (i = 0; i < 16; i++){			for (j = 0; j < 32; j++){				DataBuff[j] = SPI_in();			}			if (DataBuff[0] == 0)	break;	// 踏蝗脱挝拌浮叫			if (((DataBuff[26] != 0)||(DataBuff[27] != 0))&&	// クラスタ戎规				(DataBuff[0] != 0xE5)&&						// 猴近マ〖ク				(!(DataBuff[11] & 0x18))&&					// 奶撅ファイル				(DataBuff[8]=='M')&&(DataBuff[9]=='P')&&(DataBuff[10]=='3')){															// 橙磨灰MP3				n++;				if (--num == 0)	break;			}			ent++;		}		for (++i; i < 16; i++){			for (j = 0; j < 32; j++){				SPI_in();	// セクタ尸の荒りを粕み嘉て			}		}		SPI_read_close();		if (DataBuff[0] == 0)	break;	// 踏蝗脱挝拌浮叫		if (num == 0)	break;		sec += 512;	// 肌のセクタ	}	return n;}//****************************************//	MP3ファイルを浩栏//	fn:		妒戎规//	clst:	遍琳倡幌クラスタ。==0 の眷圭は呵介から//	remainsec: 浩栏デ〖タ荒りセクタ眶//****************************************char play_music(uint fn, uint clst, long remainsec){	ulong	sec;	uint	remain;	uint	cn;	uint	i;	if (fn != search_MP3(fn)){		return -1;	// 妒が痰い	}	MusicSize = (ulong)DataBuff[28] + ((ulong)DataBuff[29]<<8)			  + ((ulong)DataBuff[30]<<16) + ((ulong)DataBuff[31]<<24);	if (clst){		// 庞面から浩栏		Cluster = clst;		RemainSec = remainsec;		remain = MusicSize - (remainsec * 512);	} else {		// 呵介から浩栏		Cluster = (uint)DataBuff[26] + ((uint)DataBuff[27] << 8);		RemainSec = MusicSize / 512;		remain = MusicSize % 512;	}	if ((Cluster == 0xFFFF)||(Cluster < 2)){		return -2;	// クラスタ佰撅	}	// 肌のクラスタを拇べておく	NextCluster = next_cluster(Cluster, 0, 0);	StopSw = 0;	RewSw = 0;	FfSw = 0;	cn = SectorsPerCluster;	sec = (((ulong)Cluster - 2) * (ulong)SectorsPerCluster + DataStart)	* 512;	MP3_init();	Timer = 100;	// READYタイマ〖セット	while (RemainSec > 0){		uchar	data;		char	bit;		if (SPI_read_open(sec))	return -2;		cli();				// 充哈み敦贿		SPI_out(0xFF);		// 1byte誊のクロック流叫 & WAIT		for (i = 0; i < 512; i++){			while (!(inp(PIND)&(1<<MP3_DREQ))){	// VS1001 BUSYチェック				WDR;			// ウォッチドッグタイマ〖リセット				Timer = 100;	// READYタイマセット				if (NextCluster == 0){					// 肌のクラスタを拇べる					NextCluster = next_cluster(Cluster, sec, i);				} else {					sei();	// 充り哈み钓材					SLEEP;					cli();	// 充哈み敦贿				}			}			data = inp(SPDR);			outp(0xFF, SPDR);	// SD/MMCカ〖ドへ肌のデ〖タリクエスト			if (data & 0x80){				sbi(PORTD, MP3_SI);			} else {				cbi(PORTD, MP3_SI);			}			sbi(PORTD, MP3_BSYNC);	// BSYNC = H			sbi(PORTD, MP3_DCLK);			data <<= 1;			cbi(PORTD, MP3_DCLK);			cbi(PORTD, MP3_BSYNC);	// BSYNC = L			for (bit = 0; bit < 7; bit++){				if (data & 0x80){					sbi(PORTD, MP3_SI);				} else {					cbi(PORTD, MP3_SI);				}				sbi(PORTD, MP3_DCLK);				data <<= 1;				cbi(PORTD, MP3_DCLK);			}		}		sei();	// 充り哈み钓材		SPI_read_close();		--RemainSec;				if (--cn > 0){			sec += 512;	// 肌のセクタ			if (Debug && (cn == 1)){				uint n;				n = BattVolt;				WriteHex(n>>8);				WriteHex(n);				WriteCom(' ');				WriteHex(Cluster>>8);				WriteHex(Cluster);				WriteCom('\n');			}		} else {			// 肌のクラスタ			if (NextCluster == 0){				Cluster = next_cluster(Cluster, 0, 0);			} else {				Cluster = NextCluster;				NextCluster = 0;			}			if ((Cluster == 0xFFFF)||(Cluster < 2)){				// 佰撅クラスタが浮叫されたので动扩姜位				remain = 0;				break;			}			sec = (((ulong)Cluster - 2) * (ulong)SectorsPerCluster				   + DataStart) * 512;			cn = SectorsPerCluster;		}		check_batt();	// バッテリ〖チェック		if (Timer == 0){	// READYタイムアウトしたら			if (NoBusyRetry > 0){	// リトライしてもダメなら				beep(1, BEEP_LOW);	// 你不ビ〖プ1搀				NoBusyRetry = 0;				FfSw = 0;				return 2;		// FF胺いで姜位 ⅹ 肌の妒へ			} else {				NoBusyRetry = 1;				RewSw = 0;				return 3;		// REW胺いで姜位 ⅹ その妒の呵介からリトライ			}		}		// STOP, FFボタンチェック		if (StopSw > 2){			beep(1, BEEP_HIGH);			NoBusyRetry = 0;			return 1;		} else if (FfSw > 2){			beep(1, BEEP_HIGH);			NoBusyRetry = 0;			return 2;		} else if (RewSw > 2){			beep(1, BEEP_HIGH);			NoBusyRetry = 0;			return 3;		}	}	NoBusyRetry = 0;	// 1セクタ(512bytes)踏塔の尸を浩栏	if ((remain > 0)&&(remain < 512)){		uchar	data;		char	bit;		if (SPI_read_open(sec))	return -2;		cli();				// 充哈み敦贿		SPI_out(0xFF);		// 1byte誊のクロック流叫□WAIT		for (i = 0; i < 512; i++){			data = inp(SPDR);			outp(0xFF, SPDR);			if (remain-- > 0){				while (!(inp(PIND)&(1<<MP3_DREQ))){					// VS1001 BUSY					WDR;		// ウォッチドッグタイマクリア					sei();			// 充り哈み钓材					SLEEP;					cli();			// 充哈み敦贿				}				sbi(PORTD, MP3_BSYNC);	// BSYNC = H				for (bit=0; bit<8; bit++){					if (data & 0x80){						sbi(PORTD, MP3_SI);					} else {						cbi(PORTD, MP3_SI);					}					sbi(PORTD, MP3_DCLK);					data <<= 1;					cbi(PORTD, MP3_DCLK);					cbi(PORTD, MP3_BSYNC);	// BSYNC = L				}			}		}		sei();	// 充り哈み钓材		SPI_read_close();	}	return 0;}//****************************************//	肌のクラスタを滇める//****************************************uint next_cluster(uint c, ulong sec, uint remain){	ulong	addr;	uint	data;	ulong	fatadr;	uint	i;	if (FATtype == 0){		// FAT12		addr = (ulong)FATstart * 512 + (ulong)c + (c >> 1);		if ((addr & 511) == 511){			if (sec != 0){				// 粕み哈みオ〖プン面なら粕み嘉て				for (i = remain; i < 512; i++)	SPI_in();				SPI_read_close();				data = read_word(addr) & 0x00FF;				data |= ((read_word(addr+1) & 0x00FF) << 8);				// 浩刨オ〖プン、笆涟の疤弥まで粕み嘉て				if (SPI_read_open(sec))	return 0;				SPI_in();				for (i = 0; i < remain; i++)	SPI_in();			} else {				// セクタをまたぐ				data = read_word(addr) & 0x00FF;				data |= ((read_word(addr+1) & 0x00FF) << 8);			}		} else {			fatadr = addr & 0xFFFFFE00;			if ((sec != 0)&&(fatadr != FatCacheAddr)){				// 粕み哈みオ〖プン面で FATバッファ痰跟なら粕み嘉て				for (i = remain; i < 512; i++)	SPI_in();				SPI_read_close();				data = read_word(addr);				// 浩刨オ〖プン、笆涟の疤弥まで粕み嘉て				if (SPI_read_open(sec))	return 0xFFFF;				SPI_in();				for (i = 0; i < remain; i++)	SPI_in();			} else {				data = read_word(addr);			}		}		if (c & 1){			c = data >> 4;		} else {			c = data & 0x0fff;		}		if (c >= 0x0ff8)	c = 0xFFFF;	} else {		// FAT16		addr = (ulong)FATstart * 512 + (ulong)c * 2;		fatadr = addr & 0xFFFFFE00;		if ((sec != 0)&&(fatadr != FatCacheAddr)){			// 粕み哈みオ〖プン面で FATバッファ痰跟なら粕み嘉て			for (i = remain; i < 512; i++)	SPI_in();			SPI_read_close();			c = read_word(addr);			// 浩刨オ〖プン、笆涟の疤弥まで粕み嘉て			if (SPI_read_open(sec))	return 0;			SPI_in();			for (i = 0; i < remain; i++)	SPI_in();		} else {			c = read_word(addr);		}		if (c >= 0xFFF8)	c = 0xFFFF;	}	return c;}//****************************************//	MMC/SDカ〖ドから 2byteを粕む//	セクタ董肠のアクセスはできないので//	惧疤供镍で雇胃すること//****************************************uint read_word(ulong addr){	uint	w;	uint	b;	uchar	*p;	b = addr & 511;	addr &= 0xFFFFFE00;	if (addr != FatCacheAddr){		if (SPI_read_open(addr))	return 0;		for (p = FatCache; p < (FatCache + 512); ){			*p++ = SPI_in();		}		SPI_read_close();		FatCacheAddr = addr;	}	w = (uint)FatCache[b++];	w |= ((uint)FatCache[b] << 8);	return w;}//*******************************************************//	バッテリ〖排暗を拇べ、你すぎればシャットダウンする//*******************************************************int check_batt(void){

⌨️ 快捷键说明

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