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

📄 mp3player2_c.txt

📁 在高档AVR单片机ATmega8上实现MP3播放功能
💻 TXT
📖 第 1 页 / 共 3 页
字号:

	if (BattVolt < BATT_SHUTDOWN){
		sbi(PORTB, SPI_CS);		// SPI CS=H
		beep(4, BEEP_LOW);
		cli();	// 充哈み敦贿
		if (RunningTimeH){
			write_eeprom(EEPROM_RUNNING_TIME_OLD_M, RunningTimeM);
			write_eeprom(EEPROM_RUNNING_TIME_OLD_H, RunningTimeH);
			RunningTimeM = 0;
			RunningTimeH = 0;
		}

		shutdown(0);	// シャットダウン
	}

	return BattVolt;
}


//*********************************************************
//	シャットダウン
//	flag != 0 の眷圭は EEPROM今き哈みを乖わずに排富を磊る
//*********************************************************
void shutdown(char flag){

	cli();	// 充哈み敦贿
	sbi(PORTB, SPI_CS);		// SPI CS=H
	cbi(PORTB, MUTE);		// 不兰ミュ〖ト
	MP3_command(0, 0x0010);	// VS1001k powerdown
	if (!flag){
		write_eeprom(EEPROM_VOLUME, Volume);
		write_eeprom(EEPROM_MUSIC, PlayMusic);
		write_eeprom(EEPROM_CLUSTER_L, Cluster);
		write_eeprom(EEPROM_CLUSTER_H, Cluster>>8);
		write_eeprom(EEPROM_REMAIN1, RemainSec);
		write_eeprom(EEPROM_REMAIN2, RemainSec>>8);
		write_eeprom(EEPROM_REMAIN3, RemainSec>>16);
		write_eeprom(EEPROM_SIZE1, MusicSize);
		write_eeprom(EEPROM_SIZE2, MusicSize>>8);
		write_eeprom(EEPROM_SIZE3, MusicSize>>16);
		write_eeprom(EEPROM_SIZE4, MusicSize>>24);
		write_eeprom(EEPROM_RUNNING_TIME_M, RunningTimeM);
		write_eeprom(EEPROM_RUNNING_TIME_H, RunningTimeH);
	}
	for(;;){				// 痰嘎ル〖プ
		cbi(PORTC, POWER);	// Power down
		WDR;
		SLEEP;
	}
}


//*******************************************************
//	EEPROM 今き哈み
//*******************************************************
void write_eeprom(uchar adrs, uchar data){

	// 票じ柒推なら今き哈み瓢侯を乖わない
	if (read_eeprom(adrs) != data){
		while(inp(EECR) & (1<<EEWE));
		outp(adrs >> 8, EEARH);
		outp(adrs, EEARL);
		outp(data, EEDR);
		sbi(EECR, EEMWE);
		sbi(EECR, EEWE);
	}
}


//*******************************************************
//	EEPROM 粕み哈み
//*******************************************************
uchar read_eeprom(uchar adrs){

	while(inp(EECR) & (1<<EEWE));
	outp(adrs >> 8, EEARH);
	outp(adrs, EEARL);
	sbi(EECR, EERE);
	return inp(EEDR);
}


//****************************************
//	BEEP
//	苞眶¨	n	棠瓢搀眶
//			err	!= 0 ならエラ〖不(你い不)
//	充り哈み钓材にすることに庙罢
//****************************************
void beep(uchar n, char err){
	char	i;

	cli();	// MP3_init()借妄面に不翁拇泪されたら氦るので充哈み敦贿
	MP3_init();
	sei();	// 充り哈み钓材
	for (; n > 0; --n){
		if (err){
			MP3_sin(ErrorBeep);
		} else {
			MP3_sin(BeepData);
		}

		// 箕粗略ち。この粗が BEEPの不の墓さになる
		for (i=0; i < 10*2; i++){	// 腆100ms
			SLEEP;
		}

		MP3_sin(BeepStop);
	
		// BEEPの不粗
		for (i=0; i < 3*2; i++){	// 腆30ms
			SLEEP;
		}
	}

	MP3_sin(BeepStop);	// 箕」贿まらないことがあるのでもう办搀
}


