步进电机播放音乐
硬件:使用arduino uno板子与步进电机驱动器TB6600实物图因为我这里用的是方波,才用步进电机振动与地座产生共振来达到播放音乐的效果,所以这里板子接线只需要将13口与驱动器的脉冲口相接,方向使能可以不接,其它可以用共阴或者共阳。
播放音乐,首先得知道do,re,mi,fa,suo,la,xi等这些对应的频率,这里就需要用的示波器,将脉冲线接到示波器,通过调整方波频率来找到这些频率,记下来。
比如charmusic_freq_tab={ //音符定时器值表
0xff,0xea, //0 休止符
255-FREQ/24/131/256, //256-FREQ/24/x/256 //1 do 高字节
256-FREQ/24/131%256, //256-FREQ/24/x%256 //1 do 低字节
255-FREQ/24/147/256,256-FREQ/24/147%256, //2 re
255-FREQ/24/165/256,256-FREQ/24/165%256, //3 mi
255-FREQ/24/175/256,256-FREQ/24/175%256, //4 fa
255-FREQ/24/196/256,256-FREQ/24/196%256, //5 suo
255-FREQ/24/221/256,256-FREQ/24/221%256, //6 la
255-FREQ/24/248/256,256-FREQ/24/248%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/262/256,256-FREQ/24/262%256, //1 do
255-FREQ/24/294/256,256-FREQ/24/294%256, //2 re
255-FREQ/24/330/256,256-FREQ/24/330%256, //3 mi
255-FREQ/24/350/256,256-FREQ/24/350%256, //4 fa
255-FREQ/24/393/256,256-FREQ/24/393%256, //5 suo
255-FREQ/24/441/256,256-FREQ/24/441%256, //6 la
255-FREQ/24/495/256,256-FREQ/24/495%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/525/256,256-FREQ/24/525%256, //1 do
255-FREQ/24/589/256,256-FREQ/24/589%256, //2 re
255-FREQ/24/661/256,256-FREQ/24/661%256, //3 mi
255-FREQ/24/700/256,256-FREQ/24/700%256, //4 fa
255-FREQ/24/786/256,256-FREQ/24/786%256, //5 suo
255-FREQ/24/882/256,256-FREQ/24/882%256, //6 la
255-FREQ/24/990/256,256-FREQ/24/990%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/1049/256,256-FREQ/24/1049%256, //1 do
255-FREQ/24/1178/256,256-FREQ/24/1178%256, //2 re
255-FREQ/24/1322/256,256-FREQ/24/1322%256, //3 mi
255-FREQ/24/1400/256,256-FREQ/24/1400%256, //4 fa
255-FREQ/24/1572/256,256-FREQ/24/1572%256, //5 suo
255-FREQ/24/1665/256,256-FREQ/24/1665%256, //6 la
255-FREQ/24/1869/256,256-FREQ/24/1869%256, //7 xi
};还有很多,这里就不一一叙说了,原理很简单,有示波器就可以了,具体请看我上传的源代码。
有了上述这些东西之后,还需要了解arduino的定时器,我这里用的UNO板,我都板子晶振频率是16M,所以TCNT1=0Xffff - 定时时间/(分频数* (1/晶振频率)),分频数是调整计数的,越大计数越慢,一般有1、8、64、256、1024分频。定时器初始化与中断代码如下:
void DEVICE_INIT(void){
cli();
TCCR1A=0;
TCCR1B=(1<<CS12)|(1<<CS10);
TCNT1=344;
TIMSK1=(1<<TOIE1);
DDRB|=(1<<DDB5);
PORTB|=(0<<PORTB5);
sei();
}
ISR(TIMER1_OVF_vect)
{
TCNT1=65535-((ly_TH0*256+ly_TL0)/1000000)/(1024*(1/16000000));
PORTB=(~PORTB)&(1<<PORTB5);
}
上述东西大家都解决后,就可以播放音乐了,播放音乐的代码如下:(大家也可以根据自己喜欢的调子来改编)
void music_play( char *pmsc) //音乐
{
char music_freq=32; //音高
char music_long; //节拍延时
char music_data=0; //音符数据
char music_up=0; //升半音
char music_break=0; //断奏
ly_TH0=0xff;
ly_TL0=0xea;
sei();
while (*pmsc != 0x00)
{
music_data=*pmsc & 0x07;
music_long=*pmsc>>4;
//---------------------------------------------------------
if (music_long != 0){ //是音符,非功能码
if (*pmsc&0x80){ //需升降调
if (((*pmsc) & 0x08) == 0)
{if(music_freq >= 16) music_freq -= 16;} //音高下降
else
{if(music_freq < 48) music_freq += 16;} //音高上升
}
//---------------------------------------------------------
if (music_up==1){ //升半音
ly_TH0=music_frequp_tab[(music_freq+ (music_data <<1))];
ly_TL0=music_frequp_tab[(music_freq + (music_data <<1)+1)];
}
else{ //不升半音
ly_TH0=music_freq_tab[(music_freq + (music_data <<1))];
ly_TL0=music_freq_tab[(music_freq + (music_data <<1)+ 1)];
}
if (music_break){ //断奏
music_delay(music_l_tab-1);
ly_TH0=0xff;
ly_TL0=0xea;
music_delay(1);
}
else //连奏
music_delay(music_l_tab);
}
else //是功能码
{
switch(music_data){
case 0x04:
music_up=0; break; //不升半音
case 0x05:
music_up=1; break; //升半音
case 0x06:
music_break=0; break; //断奏
case 0x07:
music_break=1;break; //连奏
}
}
pmsc++;
}
cli(); //播放结束,关中断
}
播放效果视频如下:
https://v.youku.com/v_show/id_XNDExNDU3MTE1Mg==.html?spm=a2hzp.8244740.0.0
全部代码如下:
#include <interrupt.h>
#include <iom328p.h>
#defineFREQ 16000000
char music1[]={
0xcb, //示例:0xcb=11001011B,升半调/1/4拍,3Mi低音
0x35,0x16,0xb9,0x12,0x96,0x99,0xa5,
0xbd,0x99,0x96,0x15,0x13,0x15,0x62,
0x32,0x13,0xa7,0x26,0x25,0x16,0xa9,0x22,
0xa3,0xa9,0x96,0x15,0x16,0x99,0xe5,
0xbb,0x15,0xa7,0xaa,0x96,0x99,0xd5,
0x13,0x15,0x23,0x15,0x16,0x17,0x9a,0xd6,0x15,0x16,
0xb9,0x12,0x25,0x23,0x23,0x22,0x13,0x12,0x21,0x96,0x15,
0x43,0xc9,0x96,0x99,0x96,0x15,0x13,0x15,0x16,0x99,
0xd5,
0x00, //最后字节为功能码必须==0x00退出
};
char music_l_tab={0,1,2,3,4,6,8,16};//音乐节拍
charmusic_freq_tab={ //音符定时器值表
0xff,0xea, //0 休止符
255-FREQ/24/131/256, //256-FREQ/24/x/256 //1 do 高字节
256-FREQ/24/131%256, //256-FREQ/24/x%256 //1 do 低字节
255-FREQ/24/147/256,256-FREQ/24/147%256, //2 re
255-FREQ/24/165/256,256-FREQ/24/165%256, //3 mi
255-FREQ/24/175/256,256-FREQ/24/175%256, //4 fa
255-FREQ/24/196/256,256-FREQ/24/196%256, //5 suo
255-FREQ/24/221/256,256-FREQ/24/221%256, //6 la
255-FREQ/24/248/256,256-FREQ/24/248%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/262/256,256-FREQ/24/262%256, //1 do
255-FREQ/24/294/256,256-FREQ/24/294%256, //2 re
255-FREQ/24/330/256,256-FREQ/24/330%256, //3 mi
255-FREQ/24/350/256,256-FREQ/24/350%256, //4 fa
255-FREQ/24/393/256,256-FREQ/24/393%256, //5 suo
255-FREQ/24/441/256,256-FREQ/24/441%256, //6 la
255-FREQ/24/495/256,256-FREQ/24/495%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/525/256,256-FREQ/24/525%256, //1 do
255-FREQ/24/589/256,256-FREQ/24/589%256, //2 re
255-FREQ/24/661/256,256-FREQ/24/661%256, //3 mi
255-FREQ/24/700/256,256-FREQ/24/700%256, //4 fa
255-FREQ/24/786/256,256-FREQ/24/786%256, //5 suo
255-FREQ/24/882/256,256-FREQ/24/882%256, //6 la
255-FREQ/24/990/256,256-FREQ/24/990%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/1049/256,256-FREQ/24/1049%256, //1 do
255-FREQ/24/1178/256,256-FREQ/24/1178%256, //2 re
255-FREQ/24/1322/256,256-FREQ/24/1322%256, //3 mi
255-FREQ/24/1400/256,256-FREQ/24/1400%256, //4 fa
255-FREQ/24/1572/256,256-FREQ/24/1572%256, //5 suo
255-FREQ/24/1665/256,256-FREQ/24/1665%256, //6 la
255-FREQ/24/1869/256,256-FREQ/24/1869%256, //7 xi
};
charmusic_frequp_tab={ //升半音
0xff,0xea, //0 休止符
255-FREQ/24/139/256, //1 do 高字节 //255-FREQ/24/x/256
256-FREQ/24/139%256, //1 do 低字节 //256-FREQ/24/x%256
255-FREQ/24/156/256,256-FREQ/24/156%256, //2 re
255-FREQ/24/175/256,256-FREQ/24/175%256, //3 mi
255-FREQ/24/185/256,256-FREQ/24/185%256, //4 fa
255-FREQ/24/208/256,256-FREQ/24/208%256, //5 suo
255-FREQ/24/234/256,256-FREQ/24/234%256, //6 la
255-FREQ/24/262/256,256-FREQ/24/262%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/278/256,256-FREQ/24/278%256, //1 do
255-FREQ/24/312/256,256-FREQ/24/312%256, //2 re
255-FREQ/24/350/256,256-FREQ/24/350%256, //3 mi
255-FREQ/24/371/256,256-FREQ/24/371%256, //4 fa
255-FREQ/24/416/256,256-FREQ/24/416%256, //5 suo
255-FREQ/24/467/256,256-FREQ/24/467%256, //6 la
255-FREQ/24/525/256,256-FREQ/24/525%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/556/256,256-FREQ/24/556%256, //1 do
255-FREQ/24/624/256,256-FREQ/24/624%256, //2 re
255-FREQ/24/700/256,256-FREQ/24/700%256, //3 mi
255-FREQ/24/742/256,256-FREQ/24/742%256, //4 fa
255-FREQ/24/833/256,256-FREQ/24/833%256, //5 suo
255-FREQ/24/935/256,256-FREQ/24/935%256, //6 la
255-FREQ/24/1049/256,256-FREQ/24/1049%256, //7 xi
0xff,0xea, //0 休止符
255-FREQ/24/1112/256,256-FREQ/24/1112%256, //1 do
255-FREQ/24/1248/256,256-FREQ/24/1248%256, //2 re
255-FREQ/24/1400/256,256-FREQ/24/1400%256, //3 mi
255-FREQ/24/1484/256,256-FREQ/24/1484%256, //4 fa
255-FREQ/24/1618/256,256-FREQ/24/1618%256, //5 suo
255-FREQ/24/1764/256,256-FREQ/24/1764%256, //6 la
255-FREQ/24/1968/256,256-FREQ/24/1968%256, //7 xi
};
char ly_TH0;
char ly_TL0;
void music_delay(unsigned char timer) //延时 125*n 毫秒
{
unsigned char i=125,j;
do{
do{
for(j=0; j<230; j++)
;
}while(--i);
}while(--timer);
}
//---------------------------------------------------------------------------//
void music_play( char *pmsc) //音乐
{
char music_freq=32; //音高
char music_long; //节拍延时
char music_data=0; //音符数据
char music_up=0; //升半音
char music_break=0; //断奏
ly_TH0=0xff;
ly_TL0=0xea;
sei();
//---------------------------------------------------------
while (*pmsc != 0x00)
{
music_data=*pmsc & 0x07;
music_long=*pmsc>>4;
//---------------------------------------------------------
if (music_long != 0){ //是音符,非功能码
if (*pmsc&0x80){ //需升降调
if (((*pmsc) & 0x08) == 0)
{if(music_freq >= 16) music_freq -= 16;} //音高下降
else
{if(music_freq < 48) music_freq += 16;} //音高上升
}
//---------------------------------------------------------
if (music_up==1){ //升半音
ly_TH0=music_frequp_tab[(music_freq+ (music_data <<1))];
ly_TL0=music_frequp_tab[(music_freq + (music_data <<1)+1)];
}
else{ //不升半音
ly_TH0=music_freq_tab[(music_freq + (music_data <<1))];
ly_TL0=music_freq_tab[(music_freq + (music_data <<1)+ 1)];
}
//---------------------------------------------------------
if (music_break){ //断奏
music_delay(music_l_tab-1);
ly_TH0=0xff;
ly_TL0=0xea;
music_delay(1);
}
else //连奏
music_delay(music_l_tab);
}
//---------------------------------------------------------
else //是功能码
{
switch(music_data){
case 0x04:
music_up=0; break; //不升半音
case 0x05:
music_up=1; break; //升半音
case 0x06:
music_break=0; break; //断奏
case 0x07:
music_break=1;break; //连奏
}
}
//---------------------------------------------------------
pmsc++;
}
cli(); //播放结束,关中断
}
void DEVICE_INIT(void){
cli();
TCCR1A=0;
TCCR1B=(1<<CS12)|(1<<CS10);
TCNT1=344;
TIMSK1=(1<<TOIE1);
DDRB|=(1<<DDB5);
PORTB|=(0<<PORTB5);
sei();
}
ISR(TIMER1_OVF_vect)
{
TCNT1=65535-((ly_TH0*256+ly_TL0)/1000000)/(1024*(1/16000000));
PORTB=(~PORTB)&(1<<PORTB5);
}
void setup()
{
DEVICE_INIT();
while(1)
music_play(music1); //播放音乐
}
void loop(){
}
链接:https://pan.baidu.com/s/1OEe7TSm58zX87jilmajOIw
提取码:jqxh
链接失效了,能麻烦再发一次吗 好听,好厉害,顶 #include <interrupt.h>
#include <i o m 3 2 8 p.h>
这两个库函数能发一下么 wangyirun 发表于 2019-7-6 13:27
好听,好厉害,顶
感谢支持 这是神人。:handshake
页:
[1]