找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4627|回复: 0
收起左侧

小型音乐喷泉程序PWM无输出

[复制链接]
ID:102175 发表于 2016-5-16 22:05 | 显示全部楼层 |阅读模式
了好多资料都是残缺不全  
最近看了这个 毕业论文还不错   有原理图 有程序  拿来试试   可是程序写好  发现 PWM根本没输出

内容大概如下
STC12c5a60s2内部集成有8路10位AD,对经过预处理的音频信号做AD转换,
将得到的数字信号进行FFT(快速傅里叶变换),得到音频信号的频谱的功率谱,
用功率谱中个频率段的值做PWM来控制水泵的转速,以此来达到水柱随音乐的变化而发生同步变化


41.PNG    
42.PNG
原理图上     音频输入 没用他的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();  
                   }
}







评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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