本帖最后由 迷你强 于 2013-8-30 22:37 编辑
没玩几天Arduino(mega328),手头也没什么模块,看了论坛里那篇Arduino播放音乐的教程后跟着做出来了(http://www.geek-workshop.com/for ... thread&tid=2611),还不错,但是缺点很明显,必须用电脑连串口输入文件名和命令,于是就改改程序加进IR接收,让板子可以摆脱电脑独立受遥控控制播放音乐,并不难,但是很实用,贴出来
分享一下。
SD卡的接线参照“Workshop Team”的上面那篇帖子,红外接收管脚可自定义,我设的D5脚。
代码当然是根据MostFunctionDemo.ino改的,库函数用word打开各种看不懂啊,不过关键地方改对就行。
- //This is used for play music on SD card under the control of IR remote;
- #include <SimpleSDAudio.h>
- #include<IRremote.h>
- int RECV_PIN = 5; //红外线接收器OUTPUT端接在pin 5
- IRrecv irrecv(RECV_PIN); // 定义IRrecv 对象来接收红外线信号
- decode_results results; //解码结果放在decode_results构造的对象results里
- // Callback target, prints output to serial
- void DirCallback(char *buf) {
- Serial.println(buf);
- }
- char AudioFileName[16];
- // Create static buffer
- #define BIGBUFSIZE (2*512) // bigger than 2*512 is often only possible on Arduino megas!
- uint8_t bigbuf[BIGBUFSIZE];
- // helper function to determine free ram at runtime
- int freeRam () {
- extern int __heap_start, *__brkval;
- int v;
- return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
- }
- void setup()
- {
- // Open serial communications and wait for port to open:
- Serial.begin(9600);
- irrecv.enableIRIn(); //启动红外解码
- //while (!Serial) {
- // wait for serial port to connect. Needed for Leonardo only
- //}
- Serial.print(F("Free Ram: "));
- Serial.println(freeRam());
-
- // Setting the buffer manually for more flexibility
- SdPlay.setWorkBuffer(bigbuf, BIGBUFSIZE);
-
- Serial.print(F("\nInitializing SimpleSDAudio V" SSDA_VERSIONSTRING " ..."));
-
- // If your SD card CS-Pin is not at Pin 4, enable and adapt the following line:
- //SdPlay.setSDCSPin(10);
-
- // Select between SSDA_MODE_FULLRATE or SSDA_MODE_HALFRATE (62.5kHz or 31.25kHz)
- // and the output modes SSDA_MODE_MONO_BRIDGE, SSDA_MODE_MONO or SSDA_MODE_STEREO
- if (!SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_MONO)) {
- Serial.println(F("initialization failed. Things to check:"));
- Serial.println(F("* is a card is inserted?"));
- Serial.println(F("* Is your wiring correct?"));
- Serial.println(F("* maybe you need to change the chipSelect pin to match your shield or module?"));
- Serial.print(F("Error code: "));
- Serial.println(SdPlay.getLastError());
- while(1);
- } else
- {
- Serial.println(F("Wiring is correct and a card is present."));
- }
- }
- void loop(void) {
- uint8_t count=0,flag=0;//unsigned int,c will transfered one by one
- char d[9]={'B','E','T','H','.','A','F','M'};////////////////////////////1
- char e[13]={'M','A','D','W','O','R','L','D','.','A','F','M','\0'};/////2
- char f[13]={'B','L','U','E','B','I','~','1','.','A','F','M','\0'};/////////3
- char a[13]="";
- char g[13]={'M','E','M','O','R','I','E','S','.','A','F','M','\0'};///////4
-
- //Add here;
- Serial.println(F("Files on card:"));
- SdPlay.dir(&DirCallback);
- //ReEnter:
- Serial.println(F("\r\nEnter filename (send newline after input):"));
- while(1)
- {/////////////small loop in big loop;
- count=0;
- if(flag==2){for(int i=0;i<13;i++){ AudioFileName[count++]=e[i];}count=0;}
- if(flag==3){for(int i=0;i<13;i++){ AudioFileName[count++]=f[i];}count=0;}
- if(flag==4){for(int i=0;i<9;i++){ AudioFileName[count++]=d[i];}count=0;}
- if(flag==5){for(int i=0;i<13;i++){ AudioFileName[count++]=g[i];}count=0;}
- //Add here;
- Serial.print(F("Looking for file... "));
- if(!SdPlay.setFile(AudioFileName)) //judging file name according to filename
- {
- Serial.println(F(" not found on card! Error code: "));
- Serial.println(SdPlay.getLastError());
- //goto ReEnter;
- }
- else {
- Serial.println(F("found."));
- }
-
- Serial.println(F("Press s for stop, p for play, h for pause, f to select new file, d for deinit, v to view status."));
- flag = 1;
- while(flag==1) {
- SdPlay.worker();
- if (irrecv.decode(&results)) {
- switch(results.value) {
- case 0xFF30CF:
- count=0;
- for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
- count=0;
- flag=2;/////////1
- break;
- case 0xFF18E7:
- count=0;
- for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
- count=0;
- flag=3;
- break;///////////2
- case 0xFF7A85:
- count=0;
- for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
- count=0;
- flag=4;
- break;///////////3
- case 0xFF10EF:
- count=0;
- for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
- count=0;
- flag=5;
- break;///////////4
-
- //Add here;
- case 0xFFE21D:
- SdPlay.stop();
- Serial.println(F("Stopped."));
- break;
- case 0xFF22DD:
- SdPlay.play();
- Serial.println(F("Play."));
- break;
- case 0xFFE01F:
- SdPlay.pause();
- Serial.println(F("Pause."));
- break;
- case 0xFFA25D:
- SdPlay.deInit();
- Serial.println(F("SdPlay deinitialized. You can now safely remove card. System halted."));
- while(1) ;
- break;
- case 0xFFB04F:
- flag = 0;
- count=0;
- for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
- count=0;
- break;
- case 0xFF629D:
- Serial.print(F("Status: isStopped="));
- Serial.print(SdPlay.isStopped());
- Serial.print(F(", isPlaying="));
- Serial.print(SdPlay.isPlaying());
- Serial.print(F(", isPaused="));
- Serial.print(SdPlay.isPaused());
- Serial.print(F(", isUnderrunOccured="));
- Serial.print(SdPlay.isUnderrunOccured());
- Serial.print(F(", getLastError="));
- Serial.println(SdPlay.getLastError());
- Serial.print(F("Free RAM: "));
- Serial.println(freeRam());
- break;
- }
- irrecv.resume();
- }
- }
- }
- }
复制代码
该程序中有三处打头为//Add here,那三个地方是要增加歌曲或者修改歌曲名称时用到的,对应上面几行复制再改参数就行。
添加歌曲名时注意,AudioFileName的歌曲名都被自动改为大写字母、无空格、不超过12个字符(除去.afm,只有8个)的字符串,而且,不支持字符“’”,会产生错误。由于害怕里面很多库函数对AudioFileName长度有限制,就没有改长它,短了又不知道是什么歌曲,所以就没管它。SD卡中存储的afm文件显示到串口调试器里的名字才是我们需要的。
下载到板子上之后连上电池拔掉USB,然后按1,2,3等数字键选择歌曲,然后按播放键(键码不用多说了哈)就有开始播放了,
其他功能键可以自己设置,我设置的功能键在连USB时按下板子上TX灯会闪,串口调试器上也会出单词,什么功能一目了然。
有必要的朋友可以再加一个液晶显示模块显示歌名状态等。这个作品的缺点是,AFM格式文件制作有点麻烦,还比较大,然后歌曲多了的话几个数字键不够用(再进一步修改程序使其能接收两三位数字来选择歌曲即可)。 |