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

📄 fat__.c

📁 以AVRMEGA32播放SD卡中的WAV音乐
💻 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 + -