zoukankan      html  css  js  c++  java
  • 【STM32 .Net MF开发板学习12】跳动的音符(PWM合成)

    PWM除了可驱动电机外,还可以设置不同频率以模拟不同音阶的音符输出,实际测试发现,声音还是蛮动听的,不过常见的有源蜂鸣器可不行(红牛开发板自带),需要专门采购无源蜂鸣器,这二者的区别是有源蜂鸣器通电就响,而无源蜂鸣器需要输入一定频率的信号才能发声。

    我们采用Timer3作为PWM的输出源,我们计数固定为为36,占空比也固定为1/2,通过分频系数来设定相对应的PWM输出频率。

    底层代码如下,由于官方无PWM驱动模板,如下函数由我自行定义。

     //采用Timer3 36M PB0输出

     CPU_TIMER_Initialize(timer,36,PSC,Music_ISR,(void *)timer);

     CPU_TIMER_SetCCR(timer,2,param0==0 ? 0:18);

     UINT32 m_Count= param0*param1/1000;

     CPU_TIMER_SetCCM(timer,2,6); //PWM1模式

     CPU_TIMER_PWM_Start(timer,2);

     CPU_TIMER_Start(timer);

    音符频率对应表如下,根据这个,我们通过PWM就可以输出不同音阶的音符:

    音符

    频率/HZ

    半周期/us

    音符

    频率/HZ

    半周期/us

    音符

    频率/HZ

    半周期/us

    1

    262

    1908

    1

    523

    0956

    1

    1046

    0478

    1#

    277

    1805

    1#

    554

    0903

    1#

    1109

    0451

    2

    294

    1700

    2

    578

    0842

    2

    1175

    0426

    2#

    311

    1608

    2#

    622

    0804

    2#

    1245

    0402

    3

    330

    1516

    3

    659

    0759

    3

    1318

    0372

    4

    349

    1433

    4

    698

    0716

    4

    1397

    0358

    4#

    370

    1350

    4#

    740

    0676

    4#

    1480

    0338

    5

    392

    1276

    5

    784

    0638

    5

    1568

    0319

    5#

    415

    1205

    5#

    831

    0602

    5#

    1661

    0292

    6

    440

    1136

    6

    880

    0568

    6

    1760

    0284

    6#

    466

    1072

    6#

    932

    0536

    6#

    1865

    0268

    7

    494

    1012

    7

    988

    0506

    7

    1976

    0253

    "#"表示半音,用于上升或下降半个音,乘以二就提升该声音一个八度音阶,减半则降一个八度。

    考虑到IO的驱动能力,所以添加一个NPN三极管作为放大输出(实际测试,效果不太明显,和直接驱动差别不大),原理图如下:

    相关的实际器件有如下几种:

    实际的物理接线图如下:

    (直接连接和三极管放大连接)

    为了便于应用程序访问,我封装了一个Music库,相关声明如下:

    namespace YFSoft.Hardware

    {

        public sealed class Music

        {

            public static ushort DO1;

            public static ushort DO1x;

            public static ushort DO2;

            

            public static ushort SO3;

            public static ushort SO3x;

     

            public static int Play(ushort[] buff);

            public static int Play(uint addr, uint size);

            public static int Sound(ushort freq, ushort duration);

        }

    }

    Play(uint addr, uint size)函数是播放WAV文件用的,不过目前我还没有调试成功,等成功了在进行相关说明。

    我们以实际的例子,来说明Play(ushort[] buff)和Sound的使用,我们编写一个最简单的曲子,就是两只老虎,其简谱如下:

    对应的编码数据如下:

    //两只老虎

        UInt16[] lzlh = new UInt16[]

        {

            Music.DO2,Music.S1_4,

            Music.RE2,Music.S1_4,

            Music.MI2,Music.S1_4,

            Music.DO2,Music.S1_4,

            Music.P,Music.S1_16,

     

            Music.DO2,Music.S1_4,

            Music.RE2,Music.S1_4,

            Music.MI2,Music.S1_4,

            Music.DO2,Music.S1_4,

            Music.P,Music.S1_16,

           

            Music.MI2,Music.S1_4,

            Music.FA2,Music.S1_4,

            Music.SO2,Music.S1_2,

            Music.P,Music.S1_16,

     

            Music.MI2,Music.S1_4,

            Music.FA2,Music.S1_4,

            Music.SO2,Music.S1_2,

            Music.P,Music.S1_16,

     

            Music.SO2,Music.S1_8,

            Music.LA2,Music.S1_8,

            Music.SO2,Music.S1_8,

            Music.FA2,Music.S1_8,

            Music.MI2,Music.S1_4,

            Music.DO2,Music.S1_4,

            Music.P,Music.S1_16,

           

            Music.SO2,Music.S1_8,

            Music.LA2,Music.S1_8,

            Music.SO2,Music.S1_8,

            Music.FA2,Music.S1_8,

            Music.MI2,Music.S1_4,

            Music.DO2,Music.S1_4,

            Music.P,Music.S1_16,

     

            Music.DO2,Music.S1_4,

            Music.SO1,Music.S1_4,

            Music.DO2,Music.S1_2,

            Music.P,Music.S1_16,

     

            Music.DO2,Music.S1_4,

            Music.SO1,Music.S1_4,

            Music.DO2,Music.S1_2,

            Music.P,Music.S1_16,

        };

    数据成对出现,第一个是音符,第二是节拍的长度。

    好了,让我们播放一下,播放代码如下,很简单,就一句。

     Music.Play(lzlh);   //音乐播放

    再来看看Sound函数的使用,参数很简单,第一个是发声频率,第二个是持续时间,示例如下:

            //播放单个音符

            Music.Sound(Music.DO1, 1000);

            Music.Sound(Music.RE1, 1000);

            Music.Sound(Music.MI1, 1000);

            Music.Sound(Music.FA1, 1000);

            Music.Sound(Music.SO1, 1000);

            Music.Sound(Music.LA1, 1000);

         Music.Sound(Music.SI1, 1000);

     OK,有兴趣,并且对谱子有研究的网友,可以多编码一些好听的曲子,记得到时候一定与我们分享一下。

       注:该示例程序,红牛开发板需要部署最新的V0.9.8固件。

        文章相关器件:http://item.taobao.com/auction/item_detail.htm?item_num_id=7135239572

     

    【低价开发板】http://item.taobao.com/item.htm?id=7117999726

    源码下载:http://www.sky-walker.com.cn/yefan/MFV40/SourceCode/SoundTest.rar

    文章参考: .Net Micro Framework 快速入门

    中文讨论组:http://space.cnblogs.com/group/MFSoft/
  • 相关阅读:
    算法训练 P1103
    算法训练 表达式计算
    算法训练 表达式计算
    基础练习 时间转换
    基础练习 字符串对比
    Codeforces 527D Clique Problem
    Codeforces 527C Glass Carving
    Codeforces 527B Error Correct System
    Codeforces 527A Glass Carving
    Topcoder SRM 655 DIV1 250 CountryGroupHard
  • 原文地址:https://www.cnblogs.com/yefanqiu/p/1802929.html
Copyright © 2011-2022 走看看