//****************************************
//	EasyMP3 介袋步
//****************************************
void MP3_init(void){

	MP3_command(0, 0x0004);			// Soft Reset
	InitWait();
	MP3_command(0, 0x0000);
	while(!(inp(PIND)&(1<<MP3_DREQ)));

	MP3_command(11, ((uint)Volume << 8)|((uint)Volume));	// 不翁肋年
	MP3_command(3, 0x8000 + (uint)((VS1001_CLOCK)/2000));		// Clock
	InitWait();
}


//****************************************
//	EasyMP3 テスト脱赖腹侨叫蜗
//****************************************
void MP3_sin(PGM_VOID_P data){
	uchar	i;
	uchar	bit;
	uchar	c;

	for (i=0; i < 8; i++){
		c = (uchar)PRG_RDB(data++);
		sbi(PORTD, MP3_BSYNC);
		for (bit=0; bit<8; bit++){
			if (c & 0x80){
				sbi(PORTD, MP3_SI);
			} else {
				cbi(PORTD, MP3_SI);
			}
			sbi(PORTD, MP3_DCLK);
			c <<= 1;
			cbi(PORTD, MP3_DCLK);
			cbi(PORTD, MP3_BSYNC);
		}
		sbi(PORTD, MP3_SI);
	}
}


//****************************************
//	EasyMP3 コマンド叫蜗
//****************************************
void MP3_command(uchar addr, uint arg){

	cbi(PORTD, MP3_CS);
	MP3_com_write(2);
	MP3_com_write(addr);
	MP3_com_write(arg >> 8);
	MP3_com_write(arg);
	sbi(PORTD, MP3_CS);
}


//****************************************
//	EasyMP3 コマンド掐蜗	踏蝗脱
//****************************************
/*
uint MP3_command_read(uchar addr){
	char	i;
	uint	r = 0;

	cbi(PORTD, MP3_CS);
	MP3_com_write(3);
	MP3_com_write(addr);
	for(i=0; i<16; i++){
		sbi(PORTD, MP3_SCLK);
		r <<= 1;
		if (inp(PINB) & (1<<MP3_SO)){
			r |= 1;
		}
		cbi(PORTD, MP3_SCLK);
	}
	sbi(PORTD, MP3_CS);
	return r;
}
*/


//****************************************
//	EasyMP3 コマンド 1byte叫蜗
//****************************************
void MP3_com_write(uchar data){
	char	i;

	for (i=0; i<8; i++){
		if (data & 0x80){
			sbi(PORTD, MP3_SI);
		} else {
			cbi(PORTD, MP3_SI);
		}
		sbi(PORTD, MP3_SCLK);
		data <<= 1;
		cbi(PORTD, MP3_SCLK);
	}
	sbi(PORTD, MP3_SI);
}


//****************************************
//	MMC/SDカ〖ドから 32byteを粕んで DataBuffに呈羌
//****************************************
void read_32(ulong addr){
	uint		i, b;

	if (SPI_read_open(addr & 0xFFFFFE00))	return;
	b = (uint)addr & 0x01FF;
	for (i=0; i < 512; i++){
		if (i == b){
			int	n;
			for (n = 0; n < 32; n++){
				DataBuff[n] = SPI_in();
				i++;
			}
		} else {
			SPI_in();
		}
	}
	SPI_read_close();
}


//****************************************
//	介袋步箕のクロックウエイト
//****************************************
void InitWait(void){
	uchar	i;

	for(i=0; i< 255; i++){
		NOP;
	}
}


//****************************************
//	MMC/SDカ〖ド粕み哈みオ〖プン
//****************************************
uchar SPI_read_open(ulong adrs){
	uint	i;
	uchar	r;
	uchar	retry;

	// カ〖ドによってはリトライが涩妥のようだ
	for (retry = 0; retry < 100; retry++){
		cbi(PORTB, SPI_CS);		// SPI CS=L
		r = SPI_command(17, adrs);
		if (r == 0){
			for (i = 0; i < 2000; i++){	// ものすごく略つ眷圭がある
				r = SPI_in();
				if (r == 0xFE){
					return 0;	// 啪流倡幌マ〖ク
				}
			}
		} else if (r == 0xFE){
			return 0;	// 赖撅オ〖プン
		}
		sbi(PORTB, SPI_CS);		// SPI CS=H
		if (Debug){
			WriteHex(r);
			WriteCom(' ');
		}
//		InitWait();
	}

	return 1;	// オ〖プンできなかった
}


