?? mp3.c
字號(hào):
//晶振: 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
{
//主函數(shù)
void main()
{
//發(fā)光二極管初始化
led.init();
led.flash( 1 );
//液晶屏初始化
screen.init();
screen.clear();
//MP3解碼芯片初始化
vs1003b.init();
//FAT32文件系統(tǒng)初始化
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文件可以放在任意文件夾中,文件夾的層數(shù)不能超過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 );
//如果是目錄,就進(jìn)入
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電子書文件內(nèi)容
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文件內(nèi)容
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文件系統(tǒng)
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];
//隱藏扇區(qū)數(shù)
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 );
//每扇區(qū)字節(jié)數(shù)
sector_byte_size.0[uint8] = buffer[0x000b];
sector_byte_size.8[uint8] = buffer[0x000c];
//每簇的扇區(qū)數(shù)
cluster_sector_size = buffer[0x000d];
//FAT表數(shù)目
FAT_number = buffer[0x0010];
//每個(gè)FAT表占據(jù)的扇區(qū)數(shù)
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];
//保留扇區(qū)數(shù)
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;
}
//退出當(dāng)前目錄,成功時(shí)返回true,失敗時(shí)返回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;
}
//選中當(dāng)前目錄的第一項(xiàng)
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();
}
//選中當(dāng)前目錄的下一項(xiàng)
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;
}
//讀取下一個(gè)扇區(qū)
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 );
}
//關(guān)閉當(dāng)前的文件
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 );
}
//獲取當(dāng)前簇的下一個(gè)簇號(hào)
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;
}
//獲取一個(gè)簇的首扇區(qū)號(hào)
uint32 get_first_sector_of_cluster( uint32 cluster )
{
//這里最好改成 cluster * cluster_sector_size + cluster_start_sector;
return ( cluster << 3 ) + cluster_start_sector;
}
//獲取當(dāng)前項(xiàng)的信息
void get_current_item_info()
{
uint16 index = directory_node[current_level].current_index;
//項(xiàng)目類型
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;
}
//復(fù)制文件基本名
*uint8 p1 = selected_item.base_name;
*uint8 p2 = buffer + index;
loop( 8 ) {
*p1 = *p2;
++p1;
++p2;
}
*p1 = 0;
//復(fù)制文件擴(kuò)展名
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;
}
}
//獲取文件起始簇號(hào)
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];
//獲取文件長(zhǎng)度(單位字節(jié))
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
{
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -