找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5632|回复: 2
打印 上一主题 下一主题
收起左侧

51单片机的音乐播放器源码(插SD卡)

[复制链接]
跳转到指定楼层
楼主
ID:102668 发表于 2016-1-16 05:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

  1. #include <12c56.H>
  2. #define uint8 unsigned char
  3. #define uint16 unsigned int
  4. #define uint32 unsigned long
  5. sbit SDCS = P1^4;
  6. sbit LAST = P3^3;
  7. sbit NEXT = P3^4;
  8. sbit STOP = P2^5;
  9. uint32 played;
  10. volatile uint32 start_offset;
  11. volatile uint16 tptr=0,bdat=0;
  12. // 播放    插卡 曲目  立体声
  13. bit PLAY=0, CK=1  ,QM=0, STEREO=1;
  14. xdata uint8 buf0[512];
  15. void delay(uint16 dly)
  16. {
  17. uint16 i;
  18. uint8  j;
  19. for(i=0;i<dly;i++)
  20.   for(j=0;j<10;j++)
  21.    ;
  22. }

  23. void T1ISR() interrupt 3
  24. {
  25. static uint8 x=0;
  26.   if(!PLAY)
  27. {
  28.   x++;
  29.   if(x==4)x=0;

  30.   if(!x)
  31.   {
  32.    if(CK)
  33.    {
  34.     if(tptr==1920)
  35.     {
  36.      tptr=0;
  37.      TR1=0;
  38.     }
  39.     else
  40.        tptr++;
  41.    }
  42.    else if(QM)
  43.    {
  44.     if(tptr==1376)
  45.     {
  46.      tptr=0;
  47.      TR1=0;
  48.     }
  49.     else
  50.      tptr++;
  51.    }
  52.    else
  53.    {
  54.      ISP_ADDRH=(tptr>>8)&0xFF;
  55.     ISP_ADDRL=(tptr   )&0xFF;
  56.    
  57.     ISP_CONTR=0x80;
  58.     ISP_CMD=1;
  59.     ISP_TRIG=0x46;
  60.     ISP_TRIG=0xB9;
  61.    
  62.     tptr++;
  63.   
  64.     if(tptr==0x0480)TR1=0; //容量
  65.     if(tptr==0x0780)TR1=0; //0
  66.     if(tptr==0x0a80)TR1=0; //1
  67.     if(tptr==0x0d80)TR1=0; //2
  68.     if(tptr==0x1080)TR1=0; //3
  69.     if(tptr==0x1380)TR1=0; //4
  70.     if(tptr==0x1680)TR1=0; //5
  71.     if(tptr==0x1980)TR1=0; //6
  72.     if(tptr==0x1c80)TR1=0; //7
  73.     if(tptr==0x1f80)TR1=0; //8
  74.     if(tptr==0x2280)TR1=0; //9
  75.     if(tptr==0x2580)TR1=0; //千
  76.     if(tptr==0x2880)TR1=0; //百
  77.     if(tptr==0x2b80)TR1=0; //十
  78.     if(tptr==0x2e80)TR1=0; //兆
  79.    }
  80.   }
  81.   else
  82.   {
  83.     ;
  84.   }
  85. }
  86. else
  87. {
  88.   CCAP0H=buf0[tptr++];
  89.   bdat--;
  90.   if(STEREO)
  91.   {
  92.    CCAP1H=buf0[tptr++];
  93.    bdat--;
  94.   }
  95.   else
  96.   {
  97.     CCAP1H=CCAP0H;
  98.   }
  99.   if(tptr>=512)
  100.   {
  101.    tptr=0;
  102.   }
  103. }
  104. }
  105. void SPI_INIT()
  106. {
  107.   SPCTL=0xd0;
  108. }
  109. void SPI_INIT_LOW()
  110. {
  111.   SPCTL=0xd1;
  112. }
  113. uint8  SPI_COMM(uint8 dat)
  114. {
  115.   SDCS=0;
  116. SPDAT=dat;
  117. while((SPSTAT&0x80)==0);
  118. SPSTAT=0x80;
  119. SDCS=1;
  120. return(SPDAT);
  121. }
  122. uint8 SD_SendCommand(uint8 cmd, uint32 arg)
  123. {
  124. uint8 r1;
  125. uint8 retry=0;

  126. SPI_COMM(0xff);
  127. SDCS=0;

  128. SPI_COMM(cmd | 0x40);//分别写入命令 //send command
  129. SPI_COMM(arg>>24);
  130. SPI_COMM(arg>>16);
  131. SPI_COMM(arg>>8);
  132. SPI_COMM(arg);
  133. SPI_COMM(0x95);

  134. while((r1 = SPI_COMM(0xff)) == 0xff)//等待响应, //wait response
  135.   if(retry++ > 20) break;//超时退出     //time out error
  136. SDCS=1;
  137. return r1;//返回状态值     //return state
  138. }
  139. uint8  InitSD()
  140. {
  141. uint8 tmp,ret;

  142. for(tmp=0;tmp<0x0f;tmp++)
  143.   SPI_COMM(0xff);

  144. SDCS=0;
  145. SPI_COMM(0x40);
  146. SPI_COMM(0x00);
  147. SPI_COMM(0x00);
  148. SPI_COMM(0x00);
  149. SPI_COMM(0x00);
  150. SPI_COMM(0x95);

  151. for(tmp=0;tmp<0x7f;tmp++)
  152. {
  153.   ret=SPI_COMM(0xff);
  154.   
  155.   if(ret==0x01)
  156.   {   
  157.    uint8 retry=0,r1;
  158.    
  159.    do
  160.    {
  161.     r1 = SD_SendCommand(1, 0);//发active命令 //send active command
  162.     retry++;
  163.     if(retry>100) return 1;//超时退出  //time out
  164.    } while(r1);
  165.    
  166.    //SPI_High();
  167.    r1 = SD_SendCommand(59, 0);//关crc  //disable CRC
  168.    r1 = SD_SendCommand(16, 512);//设扇区大小512 //set sector size to 512
  169.   
  170.    return 0;
  171.   }
  172. }

  173. SDCS=1;
  174. return 1;
  175. }
  176. //读一个扇区  //read one sector
  177. uint8 SD_ReadSector(uint32 sector, uint8* buffer)
  178. {
  179. uint8 r1;
  180. uint16 i;
  181. uint16 retry=0;
  182. r1 = SD_SendCommand(17, (start_offset+sector)<<9);//读命令 //read command

  183. if(r1 != 0x00)
  184.   return r1;
  185. SDCS=0;

  186. //等数据的开始 //wait to start recieve data
  187. while(SPI_COMM(0xff) != 0xfe)
  188.   if(retry++ > 1000)
  189.   {
  190.    SDCS=1;
  191.    return 1;
  192.   }
  193. for(i=0; i<512; i++)//读512个数据
  194. {
  195.   bdat++;
  196.   while(bdat>=512);
  197.   *buffer++ = SPI_COMM(0xff);
  198. }

  199. SPI_COMM(0xff);//伪crc
  200. SPI_COMM(0xff);

  201. SDCS=1;
  202. return 0;
  203. }

  204. void TIMER0_INIT()
  205. {
  206. TMOD=0x22;   
  207. TH0=TL0=0xFF;
  208. TR0=1;
  209. ET0=0;
  210. }
  211. void TIMER1_INIT(uint16 hz)
  212. {
  213. if(hz>=8000)
  214. {
  215.   CLK_DIV=0x00;
  216.   TH1=TL1=(uint8)(256-((uint32)1040000/hz));//0x7e;
  217. }
  218. else
  219. {
  220.   CLK_DIV=0x02;
  221.   TH1=TL1=(uint8)(256-((uint32)260000/hz));//0x7e;
  222. }
  223. TR1=0;
  224. EA=1;
  225. ET1=1;
  226. }
  227. void CCP_INIT()
  228. {
  229. AUXR|=0x80;
  230. CMOD=0x04;
  231. CL=0x00;
  232. CH=0x00;
  233. CCAP0L=0x80;
  234. CCAP0H=0x80;
  235. CCAPM0=0x42;
  236. CCAP1L=0x80;
  237. CCAP1H=0x80;
  238. CCAPM1=0x42;
  239. CR=1;
  240. }

  241. void main()//主函数
  242. {
  243. uint8 i=0;
  244. uint32 ptr;
  245. uint8  FATs;
  246. uint16 BytesPerSector;
  247. uint8  SectorsPerClust;
  248. uint8  FirstFATSector;
  249. uint16 RootDirCount;
  250. uint16 RootDirSectors;
  251. uint16 FirstDirSector;
  252. uint16 FirstDataSector;
  253. uint32 samps;
  254. uint8  sbits;
  255. uint32 filelen;
  256. uint16 sPtr=0,iPtr=0;
  257. uint8  currTrack=0,Track=1;
  258. //------ 3.3V I/O口配置 -------
  259. P1M0=P1M1=0xf0; //P1.7-P1.4开漏
  260. //-----------------------------
  261. TIMER0_INIT();
  262. CCP_INIT();
  263. IT0=1;
  264. EX0=1;

  265. RESTART:
  266. Track=0;
  267. TR1=0;
  268. CK=1;
  269. tptr=0;
  270. PLAY=0;

  271. TIMER1_INIT(8000);
  272. TR1=1;
  273. while(TR1);
  274. CK=0;
  275. SPI_INIT_LOW();
  276. while(1)
  277. {
  278.   if(!InitSD())break;
  279. }
  280. SPI_INIT();
  281. delay(1000);

  282. tptr=0;
  283. TR1=1;
  284. while(TR1);
  285. TR1=1;
  286. while(TR1);
  287. delay(5000);
  288. goto read;
  289. LASTTRACK:
  290. TR1=0;
  291. PLAY=0;
  292. start_offset=0;
  293. currTrack=0;
  294. Track--;
  295. goto read;
  296. NEXTTRACK:
  297. TR1=0;
  298. PLAY=0;
  299. start_offset=0;
  300. currTrack=0;
  301. Track++;
  302. read:
  303. while(1)
  304. {
  305.   //FAT16文件系统处理
  306.   //判断引导扇区有效性
  307. bdat=65535;
  308.   if(!SD_ReadSector(0,buf0))
  309.   {
  310.    if((buf0[0]!=0xeb)||(buf0[1]!=0x3c)||(buf0[2]!=0x90)) //如果不是EB 3C 90说明有分区表,继续读取之,否则直接开始播放
  311.    {
  312.      start_offset=(buf0[0x01c6]<<0)|(buf0[0x01c7]<<8)|(buf0[0x01c8]<<16)|(buf0[0x01c9]<<24);
  313. bdat=65535;
  314.     SD_ReadSector(0,buf0);
  315.    }
  316.    if((buf0[510]==0x55)&&(buf0[511]==0xaa))
  317.    {
  318.     ;
  319.    }
  320.    else
  321.    {
  322.     goto RESTART;
  323.    }
  324.   }
  325.   else
  326.   {
  327.    goto RESTART;
  328.   }
  329.   //读FAT表信息
  330.   FATs=buf0[0x10];
  331.   BytesPerSector=buf0[0x0B]|(buf0[0x0C]<<8);
  332.   SectorsPerClust=buf0[0x0D];
  333.   FirstFATSector=buf0[0x0E];
  334.   RootDirCount=buf0[0x11]|(buf0[0x12]<<8);
  335.   RootDirSectors = (RootDirCount>>4);//根目录占用的扇区数
  336.   FirstDirSector=FirstFATSector+FATs*(buf0[0x16]|(buf0[0x17]<<8));
  337.   FirstDataSector = FirstDirSector+RootDirSectors;//第一个数据扇区
  338.   //搜索WAV文件   
  339.     for(sPtr=0;sPtr<RootDirSectors;sPtr++)
  340.     {
  341.      bdat=65535; //-1(允许读卡一次读完512字节)
  342.      SD_ReadSector(FirstDirSector+sPtr,buf0);
  343.      for(iPtr=0;iPtr<512;iPtr+=32)
  344.      {
  345.       if((buf0[iPtr]!='.')&&(buf0[iPtr]!=0x00)&&(buf0[iPtr]!=0xe5) & (buf0[iPtr+0x0B]!=0x0f))
  346.        if((buf0[iPtr+0x08]=='W')&&(buf0[iPtr+0x09]=='A')&&(buf0[iPtr+0x0a]=='V'))
  347.        {
  348.         ptr=(uint32)FirstDataSector+(uint32)SectorsPerClust*((buf0[iPtr+0x1A]|(buf0[iPtr+0x1B]<<8))-2);
  349.         filelen=(((uint32)buf0[iPtr+0x1c]|(((uint32)buf0[iPtr+0x1d])<<8)|(((uint32)buf0[iPtr+0x1e])<<16)|((uint32)(buf0[iPtr+0x1f])<<24))/512)-2;
  350.         currTrack++;
  351.         if(currTrack==Track)break;
  352.        }
  353.      }
  354.      if(currTrack==Track)break;
  355.     }
  356.    
  357.    
  358.    if(currTrack!=Track)
  359.    {
  360.     Track=0;
  361.     goto NEXTTRACK;
  362.    }
  363.    
  364.    bdat=65535;
  365.    SD_ReadSector(ptr++,buf0);
  366.    samps=(buf0[0x18]|(buf0[0x19]<<8)|(buf0[0x1A]<<16)|(buf0[0x1B]<<24));
  367.    sbits=buf0[0x22];
  368.    if(buf0[0x16]==2)
  369.     STEREO=1;
  370.    else
  371.     STEREO=0;

  372.    if(sbits!=8)
  373.    {
  374.    goto NEXTTRACK;
  375.     }

  376.    if(samps>48000)
  377.    {
  378.     goto NEXTTRACK;
  379.    }

  380. TIMER1_INIT(8000);
  381. QM=1;
  382. tptr=0;
  383. TR1=1;
  384. while(TR1);
  385. QM=0;
  386. TIMER1_INIT(samps/2);//(24000);
  387. bdat=65535;
  388. SD_ReadSector(ptr++,buf0);
  389. tptr=0;
  390. played=0;
  391. PLAY=1;
  392. TR1=1;
  393. while(1)
  394. {
  395.   
  396.   if(SD_ReadSector(ptr++,buf0))goto RESTART;
  397.   if(!LAST)goto LASTTRACK;
  398.   if(!NEXT)goto NEXTTRACK;
  399.   if(!STOP)PCON=PCON^0xfe;
  400.   if((played++)>filelen)goto NEXTTRACK;

  401. }

  402. }
  403. }
  404. void exint0() interrupt 0
  405. {
  406.       ;
  407. }
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:99130 发表于 2017-4-25 18:50 | 只看该作者
放个原理图吧 用了VS1003吗
回复

使用道具 举报

板凳
ID:976767 发表于 2021-12-15 09:09 | 只看该作者
请问有原理图没?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表