#课程设计之基于单片机的音乐喷泉设计
本设计就需要讲将音乐中提取到的元素,例
如音乐的快慢、调式、音高、节奏、旋律的方向和强度,并且对音乐的情感模式进行识别,然后将识别到的音乐情感模式与相同情感的LED灯和水型相匹配,使它们表达出的情感一致。水型反映音乐的速度,音乐力度反映灯光变化的速度和水的高度,音区、音调、旋律、和声等控制水型与灯光。通过配置好水型、灯光情感等数据库参数,然后将完整的音乐喷泉信息储存到数据库,发送到水泵控制。在这个过程中,根据功能和电路特点,该系统主要分为四个模块:(1)音乐播放模块:考虑到现在音源越来越先进,音频设备越来越丰富,所以本系统设置音频输入端子,由外部提供音频输入。比如说,mp3、手机、电脑等设备。(2)信号采集模块:对输入的音频信号进行预处理,方便单片机进行数据采集,主要有:放大、滤波。(3)数字信号处理模块:进行A/D转换获得数字信号,送入单片机数字信号处理程序,并根据信号强度来确定LED灯的闪烁方式,以及水泵的转速。(4)驱动模块,为LED灯和水泵提供驱动。
随着人们生活水平的日渐提高,音乐喷泉以它独到的魅力成为人们日常休闲娱乐中一个重要的物品。小型的音乐喷泉非常适合日常生活和家庭应用,具有一 定的实际和应用价值。音乐喷泉的水流速度和水流方式,根据音乐种类不同展现出 美轮美奂的画面,音乐喷泉的发明给大家的生活带来了许多不同的乐趣。
根据当前音乐喷泉的发展状况,制作了一个以 ATmega16单片机为主的微型 音乐喷泉控制系统。首先制作一个简单明了的单片机控制电路,把音乐之中检测 到的元素,如音乐的节奏、音律、快慢、旋律的乐感和强度,对音乐表达的情感 进行辨别,最后把识别出的音乐模式与同样节奏感情的 LED 灯和水流速度样式 进行匹配结合,让它们表达出一致的情感。
音乐喷泉系统拥有的四个模块:即音乐播放模块、信号采集模块、数字信号处理模块、驱动模块。该系统设置音频输入端子并从外部提供音频输入,对输入 的音频信号进行预处理,方便单片机进行数据采集。然后进行 A/D转换,得出数字信号,再发送到单片机的数字信号处理程序,据信号的强度确定来LED灯的水泵的转速闪烁方式,为 LED 灯和潜水泵提供驱动器。
#include<iom16v.h>
#include<macros.h>
#include"ADC12.h"
#include"12864drive.h"
#define uint unsigned int
#define uchar unsigned char
#define LED1_1 PORTC|=(1<<PD0) //LED灯给高电平
#define LED2_1 PORTC|=(1<<PD1)
#define LED3_1 PORTC|=(1<<PD2)
#define LED4_1 PORTC|=(1<<PD3)
#define LED5_1 PORTC|=(1<<PD4)
#define LED6_1 PORTC|=(1<<PD5)
#define LED7_1 PORTC|=(1<<PD6)
#define LED8_1 PORTC|=(1<<PD7)
/*************定义需要显示的数组*********/
/*************定义需要显示的数组*********/
uchar line0[]="音乐喷泉控制系统";
uchar line1[]=" ";
uchar line2[]=" ";
uchar line3[]=" ";
uchar line1_data[]="信号采集:";
//****************************************************
//直流减速电机pwm调速
//****************************************************
void pwm(uint a,uint b)
{
OCR1A=a;
OCR1B=b;
}
void t0_pwm(uchar du)
{
OCR0=du;
}
/********端口设置函数********/
long int b=0,z=0;
void port_init(void)
{
PORTB=0XFF;//PB为高电平
DDRB=0XFF;
DDRC=0XFF;//PC为高电平
PORTC=0XFF;
DDRA=0XFF;
PORTA=0X04;//PA2为高电平,其余输出低电平
DDRD=0X0F;
PORTD=0XFF;//PD输入带上拉的输入
}
/********延时函数********/
void delay(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<1141;j++);
}
}
void qidong(void) //12864屏幕显示启动
{
LCD_write_str(0,0,line0);
LCD_write_str(0,1,line1);
LCD_write_str(0,2,line2);
LCD_write_str(0,3,line3);
Delay_ms(3000);
lcd_clr();
}
//****************************************************
//T1初始化
//****************************************************
void t1_init(void)
{
DDRD|=BIT(4);//|BIT(5)
TCCR1A=0XA2;//1010 0010
TCCR1B=0X19;//0001 1001
ICR1=300;
}
/******************运用mega16内部AD转换**********************/
uint mega16_ad()
{
uint addata;
DDRA&=~BIT(PA1);//PA1为输入状态
PORTA&=~BIT(PA1);//PA1为高阻态输入
ADMUX=0XC1;//AVCC为基准电,AD1为输入通道 01000001
ADCSR=0X80;//10000000
ADCSR|=BIT(ADSC); //开始转换
while(!(ADCSR&(BIT(ADIF))));//等待ADIF为1,开始转换
addata=ADCL; //将ADC1的值强制转为十进制赋给无符号整形
addata=addata+ADCH*256; //将寄存器高位ADCH的值读取,将这16位寄存器值全赋给addata
return addata; //返回addata
}
/********主函数 (屏幕初始化)********/
void main(void)
{
uint ada,i,q,add;
uchar ad[5]={'0'},b[3]={'0'},c[3]={'0'};//定义音乐符号数组
AD_Init();
port_init(); //系统初始化,设置IO口属性
t1_init();
lcd_init(); //初始化LCD
qidong();
lcd_clr(); //清屏
delay(10);
while(1)
{
for(i=0;i<4;i++)
{
ada=mega16_ad(); //将addata的值赋给ada
ada=ada*6;
add=add+ada;//add的值读取
}
add=add/4; //进行电压范围的转换
ad[0]=add/1000+0x30; //个位
ad[1]=add/100%10+0x30; //十分位
ad[2]=add/10%10+0x30; //百分位
ad[3]=add%10+0x30;//千分位
q=add/3+50; //将add的值赋给电机
b[0]=0x0e;
c[0]=0x20;c[1]=0x0d; //16*8半宽字型
LCD_write_str(6,1,ad); //12864屏显信号采集量
pwm(q,q);delay(1); //PWM调速,延迟
LCD_write_str(0,0,line0); //12864屏显汉字
if(add>100){LCD_write_str(0,3,b);LED1_1;} //LED灯亮,水泵正转
if(add>150)LCD_write_str(0,2,c);
if(add>200){LCD_write_str(1,3,b);LED2_1;}
if(add>250)LCD_write_str(1,2,c);
if(add>300){LCD_write_str(2,3,b);LED3_1;}
if(add>350)LCD_write_str(2,2,c);
if(add>400){LCD_write_str(3,3,b);LED4_1;}
if(add>450)LCD_write_str(3,2,c);
if(add>500){LCD_write_str(4,3,b);LED5_1;}
if(add>550)LCD_write_str(4,2,c);
if(add>600){LCD_write_str(5,3,b);LED6_1;}
if(add>650)LCD_write_str(5,2,c);
if(add>700){LCD_write_str(6,3,b);LED7_1;}
if(add>750)LCD_write_str(6,2,c);
if(add>800){LCD_write_str(7,3,b);LED8_1;}
if(add>850)LCD_write_str(7,2,c);delay(50);
LCD_write_str(0,1,line1_data);
LCD_write_str(0,3," ");//显示位置
LCD_write_str(0,2," ");//显示位置
add=0;
PORTC=0X00; //PC输出低电平,灯灭
}
}