📄 fat__.c
字号:
#include <mega32.h>
#ifndef __SLEEP_DEFINED__
#define __SLEEP_DEFINED__
.EQU __se_bit=0x80
.EQU __sm_mask=0x70
.EQU __sm_powerdown=0x20
.EQU __sm_powersave=0x30
.EQU __sm_standby=0x60
.EQU __sm_ext_standby=0x70
.EQU __sm_adc_noise_red=0x10
.SET power_ctrl_reg=mcucr
#endif
#include "type.h"
#include "fat.h"
#include "sd.c"
#include "sd.h"
//低速模式
void SPI_Low(void)
{
SPCR =0x52;//_BV(SPE)|_BV(MSTR)|_BV(SPR1)|_BV(SPR0);
SPSR &= 0xfe; //关双速
}
//高速模式
void SPI_High(void)
{
SPCR =0x50;// _BV(SPE)|_BV(MSTR);
SPSR |=0x01;// _BV(SPI2X); //开双速
}
//端口初始化,模式初始化
void SPI_Init(void)
{
DDR_INI(); //端口设置,主要是SPI
SPI_Low(); //先低速
}
//sd卡初始化
void MMC_SD_Init(void)
{
SPI_Init();
SPI_CS_Deassert();//cs=1
}
//写读一个字节 //read and write one byte
uint8 SPI_WriteByte(uint8 val)
{
SPDR = val;
while(SPSR.7==0);
return SPDR;
}
//sd卡写命令
uint8 MMC_SD_SendCommand(uint8 cmd, uint32 arg)
{
uint8 r1;
uint8 retry=0;
SPI_WriteByte(0xff);
SPI_CS_Assert(); //CS=0
SPI_WriteByte(cmd | 0x40);//分别写入命令
SPI_WriteByte(arg>>24);
SPI_WriteByte(arg>>16);
SPI_WriteByte(arg>>8);
SPI_WriteByte(arg);
SPI_WriteByte(0x95);
while((r1 = SPI_WriteByte(0xff)) == 0xff)//等待响应,
if(retry++ > 200) break;//超时退出
SPI_CS_Deassert(); //cs=1
return r1;//返回状态值
}
//sd卡复位
uint8 MMC_SD_Reset(void)
{
uint8 i;
uint8 retry;
uint8 r1=0;
retry = 0;
SPI_Low();
SPI_CS_Deassert();//
for(i=0; i<16; i++)
SPI_WriteByte(0xFF);
do
{
for(i=0;i<20;i++) SPI_WriteByte(0xff);
r1 = MMC_SD_SendCommand(0, 0);//发idle命令
retry++;
//TransmitByte(retry);
if(retry>200) return 1;//超时退出
} while(r1 != 0x01);
retry = 0;
do
{
r1 = MMC_SD_SendCommand(1, 0);//发active命令
retry++;
if(retry>100) return 1;//超时退出
} while(r1);
SPI_High();
r1 = MMC_SD_SendCommand(59, 0);//关crc
r1 = MMC_SD_SendCommand(16, 512);//设扇区大小512
return 0;//正常返回
}
//读一个扇区
uint8 MMC_SD_ReadSingleBlock(uint32 sector, uint8* buffer)
{
uint8 r1;
uint16 i;
uint16 retry=0;
SPI_CS_Deassert();//
for(i=0; i<16; i++)
SPI_WriteByte(0xFF);
r1 = MMC_SD_SendCommand(17, sector<<9);//读命令 /9
if(r1 != 0x00)
return r1;
SPI_CS_Assert(); //cs=0
//等数据的开始
while(SPI_WriteByte(0xff) != 0xfe)if(retry++ > 1000){SPI_CS_Deassert();return 1;}
for(i=0; i<512; i++)//读512个数据
{
*buffer++ = SPI_WriteByte(0xff);
}
SPI_WriteByte(0xff);//伪crc
SPI_WriteByte(0xff);
SPI_CS_Deassert(); //cs=1
return 0;
}
/*
//读一个扇区
uint8 MMC_SD_ReadSingleBlock1(uint32 sector, uint8* buffer)
{
uint8 r1;
uint16 i;
uint16 retry=0;
MMC_SD_SendCommand(16, 256);
r1 = MMC_SD_SendCommand(17, sector<<8);//读命令 /9
if(r1 != 0x00)
return r1;
SPI_CS_Assert(); //cs=0
//等数据的开始
while(SPI_WriteByte(0xff) != 0xfe)if(retry++ > 1000){SPI_CS_Deassert();return 1;}
for(i=0; i<256; i++)//读512个数据
{
*buffer++ = SPI_WriteByte(0xff);
}
SPI_WriteByte(0xff);//伪crc
SPI_WriteByte(0xff);
SPI_CS_Deassert(); //cs=1
return 0;
}
*/
u8 bf[512];
u8 secpclus; //每籁包函扇区数
u16 fr_fatsec; //FAT表首扇区
u16 rodir; // 根目录首扇区
u8 firstrodirclus; //根目录的首籁号
u32 filefirstclus; //文件首籁号
u32 filesize; //
BYTE (* FAT_ReadSector)(DWORD sector, BYTE * buffer) = MMC_SD_ReadSingleBlock;//device read
///FAT初始化
unsigned char FAT_Init()
{ u32 x;
DWORD *p;
u16 *rscnt;//保留扇区数
u32 *fatsz;//FAT大小
if(FAT_ReadSector(0,bf))return 1; //读出启动扇区
p=&bf[454]; //取出分区启动扇区地址
x=*p;
FAT_ReadSector(x,bf); //读分区的启动扇区
secpclus=bf[13]; //每籁的扇区数
rscnt=&bf[14]; //保留扇区
fatsz=&bf[36]; //FAT大小
firstrodirclus=bf[44];//根目录的首籁号0
fr_fatsec=x+(*rscnt); //FAT首扇区
rodir=fr_fatsec+(*fatsz)*2; //算出根目录
return 0;
}
//读一个簇中的一个扇区
unsigned char FAT_LoadPartCluster(unsigned long cluster,unsigned part,BYTE * buffer)
{
DWORD sector;
sector=rodir+(DWORD)(cluster-2)*(DWORD)secpclus;//算出扇区
if(MMC_SD_ReadSingleBlock(sector+part,buffer))return 1;
else return 0;
}
//读下一簇簇号
unsigned long FAT_NextCluster(unsigned long cluster)
{ u32 *x;
DWORD sector;
DWORD offset;
offset = cluster/128;
if(cluster<2){return 0x0ffffff8;}
sector=fr_fatsec+offset;
if(FAT_ReadSector(sector,bf))return 0x0ffffff8;//读FAT表
offset=cluster%128;//因为籁号大于128时就会跨扇区
x=&bf[offset*4];
return *x;
}
//----------------------------------------
//读下一簇簇号
unsigned long FAT_NextCluster1(unsigned long cluster)
{ u32 *x;
u8 r1,i;
u16 retry=0;
u8 buf[4];
DWORD sector;
DWORD offset;
offset = cluster/128;
//if(cluster<2){return 0x0ffffff8;}
sector=(fr_fatsec+offset)*512;
offset=cluster%128;//因为籁号大于128时就会跨扇区
sector=sector+offset*4;
MMC_SD_SendCommand(16, 4);
r1 = MMC_SD_SendCommand(17, sector);
if(r1 != 0x00)
return r1;
SPI_CS_Assert(); //cs=0
//等数据的开始
while(SPI_WriteByte(0xff) != 0xfe)if(retry++ > 1000){SPI_CS_Deassert();return 1;}
for(i=0; i<4; i++)//读4个数据
{
buf[i] = SPI_WriteByte(0xff);
}
x=buf;
SPI_WriteByte(0xff);//伪crc
SPI_WriteByte(0xff);
MMC_SD_SendCommand(16,512);
SPI_CS_Deassert(); //cs=1
return *x;
}
//-------------------------
///////////////////////////////////////
//search the file , when *count = 0 it will bring the number whole songs, when *cout != 0 the *MusicInfo will bring the infomation of the file
BYTE Search(WORD *Count)//当COUNT为零时,有它带回这个目录下总共有多少首音乐
{ u32 tempclust,sector;
u8 cnt;
u16 offset;
u16 i=0;
u16 *p;
tempclust=firstrodirclus;
while(1)
{ sector=rodir+(DWORD)(tempclust-2)*(DWORD)secpclus;//算出扇区
for(cnt=0;cnt<secpclus;cnt++)//读一个籁
{
if(FAT_ReadSector(sector+cnt,bf)){return 1;}
for(offset=0;offset<512;offset+=32)//扇区内遍历
{
if((bf[offset] !=0)&(bf[offset] !='.')&(bf[offset] !=0xe5)&(bf[offset+11]!=0x0f))
{
if((bf[offset+8] == 'W')&&(bf[offset+9] == 'A')&&(bf[offset+10] == 'V'))
{
p=&bf[offset+20];
filefirstclus=*p;
//TransmitByte(filefirstclus);
filefirstclus=filefirstclus<<16;
p=&bf[offset+26];
filefirstclus=(filefirstclus+*p);
p=&bf[offset+28];
filesize=*p;
i++;
if(i==*Count){return 0;}
}
}
}
}
tempclust=FAT_NextCluster(tempclust);//next cluster
if(tempclust == 0x0fffffff || tempclust == 0x0ffffff8 )break;
}
if(*Count==0)*Count=i;
return 0;
}
/*
09-4-4完成FAT的初始化,读取分区表,启动扇区
09-4-5完成FAT表。文件查找
09-4-6完成双缓冲播放//88.2K不卡(24M)
*/
#include <mega32.h>
#ifndef __SLEEP_DEFINED__
#define __SLEEP_DEFINED__
.EQU __se_bit=0x80
.EQU __sm_mask=0x70
.EQU __sm_powerdown=0x20
.EQU __sm_powersave=0x30
.EQU __sm_standby=0x60
.EQU __sm_ext_standby=0x70
.EQU __sm_adc_noise_red=0x10
.SET power_ctrl_reg=mcucr
#endif
#include <delay.h>
#include "sd.h"
#include "fat.h"
#include "type.h"
#define ClockCPU 24000000
#define Baud 2400//串口
extern u8 bf[512];
extern u8 secpclus; //每籁包函扇区数
extern u16 fr_fatsec; //FAT表首扇区
extern u16 rodir; // 根目录首扇区
extern u8 firstrodirclus; //根目录的首籁号
extern u32 filefirstclus; //文件首籁号
extern u32 filesize;//文件大小(字节)
u16 totalsongs;
u16 flag,j,f=0;
u8 chanal;//文件声道数
u8 timer;
u8 bf1[1024];
///================
void UART_Init(void)
{UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRL = (ClockCPU/Baud)/16-1;
}
//----------------------------
//==============================
void TransmitByte( u8 data )
{
while ( !(UCSRA & (1<<5)) );
UDR = data;
}
//-------------------------------------------
//中断服务
//主要是重设定时器初值,放出声音,检测是否要读SD卡
//------------------------------------------
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=timer+2;
OCR1AL=bf1[j];
if(chanal==2)j++;//立体声时就要用下个数给下个声道
OCR1BL=bf1[j];
j++;
if(j==512){flag=1;} //要读缓冲2
if(j==1024)
{j=0;
flag=2; //要读缓冲2
}
}
//-----------------------------------------------------
//播放函数
//-----------------------------------------------------
void PlayMusicwithKey()//播放音乐函数,一旦执行不会退出
{
uint8 i; //循环变量
u32 *p;
uint32 totalsect;//文件拥有的扇区数
uint16 leftbytes;//剩余字节
uint16 songs=1;
next:
#asm("cli")
Search(&songs); //找到相应的文件
TransmitByte(songs); //文件首籁号
TransmitByte(filefirstclus>>24); //文件首籁号
TransmitByte(filefirstclus>>16); //文件首籁号
TransmitByte(filefirstclus>>8); //文件首籁号
TransmitByte(filefirstclus); //文件首籁号
delay_ms(1000);
delay_ms(1000);
totalsect = filesize/512; //计算扇区数
leftbytes = filesize%512; //计算剩余的字节数
i=0;
flag=0;
FAT_LoadPartCluster(filefirstclus,0,bf1);
chanal=bf1[22];//读取声道数
p= &bf1[24];
FAT_LoadPartCluster(filefirstclus,1,&bf1[512]);
//读取WAV文件头,取得采样率,计算定时器初值
if(ClockCPU/(*p)>255)
{
if(ClockCPU/(*p*8)>255)
{if(ClockCPU/(*p*64)>255)while(1);
else {timer=0xff-ClockCPU/(*p*64);
TCCR0=0x03;
}
}
else {timer=0xff-ClockCPU/(*p*8);
TCCR0=0x02;
}
}
else {timer=0xff-ClockCPU/(*p);
TCCR0=0x01;
}
filefirstclus=FAT_NextCluster1(filefirstclus);
#asm("sei")
flag=0;
j=0;
while(1)
{
if(flag==1)
{
FAT_LoadPartCluster(filefirstclus,i,bf1);
flag=0;
i++;
if(i==secpclus){i=0;
filefirstclus=FAT_NextCluster1(filefirstclus);
if(filefirstclus== 0x0fffffff || filefirstclus== 0x0ffffff8 )//如果无后续簇则结束
{
songs++;
if(songs>totalsongs)songs=1;
goto next;
}
}
}
if(flag==2) {
FAT_LoadPartCluster(filefirstclus,i,&bf1[512]);
flag=0;
i++;
if(i==secpclus){i=0;
filefirstclus=FAT_NextCluster1(filefirstclus);
if(filefirstclus== 0x0fffffff || filefirstclus== 0x0ffffff8 )//如果无后续簇则结束
{
songs++;
if(songs>totalsongs)songs=1;
goto next;
}
}
}
DDRA=0x00;
PORTA=0XFF;
if(PINA!=0xff)
{ #asm("cli")
delay_ms(100);
if(PINA!=0xff)
{ f=PINA;
while(PINA!=0xff);
if(f==0xfe)
{songs++;
if(songs>totalsongs)songs=1;
goto next;
}
if(f==0xfd)
{songs--;
if(songs==0)songs=1;
goto next;
}
}
#asm("sei")
}
}
}
void main(void)
{
uint8 retry = 0;
DDRA= 0xff;//初始化端口
PORTA = 0xff;
DDRC= 0xff;//初始化端口
PORTC = 0xff;
DDRD= 0xff;//初始化端口
PORTD = 0xff;
delay_ms(10);
TCCR0=0x02;
TCNT0=0xbc;
OCR0=0x00;
TCCR1A=0xA2;
TCCR1B=0x19;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x0;
ICR1L=0xff;
OCR1AH=0x00;
OCR1AL=30;
OCR1BH=0x00;
OCR1BL=30;
TIMSK=0x01;
ACSR=0x80;
MMC_SD_Init ();//初始化spi口
UART_Init();
while(MMC_SD_Reset())//初始化SD卡
{
retry++;
if(retry>20)
{ DDRA=0XFF;
while(1)
{for (retry=0;retry<0xff;retry++)
{TransmitByte(0X22); }
}
}
}
delay_ms(0xff);
if(FAT_Init())//初始化文件系统 支持FAT16和FAT32
{
DDRD=0XFF;
while(1)
{
TransmitByte(0xf2);
}
}
totalsongs=0;
Search(&totalsongs);//找WAV文件总数
/*
TransmitByte(totalsongs);
for(retry=1;retry<totalsongs;retry++)
{Search(&retry);
TransmitByte(retry); //文件首籁号
TransmitByte(filefirstclus>>24); //文件首籁号
TransmitByte(filefirstclus>>16); //文件首籁号
TransmitByte(filefirstclus>>8); //文件首籁号
TransmitByte(filefirstclus); //文件首籁号
}
*/
PlayMusicwithKey();
while (1)
{
// Place your code here
//TransmitByte(0xf0);
};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -