找回密码
 立即注册
查看: 1544|回复: 7

八音盒例程分享——基于stc32g12k128的硬件spwm乐音产生应用实例

[复制链接]
  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    611

    积分

    高级会员

    积分
    611
    发表于 2023-5-12 16:36:22 | 显示全部楼层 |阅读模式
      在调试装置时需要一个稳定的声音源,想到之前买的有不少stcMCU芯片,可以用它来产生几个声音信号。于是写了这个程序。
      八音盒能产生七个不同的乐音,而音乐就是由这些基本乐音组合构成(有点脸红)。所以本例程就是个基于MCU的乐音产生程序。
      用MCU产生一个乐音本身很简单,比如要产生一个110HZ的乐音,只要用MCU生成一个频率为110HZPWM方波,然后输出电路上加个一阶低通滤波器,驱动喇叭就听到声音了。
       但当我们需要产生多个乐音时,就遇到一个问题,不同乐音的频率不同,需要的滤波器的参数就不一样,只用一个滤波器时,频率高的乐音会受到较大的衰减。结果低音很强,高音听不见了。
      当然可以用七个不同的低通滤波器,应对七个频率,用一个cd4051进行选择,mcu输出不同频度时,控制cd4051接通不同的滤波器。不过这样硬件就多了几样。而且无法适应更多的频率。
      常用解决办法是采用一个高频率的载波,然后把需要产生的声音频率信号调制到载波上。这样就节省了滤波器。这就是spwm波。它是一个脉冲宽度按正弦规律变化的PWM波。下面给出一个实现方法。
            stc32g12k128具有硬件pwm功能。只要做好设置,它能自动产生符合设置频率和脉宽的PWM波,不需要占用MCU时间。我们只要合理控制它的脉宽变化,就能得到需要的SPWM波了。所以程序简单稳定。精度也很高。
      我选择系统主频用24MHZ,载波频率为55*512=28160HZ55为参考频率,512为对应该频率时正弦波表的点数。因为人耳可闻声频率上限20KHZ,所以这个频率不会对乐音产生干扰,同时它又能保证每个周期对应一个波点数据。最大限度的保证产生的声音的精度。对其它频率的乐音,载波频率不变,只改变正弦波表的点数。始终保证系统在最大精度上运行。该载波频率对应的周期设置值为:24000000/28161=852=0x0354
             STC官方技术手册上有现成的产生spwm波的例程。就直接套用了,包括pwm设置和pwm中断服务。本例程主要是解决正统波表的生成,管理,使用。乐谱表的建立和使用。乐曲的播放管理。
       对spwm波来讲,每个频率的正弦波都需要一组正统波表数据,建立正统波表时,我使用了软件
              Spwm_calc.exe
       它的界面如图所示。中值采用420,幅值415,调制度0.98,在55HZ时的点数512.其它频率的点数值通过计算获得。产生了七组数据存放在头文件sin_table1.h里,每组数据的第一个数放的是本组数据的个数(也就是使用的点数)。第二个开始才是正弦波表的数据。也就是说。读波表数据要从第二个开始读。这是为了编程序简单方便。
       系统设置了三个数组,一个是正弦波表,放在头文件里。第二个是波表索引数组u16 *sin_table_index[],存放正弦波表的数据的地址,它是乐谱与正弦波表的过渡。第三个是乐谱数组
    u8 music_score[33][3]
        乐谱表中一组数据有三个,第一个是音符名,程序根据它通过索引数组读取对应正弦波表。第二个是音组名。1是最低音,2是低音,3是中音4是高音,5是最高音。这个数据决定从波表中读取数据的数量,数据越少音频越高。比如读512个是最低音的6la),那么读256个就是低音的6la,高了八度。频率高一倍。以此类推。这样七组波表数据可用以播放几十个乐音。第三个是音长(乐音的持续时间)。本例程只设置了三个数值,1是全音,2是半音,4 4分音。仅用来展示一下音长管理的方法。想多加几个音长设置很容易。
        例程中使用了四个中断服务:
             PWMA中断,基本照抄官方例程,用来产生spwm波。不同的是这里输出的正弦波频率不是固定的。所以读波表时不能用固定首地址。而是用了一个变量*p存放正弦波表首地址值,方便切换频率。
      外中断int0控制程序运行,主要是把等待切换为运行。如果不用这个中断。可以让程序开机后就自动循环播放。在中断服务程序中。控制变量CC的值,从而影响主程序里语句
    While(cc);的运行。
      在调试时发现中断服务里改变cc值后,主程序里的while语句没有响应。接上stc-link1d仿真器后观察到,中断发生后cc值确实发生了变化,但while语句不理会,没有如预期的那样跳出死循环。把这个现象放到群里咨询时,有高人指出。这是由于keil编译不合理所致,解决的办法是声名变量CC时加一个限制符volatile。试了一下,果然解决了问题。
      中断T1是避免按键振动产生干扰的延时。这两个都不重要,可以不用。
      中断T0是核心,它控制一个乐音的播放时间,同时设定播放所需要的所有参数。各语句的作用在程序里做了注明。
    void t0_sever() interrupt 1//确定一个音符的输出参数,包括乐音的持续时间,音高数据的地址,数据量,读取参数
    {
    read_music_long(cnt);//读当前音符的播放时间,并设定对应的延时
            pp2=music_score[cnt][1];//读取本音符的音组值,以确定读波表数据时的偏移量
            pp3=pow(2,pp2);//计算本音符数据偏移量,在式中给pp2加整数能成倍提高输出频率
    pp0=*sin_table_index[music_score[cnt][0]-1];///pp2;//读取本音符的数据量
    pp1=(sin_table_index[music_score[cnt][0]-1]+1);//取本音符数据指针初值
            p=pp1;//赋正弦数据指针初值
            cnt++;//准备读下一个数据
            if(cnt>33)//乐谱播放完成,这里的33是根据乐谱数据的参数设定的。如果改变乐谱数据量,这里要做对应变化,用小了不能完整播放,用大了会出错
            {
            cc=0;//播放结束
            ET0=0;//关中断
            PWMA_IER = 0x00; //关中断
                PWMA_ENO = 0x00;//关闭PWM输出

            }
    }
      音长子程序里有三个软件定时程序,是直接使用stc官方的软件延时工具产生的。全音用了一秒,半音0.5秒,四分音用0.25秒。
      乐音播放所需要的控制参数都是在这个中断服务里确定的。PWM中断服务则负责按参数进行输出。
        本例程的主程序很简单,包括系统设置和播放管理两项。直接列出来吧:
    void main(void)
    {
            mcu_initial();//mcu设置程序
            //打开播放程序,播放完成后重新进入等待
        while(1)//这个是重入语句
        {

                    cc=1;//等待状态,由中断int0改变,如果使用cc=0;程序自动重复播放乐曲
                    while(cc);
                    //初始化播放指针并开始播放
                     cnt=0;//把播放计数复位到开始位置
                     ET0=1;
                    TR0 = 1;                                //定时器0开始计时
                   PWMA_IER = 0x01; //使能中断
                   PWMA_ENO |= 0x01; //使能输出
                   PWMA_ENO |= 0x02; //使能输出

                            cc=1;
                          while(cc);//等待播放完成,由T0中断服务程序控制这里的CC值
        }
    }
      为听到产生的声音,我使用了唯创的PWM功率放大模块WT1312,它能把spwm信号变成推动喇叭的正弦信号并直接推动喇叭发声。其电路如图所示:把mcuspwm输出端直接连上功放芯片的PWM输入端就行了。因电流较大。芯片电源单独接了一个4.2/3.7V锂电池。二者不需要共地。功放的输入阻抗是100K,对MCU输出要求很低。它的体积很小,又只用了一个电容,所以我直接用sop23-10/dip10转接板当功放板了。接好的板子如图。MCU部分电路没有特殊要求,使用最小系统板就行,我在实验中用了stc32g12k128的降龙棍系统板。音频播放和测试视频见附件。因为测试电路和这个八音盒程序都没使用晶振,所以会有些误差。效果整体还是很不错的。完整的程序见附件,欢迎大家批评指正。

    功率输出.png
    波表生成.png
    功放.jpg

    spwm_1.zip

    98.54 KB, 下载次数: 62

    放音.mp4

    59.15 MB, 下载次数: 57

    测音.mp4

    60.31 MB, 下载次数: 52

    回复 送花

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-30 09:05
  • 签到天数: 79 天

    [LV.6]常住居民II

    9

    主题

    170

    回帖

    1703

    积分

    版主

    积分
    1703
    发表于 2023-5-12 17:01:49 | 显示全部楼层
    感谢楼主分享!
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    3 天前
  • 签到天数: 95 天

    [LV.6]常住居民II

    70

    主题

    611

    回帖

    1890

    积分

    超级版主

    积分
    1890
    QQ
    发表于 2023-5-12 17:10:36 | 显示全部楼层
    啊呀妈呀,这么厉害,必须跟着学起来
    热线19952583534
    www.STCAI.com
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    7 天前
  • 签到天数: 30 天

    [LV.5]常住居民I

    11

    主题

    185

    回帖

    1814

    积分

    版主

    积分
    1814
    QQ
    发表于 2023-5-12 17:14:18 | 显示全部楼层
    本帖最后由 红心A 于 2023-5-12 17:17 编辑

    佩服!大佬!
    QQ:1638975601
    手机:19952583876
    回复 送花

    使用道具 举报

    该用户从未签到

    46

    主题

    3046

    回帖

    6869

    积分

    超级版主

    积分
    6869
    发表于 2023-5-12 22:02:36 | 显示全部楼层
    赞一个,楼主厉害!
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    611

    积分

    高级会员

    积分
    611
     楼主| 发表于 2023-5-13 14:03:41 | 显示全部楼层
    本帖最后由 丽江春水 于 2023-5-13 14:34 编辑
    梁工 发表于 2023-5-12 22:02
    赞一个,楼主厉害!

    梁工能过目已感荣幸,一直很敬佩您

    点评

    客气了! 用一个八音盒的音色波表,多通道播放叠加,有和弦效果,下面是6通道的效果。20年前做玩具电子琴时,都是8通道DAC合成的,现在的MCU速度快了,软件合成,一个DAC即可(PWM亦可),STC32F跑30MHz以上,32K采  详情 回复 发表于 2023-5-13 15:58
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    46

    主题

    3046

    回帖

    6869

    积分

    超级版主

    积分
    6869
    发表于 2023-5-13 15:58:20 | 显示全部楼层
    丽江春水 发表于 2023-5-13 14:03
    梁工能过目已感荣幸,一直很敬佩您

    客气了!
    用一个八音盒的音色波表,多通道播放叠加,有和弦效果,下面是6通道的效果。20年前做玩具电子琴时,都是8通道DAC合成的,
    现在的MCU速度快了,软件合成,一个DAC即可(PWM亦可),STC32F跑30MHz以上,32K采样可达16通道。




    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    611

    积分

    高级会员

    积分
    611
     楼主| 发表于 2023-5-14 15:17:01 | 显示全部楼层
    梁工 发表于 2023-5-13 15:58
    客气了!
    用一个八音盒的音色波表,多通道播放叠加,有和弦效果,下面是6通道的效果。20年前做玩具电子琴 ...

    受教了。我去试试。谢谢
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-20 15:19 , Processed in 0.088968 second(s), 61 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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