//****************************************
//	MMC/SDカ〖ド粕み哈みクロ〖ズ
//	1byteのずれがあっても丹にしない
//****************************************
void SPI_read_close(void){
	uint	i;

	SPI_in();	// CRC
	SPI_in();	// CRC
	// BUSYチェック
	for (i = 0; i < 1000; i++){
		if (SPI_in() == 0xFF)	break;
	}
	sbi(PORTB, SPI_CS);		// SPI CS=H
}


//****************************************
//	MMC/SD SPIコマンド叫蜗
//****************************************
uchar SPI_command(uchar com, ulong arg){
	uint	i;
	uchar	r;

	// BUSYチェック 丝家のカ〖ドでは涩寇みたい
	for (i = 0; i < 1000; i++){
		r = SPI_in();
		if (r == 0xFF)	break;
	}
	if (r != 0xFF)	return 1;

	SPI_out(com|0x40);
	SPI_out(arg >> 24);
	SPI_out(arg >> 16);
	SPI_out(arg >> 8);
	SPI_out(arg);
	SPI_out(0x95);		// 介袋步コマンドのCRC

	for(i = 0; i < 1000; i++){
		r = SPI_in();
		if (r == 0xFE)		break;
		if (!(r & 0x80))	break;
	}
	return r;
}


//****************************************
//	MMC/SD SPIデ〖タ叫蜗
//****************************************
void SPI_out(uchar data){

	outp(data, SPDR);
	while(!(inp(SPSR) & 0x80));
}


//****************************************
//	MMC/SD SPIデ〖タ掐蜗
//****************************************
uchar SPI_in(void){

	outp(0xFF, SPDR);
	while(!(inp(SPSR) & 0x80));
	return inp(SPDR);
}


//****************************************
//	MMC/SD SPIクロック姜位略ち
//	SPDRをアクセスしてない眷圭は
//	SPIF=0になって痰嘎ル〖プする眷圭があることに庙罢
//****************************************
void SPI_wait(void){
	while(!(inp(SPSR) & 0x80));
}	


//****************************************
//	1セクタ〖粕み哈んで山绩する
//****************************************
void print_sector(ulong sec){
	uchar	r;
	int		i;

	sec *= 512; 
	r = SPI_read_open(sec);
	WriteHex(r);
	WriteCom('\n');
	for (i=0; i<512; i++){
		r = SPI_in();
		WriteHex(r);
		if ((i & 31) == 31){
			WriteCom('\n');
		} else if (i & 1){
			WriteCom(' ');
		}
	}
	SPI_read_close();
}


//****************************************
//	シリアル掐蜗。掐蜗があるまで略つ
//****************************************
uchar	ReadCom(void){

	do {
		WDR;
	} while(!(inp(UCSRA)&(1<<RXC)));
	return inp(UDR);
}

//****************************************
//	シリアル叫蜗
//****************************************
void WriteCom(uchar data){

	do {
		;
	} while(!(inp(UCSRA)&(1<<UDRE)));
	outp(data, UDR);
}


//****************************************
//	1byteを16渴眶で山绩
//****************************************
void WriteHex(uchar data){
	uchar	c;

	c = (data>>4) + '0';
	if (c > '9'){	c += 7; }
	WriteCom(c);

	c = (data & 0x0f) + '0';
	if (c > '9'){	c += 7; }
	WriteCom(c);
}


//****************************************
//	intを 10渴矢机误恃垂
//****************************************
/*
void ItoStr(uint i, uchar str[]){
	char	*p;

	if (i >= 10000){
		p = &str[5];
	} else if (i >= 1000){
		p = &str[4];
	} else if (i >= 100){
		p = &str[3];
	} else if (i >= 10){
		p = &str[2];
	} else {
		p = &str[1];
	}
	*p-- = 0;

	do {
		*p-- = (i % 10) + '0';
		i /= 10;
	} while(i);
}
*/


//****************************************
//	盖年矢机误叫蜗
//	蝗脱毋¨
//		char *s;
//		s = PSTR("Message OK.\n");
//		WriteComMsg(s);
//****************************************
void WriteComMsg(PGM_VOID_P msg){
	char	i;
	uchar	c;

	i = 0;
	while((c = (uchar)PRG_RDB(msg++)) != 0){
		WriteCom(c);
		i++;
	}
}

//****************************************
//	バッファ矢机误叫蜗
//****************************************
void WriteComStr(uchar *msg){
	char	i;
	uchar	c;

	i = 0;
	while((c = (uchar)(*msg++)) != 0){
		WriteCom(c);
		i++;
	}
}

⌨️ 快捷键说明

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