【求助】PWM转DA输出WAV音频的一个小程序

2020-01-12 17:25发布

本帖最后由 wicy001 于 2012-4-28 13:45 编辑

利用STC90C516RD+实现PWM输出WAV格式的音频,这是一个非常简单的程序

说明:1.此单片机没有集成PWM,需要使用定时器实现
         2.播放wav音频的格式为8bit,8Khz 单声道,大小<60K,放在程序存储器中。
         3.晶振需要 8Khz*(2^8bit)*12T=24.576Mhz,如果烧写使用6T方式,晶振可减半。
         4.端口接耳机,耳机另一端接+5V,这样声音听着会大一些。

问题:
       输出有噪音,噪音非常尖锐,而且声音很大,比声音信号要大。请各位大侠看看,问题出在哪,应该怎么解决?

-----------
声音尖锐,频率应该很高,试着加一个RC低通,但效果不明显。

---------------为方便大家快速阅读,将帖子相关内容整理如下-------------
图1:RC电路


图2:经过RC电路仿真波形      【如何去掉图中的尖刺?】


图3:未经RC电路前端口的仿真波形  【斜坡受RC影响,正常。如果不加RC电路,输出是平的】



/*************************程序****************************/
#include <reg52.h>   //MCU为STC89/STC90
#include "sound.h"    //wav格式数据

sbit BEEP = P0^0;         //耳机一端接在P0.0脚上,一端接+5V
unsigned int counter,wavedataL;
unsigned char currentdata,nextdata,i;




void sys_start()
{

    TMOD|= 0x02;  //T0,自动重装模式
        TH0 = currentdata;
        TL0 = currentdata;


    ET0 = 1;
        EA  = 1;       

        TR0 = 1;
        BEEP=0;
}



main()
{
  unsigned int tmp;

  tmp=sound[0x29];                           //从wav文件中取,数据长度。数据长度应该是4个字节,
  tmp=tmp<<8;
  wavedataL=tmp+sound[0x28];  //由于wav存在片内flash中,文件大小有限制,数据长度用int型足够表示了。

  counter=0x2c;          //wav文件第一个数据
  
  currentdata=sound[counter];       
  nextdata=sound[counter];

  //以上数字请参考wav格式说明

  sys_start();


  while(1)
  {
   
        if(counter>wavedataL)                //反复重播
                 {
                         counter=0x2c;      
                 }

        if(BEEP) TH0=0xFF-currentdata;
        else TH0=currentdata;

   }


}

/*************************************/

void Timer0int(void) interrupt 1    //定时器0中断
{
   
       
        BEEP=~BEEP;

        if(BEEP)
        {

                counter++;
                nextdata=sound[counter];

        }
        else
        currentdata=nextdata;
}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
99条回答
wicy001
1楼-- · 2020-01-22 19:17
国防大学 发表于 2013-3-21 08:39
真是太谢谢楼主了!看了楼主的程序恍然大悟,以后还要像楼主多学习,昨天仔细研究了楼主的程序,然后自己 ...

很高兴,能够帮到你。
xwkm
2楼-- · 2020-01-22 20:08
wicy001 发表于 2012-5-2 09:23
嗯。STC90/89不支持1T,最大支持6T,我可以试一下。

播放8KHz的wav,按理说接着8Khz输出是可以的。 ...

8K的WAVE文件是指采样率8K。而不是载波频率8K.对于这种东西载波频率得弄到人耳听不到的频率,比如说8K至少得32k的PWM.44K至少得100k的PWM。
lr120363092
3楼-- · 2020-01-23 01:42
 精彩回答 2  元偷偷看……
xwkm
4楼-- · 2020-01-23 06:36
lr120363092 发表于 2013-4-28 16:57
播放8KHZ的WAV,如果PWM超过了8Khz,那播放出来的 声音不是被加快播放了??就是说话变快了 ...

PWM只是载波而已。
8kHz的WAVE指的是对占空比,或者说有效功率的改变量是8K次。对载波频率没有要求。对于8K的WAVE的话,20K的PWM载波是起步价(注意某些人,比如我能听到23k左右的声音,那种尖锐的令人头疼的声音,在这个PWM输出的下面要接个RC滤波。中心频点在4K左右就可以了)。
如果你要播放 CD音质的WAVE的话。对不起,PWM载波频率至少要100k。这个就别软件模拟了。老实用硬件PWM吧。
wicy001
5楼-- · 2020-01-23 07:46
lr120363092 发表于 2013-4-28 16:57
播放8KHZ的WAV,如果PWM超过了8Khz,那播放出来的 声音不是被加快播放了??就是说话变快了 ...

8Khz的wav,如果PWM也是8K,那就是每个PWM的周期播放一个WAV数据,播放出来的WAV就是8Khz,正常语速

如果PWM是16K,WAV数据需要要PWM连续播放2次,再播放下一数据,这样播放出来WAV也是8Khz,正常语速,如果一个PWM周期仍播放一个WAV,语速就会快一倍。


人耳听得的范围在20K以内,所以PWM频率超过20K,基本上就听不到杂音(主要指PWM自身的杂音),效果还是可以的。如果对音效要求高,则可以提高PWM频率。

gamethink
6楼-- · 2020-01-23 10:40
请教LZ,WAV记录的音频数据是有分正/负的,比如8位,究竟如何和PWM的0-255关联起来?

一周热门 更多>