标题:
小型音乐喷泉程序PWM无输出
[打印本页]
作者:
missmb
时间:
2016-5-16 22:05
标题:
小型音乐喷泉程序PWM无输出
了好多资料都是残缺不全
最近看了这个 毕业论文还不错 有原理图 有程序 拿来试试 可是程序写好 发现 PWM根本没输出
内容大概如下
STC12c5a60s2内部集成有8路10位AD,对经过预处理的音频信号做AD转换,
将得到的数字信号进行FFT(快速傅里叶变换),得到音频信号的频谱的功率谱,
用功率谱中个频率段的值做PWM来控制水泵的转速,以此来达到水柱随音乐的变化而发生同步变化
41.PNG
(502.12 KB, 下载次数: 80)
下载附件
2016-5-16 22:04 上传
42.PNG
(493.81 KB, 下载次数: 90)
下载附件
2016-5-16 22:04 上传
原理图上 音频输入 没用他的MIC 用的音频座 直接输入到P1.0 1.1
1602还没到货 暂时没试效果 不过
PWM没输出 想必 频谱显示也是错乱。
测量 P1.3 1.4 4.2 4.3 电压值都是 5V 插个LED 测量 发现亮度根本不会变化
想用 PWM输出 接个固态调压器 来控制 220潜水泵
求帮忙看看程序 能达到这个效果就好 。
得到音频信号的频谱的功率谱,
用功率谱中个频率段的值做PWM来控制水泵的转速,以此来达到水柱随音乐的变化而发生同步变化
程序附上
/**********************************头文件和 变量定义*******************************************/
#include <STC12C5A60S2.H>
#include <intrins.h>
#include <math.h>
#ifndef _FFT_H_
#define _FFT_H_
#ifndef _ADC_H_
#define _ADC_H_
#define uchar unsigned char
#define uint unsigned int
#define FFT_N 32 //定义 傅里叶变换的点数
#define PI 3.1415926535897932384626433832795028841971 //定义圆周率
sbit en0=P3^0;
sbit en1=P3^1;
sbit en2=P3^2;
sbit en3=P3^3; //1602接口定义
sbit en4=P3^4;
sbit en5=P3^5;
sbit en6=P3^6;
sbit en7=P3^7;
uchar x0,x1,x2,x3,x4,x5,x6,x7;
uchar x,i;
/************************音频采集AD模块程序************************************************/
/*************AD延时函数*******************/
void delay_ad(uint z){
uint x,y;
for(x=z;z>0;z--)
for(y=110;y>0;y--);
}
/**************AD初始化*********************/
void init_ad(){
P1ASF=0x03; //选用P1.0 P1.1 作为AD检测
P1M0=0x03;
P1M1=0X03;
ADC_CONTR=0x80; //打开AD电源设置AD转换速率和通道
ADC_RES=0;
ADC_RESL=0;
delay_ad(10);
}
/**************AD转换*************************/
#ifndef _ADC_H_
#define _ADC_H_
void ad(){
ADC_CONTR=0x08; //打开AD
_nop_();
_nop_();
_nop_();
_nop_();
while(!(ADC_CONTR&0x10));
ADC_CONTR=0x80;
_nop_();
_nop_();
_nop_();
_nop_();
S
[ i].real=(ADC_RES*4+ADC_RESL)*5/1.204;
S[ i].imag=0;
}
/********************************快速傅里叶变换FFT模块*****************/
#ifndef _FFT_H_
#define _FFT_H_
struct compx{float real,imag;}; //定义一个复数结构
struct compx s[FFT_N]; //FFT输入和输出,从S[0]开始存放,根据大小自己定义
float SIN_TAB[FFT_N/4+1]; //定义正弦表的存放空间
/******************************************************************
函数原型 struct compx EE(struct compx b1,struct compx b2)
函数功能 对两个复数进行乘法运算
输入参数 两个已联合体定义的复数 A,B
输出参数 A和B的乘积,以联合体的形式输出
********************************************************************/
struct compx EE(struct compx a,struct compx b){
struct copmx c;
c.real=a.real*b.real-a.imag*b.imag;
c.imag=a.real*b.imag+a.imag*b.real;
return(c);
}
/**********************************************************************
函数功能 创建一个正弦采样表,采样点数与傅里叶变换点数相同
输出参数;*sin_t存放正弦表的数组指针
输出参数 无
**************************************************************************/
void create_sin_tab(float*sin_t){
uint i;
for(i=0;i<=FFT_N/4;i++)
sin_t[ i]=sin(2*PI*i/FFT_N);
}
/***************************************************************************
函数原型 void sin_tab(float pi)
函数功能 采用查表的方法计算一个数的正弦值
输入参数 pi索要计算正弦值弧度值,范围0--2*PI,不满足需要转换
输出参数 输入值pi的正弦值
******************************************************************************/
float sin_tab(float pi){
uint n;
float a;
n=(uint)(pi*FFT_N/2/PI);
if(n>0&&n<FFT_N/4)
a=SIN_TAB[n];
else if(n>FFT_N/4&&n<FFT_N/2){
n=FFT_N/4;
a=SIN_TAB[FFT/4-n];
}
else if(n>FFT_N/2&&n<FFT_N/4){
n=FFT_N/2;
a=SIN_TAB[n];
}
else if(n>=3*FFT_N/4&&n<FFT_N){
n=FFT_N-n;
a=SIN_TAB[n];
}
return a;
}
/***************************************************************************
函数原型 void cos tab(float pi)
函数功能 采用查表的方法计算一个数的余弦值
输出参数 pi所要计算余弦值弧度值 范围0--2*PI 不满足需要转换
输出参数 输入值pi的余弦值
***********************************************************************************/
float cos_tab(float pi){
float a,pi2;
pi2=pi+PI/2;
if(pi2>2*PI)
pi2=2*PI;
a=sin_tab(pi2);
return a;
}
/******************************************************************************
函数原型 void FFT(struct compx*xin,int N)
函数功能 对输入的复数组进行快速的傅里叶变换FFT
输入参数 *xin复数结构体组的首地址指针 struct型
输出参数 无
********************************************************************************/
void FFT(struct compx*xin){
uint f,m,nv2,nml,i,k,l,j=0;
struct compx u,w,t;
nv2=FFT_N/2 //变址运算 吧自然顺序变成倒位序,采用雷德算法
nml=FFT_N-1;
for(i=0;i<nml;i++){
if(i<j){ //如果I<J即进行变址
t=xin[j];
xin[j]=xin[ i];
xin[ i]=t;
}
k=nv2; //求J得下一位倒位序
while(k<=j){ //如果K<=J 表示J的最高位未1
j=j-k; // 把最高位变成0
k=k/2; // K/2比较次高位 以此类推 逐个比较 直到某个位未0
}
j=j+k; //吧0改为1
}
}
{uint le,lei,ip; // FFT运算核,使用蝶形运算完成FFT运算
f=FFT_N;
for(l=1;(f=f/2)!=1;1++) // 计算l的值,即计算蝶形级数
for(m=1;m<=1;m++){ // 控制蝶形结级数 m表示第m级蝶形,l为蝶形级总数
l=log(2)N //
le=2<<(m-1); // le蝶形结距离,即第m级蝶形的蝶形结
lei=le/2; // 同一蝶形结中参加运算的两点的距离
u.real=1.0; // u为蝶形结运算系数,初始值为1
u.imag=0.0; //
w.real=cos_tab(PI/lei); // w为系数商,即当前系数与前一个系数的商
w.imag=-sin_tab(PI/lei); //
for(j=0;j<lei-1;j++){ // 控制计算不同种蝶形结,即计算系数不同的蝶形结
for(i=j;i<=FFT_N-1;i=i+le){ // 控制同一蝶形结运算,即计算系数相同蝶形结
ip=i+lei; // i,ip分别表示参加蝶形运算的两个节点
t=EE(XIN[IP],u); // 蝶形运算,详见公式
} xin[ip].real=xin[ i].real-t.real;
xin[ip].imag=xin[ i].imag-t.imag;
xin[ i].real=xin[ i].real+t.real;
xin[ i].imag=xin[ i].imag+t.imag;
}
u=EE(u,w); // 改变系数,进行下一个蝶形运算
}
}
/***********************PWM脉宽调制模块**************************/
#ifndef _PWM_H_
#define _PWM_H_
/*******************PWM初始化****************************************/
void init_pwm() {
CCON=0x00; //工作寄存器设定
CH=0;
CL=0;
CMOD=0x02; //设置pwm工作模式
CCAPM0=0X42; //设定比较器0和PWM0
PCA_PWM0=0X00;
CCAP0H=0x00; //设定PWM0初始值
CCAP0L=0X00;
CCAPM1=0X42; //设定比较器1和PWM1
PCA_PWM1=0X00;
CCAP1H=0x00; //设定PWM0初始值
CCAP1L=0X00;
CR=1;
}
/********************* PWM0调节 ******************************/
void set_pwm0(uchar a) {
CCAP0H=a;
}
/**************** PWM1调节 *****************************/
void set_pwm1(uchar b) {
CCAP1H=b;
}
/**************************1602显示模块****************************/
#ifndef __1602_H__
#define __1602_H__
sbit rs=P2^6;
sbit en=P2^7;
/****************自定义字符 分别为1横格-8横格 ***********************/
uchar table[8][8]= {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f},
{0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x1f},
{0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x1f},
{0x00,0x00,0x00,0x00,0x1f,0x00,0x1f,0x1f},
{0x00,0x00,0x00,0x1f,0x1f,0x00,0x1f,0x1f},
{0x00,0x00,0x00,0x1f,0x1f,0x00,0x1f,0x1f},
{0x00,0x1f,0x00,0x1f,0x1f,0x00,0x1f,0x1f},
{0x1f,0x1f,0x00,0x1f,0x1f,0x00,0x1f,0x1f},
};
/***************************1602延时函数 *****************************************/
void delay_1602(uchar n) {
uchar x,y;
for(x=n;x>0;x--)
for(y=110;y>0;y--);
}
/*********************** 1602写指令函数 *****************************************/
void writecom_1602(uchar a) {
rs=0;
P0=a;
en=0;
en=1;
delay_1602(5);
}
/*******************************1602写数据函数 *************************************/
void writedat_1602(uchar b) {
rs=1;
P0=b;
en=0;
en=1;
delay_1602(5);
}
/******************************1602初始化函数 ****************************************/
void init_1602() {
writecom_1602(0x38);
writecom_1602(0x0c);
writecom_1602(0x06);
writecom_1602(0x01);
}
/*****************************写入自定义字符函数 ****************************************/
void writeCGRAM_1602() {
uchar n,m;
for(n=0;n<8;n++) {
for(m=0;m<8;m++) {
writecom_1602(0x40+n*8+m);
writedat_1602(table[n][m]);
}
}
}
/*****************************显示自定义字符函数 **************************************/
void display_1602(uchar x,uchar y, uchar dat) {
if(x==1){ //第一行显示
writecom_1602(0x80+y);
writedat_1602(dat);
delay_1602(10);
}
if(x==2) { //第二行显示
writecom_1602(0xc0+y);
writedat_1602(dat);
delay_1602(10);
}
}
/***************************数据显示 ************************************/
void display() {
uchar n; uint a;
for(n=0;n<FFT_N/2;n++) {
a=sqrt(s[n].real*s[n].real);
if(n==0) {
a=a/FFT_N;
x0=a;
set_pwm0(a);
}
else {
a=2*a/FFT_N;
if(n==1){x1=a; set_pwm1(a);}
if(n==2){x2=a;}
if(n==3){x3=a;}
if(n==4){x4=a;}
if(n==5){x5=a;}
if(n==6){x6=a;}
if(n==7){x7=a;}
}
if(a<8) {
display_1602(1,n,0x20);
display_1602(2,n,a);
}
else if(a>16) {
display_1602(1,n,7);
display_1602(2,n,7);
}
else {
display_1602(1,n,a-8);
display_1602(2,n,7);
}
}
}
/*******************定时器初始化 ********************************/
void init_T0() {
TMOD=0x02; //设定定时器0工作模式2
TH0=256-100;
TL0=256-100;
EA=1;
ET0=1;
TR0=1;
}
/**********************中断函数 *********************************/
void time_T0() interrupt 1 {
if(x==20){x=0;en0=1;en1=1;en2=1;en3=1;en4=1;en5=1;en6=1;en7=1;}
if(x<x0){en0=1;} else{en0=0;}
if(x<x1){en1=1;} else{en1=0;}
if(x<x2){en2=1;} else{en2=0;}
if(x<x3){en3=1;} else{en3=0;}
if(x<x4){en4=1;} else{en4=0;}
if(x<x5){en5=1;} else{en5=0;}
if(x<x6){en6=1;} else{en6=0;}
if(x<x7){en7=1;} else{en7=0;}
x++;
}
/******************************主函数 ********************************/
void main() {
x=0;
init_ad();
create_sin_tab(SIN_TAB);
init_1602();
writeCGRAM_1602();
init_pwm();
init_T0();
while(1) {
for(i=0;i<FFT_N;i++) {
ad();
}
FFT_N(s);
display();
}
}
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1