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

📄 mp3.c

📁 AVR+CH375+VS1003
💻 C
📖 第 1 页 / 共 3 页
字号:

//晶振: 11.0592MHz

#cpu "MEGA32"

//*******************************************************
//SD卡配置类
unit SD_card_config
{
	public bit SD_DO_port = @sfr.PORTB.0;
	public bit SD_DO_pin = @sfr.PINB.0;
	public bit SD_DO_ddr = @sfr.DDRB.0;
	
	public bit SCLK_port = @sfr.PORTB.1;
	//bit SCLK_pin = @sfr.PINB.1;
	public bit SCLK_ddr = @sfr.DDRB.1;
	
	public bit SD_DI_port = @sfr.PORTB.2;
	//bit SD_DI_pin = @sfr.PINB.2;
	public bit SD_DI_ddr = @sfr.DDRB.2;
	
	public bit CS_port = @sfr.PORTB.3;
	//bit CS_pin = @sfr.PINB.3;
	public bit CS_ddr = @sfr.DDRB.3;
}
//*******************************************************
//主控制元件
unit main
{
	//主函数
	void main()
	{
		//发光二极管初始化
		led.init();
		led.flash( 1 );
		
		//液晶屏初始化
		screen.init();
		screen.clear();
		
		//MP3解码芯片初始化
		vs1003b.init();
		
		//FAT32文件系统初始化
		FAT32.init();
		if( !FAT32.is_ok ) {
			screen.put_const_string( 0, 0, "SD init failed!" );
			led.flash( 10 );
		}
		screen.put_const_string( 0, 0, "START PLAY..." );
		time.delay_10ms( 100 );
		play();
		screen.clear();
		screen.put_const_string( 0, 0, "PLAY END" );
		
		forever {
			led.flash( 2 );
			time.delay_10ms( 100 );
		}
	}
	//遍历硬盘,显示所有文件的名称和大小,如果是MP3文件就播放
	//MP3文件可以放在任意文件夹中,文件夹的层数不能超过8层
	void play()
	{
		FAT32.open_root_directory();
		FAT32.select_first_item();
		screen.clear();
		
		forever 
		{
			if( selected_item.is_out ) 
			{
				//screen.put_char( 0, current_level * 10, ' ' );
				bool is_right = FAT32.close_current_directory();
				if( !is_right ) 
				{
					return;
				}
				FAT32.select_next_item();
			}
			if( !selected_item.is_directory && !selected_item.is_file ) {
				FAT32.select_next_item();
				continue;
			}
			//显示硬盘目录层次
			//uint8 index = directory_node[current_level].current_sector << 4;
			//index += (uint8)( directory_node[current_level].current_index >> 5 );
			//screen.put_char( 0, current_level * 10, 'A' + index );
			//显示文件名
			screen.put_ram_string( 1, 0, selected_item.base_name );
			screen.put_char( 1, 8 * 5, '.' );
			screen.put_ram_string( 1, 9 * 5, selected_item.extend_name );
			//显示文件大小
			screen.put_const_string( 2, 0, "SIZE: " );
			uint8 size = (uint8)( selected_item.length >> 10 );
			screen.put_hex_byte( 2, 40, size );
			screen.put_const_string( 2, 50, "KB" );
			time.delay_10ms( 100 );
			
			//如果是目录,就进入
			if( selected_item.is_directory ) {
				FAT32.open_selected_directory();
				FAT32.select_first_item();
			}
			else {
				//判断是否为MP3文件
				if( selected_item.extend_name[0] == 'M' &&
				    selected_item.extend_name[1] == 'P' &&
				    selected_item.extend_name[2] == '3' ) {
					FAT32.open_selected_file();
					play_mp3_file();
					FAT32.close_current_file();
				}
				FAT32.select_next_item();
			}
		}
	}
	//显示txt电子书文件内容
	void show_txt_file()
	{
		uint16 index = 0;
		forever {
			screen.clear();
			uint8 line = 0;
			uint8 column = 0;
			do {
				uint8 c = FAT32.buffer[index];
				++index;
				if( FAT32.file_index + index >= selected_item.length ) {
					return;
				}
				if( index == 512 ) {
					FAT32.read_next_sector();
					index = 0;
				}
				if( c == 0x0d ) {
					++line;
					column = 0;
					continue;
				}
				if( c == 0x0a ) {
					continue;
				}
				screen.put_char( line, column, c );
				column += 5;
				if( column >= 16 * 5 ) {
					++line;
					column = 0;
				}
			}
			while( line < 6 );
			time.delay_10ms( 100 );
		}
	}
	//播放MP3文件内容
	void play_mp3_file()
	{
		uint16 index = 0;
		forever {
			loop( 16 ) {
				//等待解码芯片空闲
				while( vs1003b.is_busy() ) {}
				vs1003b.write_buffer_data( FAT32.buffer + index );
				index += 32;
			}
			if( FAT32.file_index + index >= selected_item.length ) {
				return;
			}
			if( index == 512 ) {
				led.set_LED( true );
				FAT32.read_next_sector();
				index = 0;
				led.set_LED( false );
			}
		}
	}
}
//*******************************************************
//FAT32文件系统
unit FAT32
{
	//初始化
	public void init()
	{
		is_ok = false;
		
		//SD卡初始化
		SD_card.init();
		is_ok = SD_card.reset();
		
		//读取MBR
		is_ok = SD_card.read_block( 0, buffer );
		
		//获取硬盘总空间
		disk_sector_size.0[uint8] = buffer[0x01ca];
		disk_sector_size.8[uint8] = buffer[0x01cb];
		disk_sector_size.16[uint8] = buffer[0x01cc];
		disk_sector_size.24[uint8] = buffer[0x01cd];
		
		//隐藏扇区数
		uint32 hidden_sector_number;
		hidden_sector_number.0[uint8] = buffer[0x01c6];
		hidden_sector_number.8[uint8] = buffer[0x01c7];
		hidden_sector_number.16[uint8] = buffer[0x01c8];
		hidden_sector_number.24[uint8] = buffer[0x01c9];
		
		//读取DBR
		is_ok = SD_card.read_block( hidden_sector_number, buffer );
		//每扇区字节数
		sector_byte_size.0[uint8] = buffer[0x000b];
		sector_byte_size.8[uint8] = buffer[0x000c];
		//每簇的扇区数
		cluster_sector_size = buffer[0x000d];
		//FAT表数目
		FAT_number = buffer[0x0010];
		//每个FAT表占据的扇区数
		FAT_sector_size.0[uint8] = buffer[0x0024];
		FAT_sector_size.8[uint8] = buffer[0x0025];
		FAT_sector_size.16[uint8] = buffer[0x0026];
		FAT_sector_size.24[uint8] = buffer[0x0027];
		
		//保留扇区数
		uint16 reserved_sector_number;
		reserved_sector_number.0[uint8] = buffer[0x000e];
		reserved_sector_number.8[uint8] = buffer[0x000f];
		
		FAT1_start_sector = hidden_sector_number + reserved_sector_number;
		FAT2_start_sector = FAT1_start_sector + FAT_sector_size;
		cluster_start_sector = FAT2_start_sector + FAT_sector_size;
		cluster_start_sector -= cluster_sector_size * 2;
		
		is_ok = true;
	}
	//打开根目录
	public void open_root_directory()
	{
		current_level = 0;
		directory_node[current_level].start_cluster = 2;
	}
	//打开选中的目录
	public void open_selected_directory()
	{
		++current_level;
		directory_node[current_level].start_cluster = selected_item.start_cluster;
	}
	//退出当前目录,成功时返回true,失败时返回false
	public bool close_current_directory()
	{
		if( current_level == 0 ) {
			return false;
		}
		--current_level;
		uint32 sector = get_first_sector_of_cluster(
			directory_node[current_level].current_cluster );
		sector += directory_node[current_level].current_sector;
		is_ok = SD_card.read_block( sector, buffer );
		return true;
	}
	//选中当前目录的第一项
	public void select_first_item()
	{
		uint32 cluster = directory_node[current_level].start_cluster;
		directory_node[current_level].current_cluster = cluster;
		directory_node[current_level].current_sector = 0;
		directory_node[current_level].current_index = 0;
		uint32 sector = get_first_sector_of_cluster( cluster );
		is_ok = SD_card.read_block( sector, buffer );
		get_current_item_info();
	}
	//选中当前目录的下一项
	public void select_next_item()
	{
		uint16 i = directory_node[current_level].current_index;
		i += 0x20;
		if( i == 0x0200 ) {
			i = 0;
			++directory_node[current_level].current_sector;
			
			uint32 sector = get_first_sector_of_cluster(
			directory_node[current_level].current_cluster );
			sector += directory_node[current_level].current_sector;
			if( sector == cluster_sector_size ) {
				//获取下一簇
				uint32 c_cluster = get_next_cluster(
						directory_node[current_level].current_cluster );
				directory_node[current_level].current_cluster = c_cluster;
				if( c_cluster >= 0x0f_ff_ff_00 ) {
					selected_item.is_out = true;
					return;
				}
				sector = get_first_sector_of_cluster( current_file_cluster );
				directory_node[current_level].current_sector = 0;
			}
			is_ok = SD_card.read_block( sector, buffer );
		}
		directory_node[current_level].current_index = i;
		get_current_item_info();
	}
	
	uint32 current_file_cluster;
	uint32 current_file_sector_offset;
	uint32 current_file_sector;
	public uint32 file_index;
	//打开选中的文件
	public void open_selected_file()
	{
		current_file_cluster = selected_item.start_cluster;
		current_file_sector = get_first_sector_of_cluster( current_file_cluster );
		is_ok = SD_card.read_block( current_file_sector, buffer );
		current_file_sector_offset = 0;
		file_index = 0;
	}
	//读取下一个扇区
	public void read_next_sector()
	{
		file_index += sector_byte_size;
		++current_file_sector_offset;
		if( current_file_sector_offset == cluster_sector_size ) {
			//获取下一簇
			current_file_cluster = get_next_cluster( current_file_cluster );
			if( current_file_cluster >= 0x0f_ff_ff_00 ) {
				return;
			}
			current_file_sector = get_first_sector_of_cluster( current_file_cluster );
			current_file_sector_offset = 0;
		}
		is_ok = SD_card.read_block( current_file_sector + current_file_sector_offset, buffer );
	}
	//关闭当前的文件
	public void close_current_file()
	{
		uint32 sector = get_first_sector_of_cluster(
			directory_node[current_level].current_cluster );
		sector += directory_node[current_level].current_sector;
		is_ok = SD_card.read_block( sector, buffer );
	}
	//获取当前簇的下一个簇号
	uint32 get_next_cluster( uint32 c_cluster )
	{
		uint32 sector = FAT1_start_sector + ( c_cluster >> 7 );
		is_ok = SD_card.read_block( sector, buffer );
		uint16 offset = (uint16)( c_cluster << 2 & 0x0000_01ff );
		c_cluster.0[uint8] = buffer[offset];
		c_cluster.8[uint8] = buffer[offset + 1];
		c_cluster.16[uint8] = buffer[offset + 2];
		c_cluster.24[uint8] = buffer[offset + 3];
		return c_cluster;
	}
	//获取一个簇的首扇区号
	uint32 get_first_sector_of_cluster( uint32 cluster )
	{
		//这里最好改成 cluster * cluster_sector_size + cluster_start_sector;
		
		return ( cluster << 3 ) + cluster_start_sector;
	}
	//获取当前项的信息
	void get_current_item_info()
	{
		uint16 index = directory_node[current_level].current_index;
		//项目类型
		selected_item.type = buffer[index + 0];
		if( selected_item.type == selected_item.NULL ) {
			selected_item.is_out = true;
		}
		else {
			selected_item.is_out = false;
		}
		if( selected_item.type == selected_item.DELETE ) {
			selected_item.is_delete = true;
		}
		else {
			selected_item.is_delete = false;
		}
		if( selected_item.type == selected_item.SYSTEM_DIR ) {
			selected_item.is_system_dir = true;
		}
		else {
			selected_item.is_system_dir = false;
		}
		//复制文件基本名
		*uint8 p1 = selected_item.base_name;
		*uint8 p2 = buffer + index;
		loop( 8 ) {
			*p1 = *p2;
			++p1;
			++p2;
		}
		*p1 = 0;
		//复制文件扩展名
		p1 = selected_item.extend_name;
		loop( 3 ) {
			*p1 = *p2;
			++p1;
			++p2;
		}
		*p1 = 0;
		//获取文件属性
		selected_item.attribute = buffer[index + 11];
		if( selected_item.attribute == 0x0f ) {
			selected_item.is_long_name = true;
		}
		else {
			selected_item.is_long_name = false;
		}
		selected_item.is_directory = false;
		selected_item.is_file = false;
		if( !selected_item.is_out && !selected_item.is_delete && !selected_item.is_system_dir && !selected_item.is_long_name ) {
			if( selected_item.attribute & selected_item.DIRECTORY != 0 ) {
				selected_item.is_directory = true;
			}
			else {
				selected_item.is_file = true;
			}
		}
		//获取文件起始簇号
		selected_item.start_cluster.0[uint8] = buffer[index + 26];
		selected_item.start_cluster.8[uint8] = buffer[index + 27];
		selected_item.start_cluster.16[uint8] = buffer[index + 20];
		selected_item.start_cluster.24[uint8] = buffer[index + 21];
		//获取文件长度(单位字节)
		selected_item.length.0[uint8] = buffer[index + 28];
		selected_item.length.8[uint8] = buffer[index + 29];
		selected_item.length.16[uint8] = buffer[index + 30];
		selected_item.length.24[uint8] = buffer[index + 31];
	}
	
	//目录列表
	struct s_directory_node
	{

⌨️ 快捷键说明

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