打印
[活动专区]

【AT-START-F407测评】+应用设计【玩具电子琴的故事】

[复制链接]
922|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gddddd|  楼主 | 2021-2-26 19:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 gddddd 于 2021-2-27 00:27 编辑

    首先还是要感谢雅特力公司!感谢21IC电子论坛!赠送的AT-START-F407开发板
十分强大,值得好好琢磨。
    这次要说的是一个【玩具电子琴的故事】,还是好久好久之前了,帮朋友做了
一个玩具电子琴的设计,很简单的电路,成品的绑定芯片,8个按键1个拨动开关1个
喇叭加上外衣就是全部了,音质嘛就是五毛特效的哪种(后面视频有展示到),市
面上还有很多类似的玩具,真的是五毛特效,因为不算外壳开模的话,成本是毛毛
钱,所以效果是真实的五毛 ^_^
    前些时间,朋友又找到问我,这个玩具电子琴,都还小巧好看,就是声音让人
有种让人怀疑人生(好听的音乐是让耳朵**的感觉)的感觉,实在是不敢久听,
虽然是小朋友的玩具,也是对小朋友的耳朵不负责任。感觉说这话的时候他隐藏心
意是怕做这种产品,太对不起大家,怕生个娃娃没小XX。说是想改变设计,让玩具
电子琴的声音也能让耳朵**,我默默的无语,朋友的尿性还是知道的,就问了一
句,成本控制不用考虑吗。。。结果和以前一样说:当然要越便宜越好,好吧我确
实白问了,再看看现在芯片的成本是好好学习,天天向上,好难呀,这个任务怕是
完不成了。
    拿出手中的AT-START-F407开发板,看了看官方的芯片报价,我只能说玩具的世
界也不都是快乐呀,做个设计要抠门到底还怎么快乐,不管了用AT-START-F407开发
板来验证设计还是牛刀小用。当然为了减少芯片成本,很多华丽的实现方法就不能
考虑了,经过多时的考虑,歪果仁的网站上看到这么一个小玩意,使用Attiny45做
的波表旋律发生器,网址在:http://elm-chan.org/works/mxb/report.html 这个
波表合成是简化版的,下面借用两张图说明一下,标准波形分为A(Attatk)、
D(Decay)、S(Sustain)、R(Release),而简化版的只有A(Attatk)、S(Sustain)




    简单说说ADSR,也就是包络,声音从无到有从有到无的过程,都需要经历一个过
渡变化的阶段。只是有的乐器过渡得快,有的乐器慢。ADSR包络最早由 Columbia-Princeton
Electronic Music Center 的 Vladimir Ussachevsky提出,而后由ARP乐器公司完
善(取至知乎的介绍)。声音从无到有的这段时间,叫做上升时间(Attack Time),
而将声音从有到无的时间,叫做释放时间(Release Time)。简单说就是简化版的合
成器保留了A部分,放弃了D部分,循环S部分,没有R部分,后面我都捡自己感觉重点
的说说,不然太水了。这次最终的设计计划64K内完成,需要存上几十首歌曲,所以
使用简单版本的包络也是无奈之举,当然想让耳朵**是完不成的任务呀。
    硬件方面的话,一块芯片必不可少,看官方介绍雅特力AT32F421F8-20PIN应该是
最便宜最具性价比的,考虑就用这个(不得不说X宝也不靠谱了,年前我拍了好些421
的芯片,这都元宵节还没发货,怕是拍的价格便宜不给发货了),功放的话能省则省,
画外音:朋友幽怨的话语淡淡飘来,要用功放也要毛票的,捡五毛。。不三毛以下的。。。
哎,好久没这么动手了,用面包板搭了个8脚功放CS85711(三毛以下)


    音频输出信号经过2级RC滤波进入功放,可能是功放电路中阻容参数不是太对,出
来的声音有底噪。又去X宝了买了PAM8403A小板(这个超标了),还是有底噪,估计
程序上还有虫子没捉完,另外程序中还减小了音量输出,要不然这小喇叭还爆音。。。
都是低价惹的祸,不过值得高兴的是编译出的代码只有16K不到,再加加功能,放几十
首歌曲还是有空间的。


    软件方面的话,先踩一脚STC,试过把代码放STC8G上跑,开最高36M主频在32768Hz
的中断频率下,最关键的需要中断中运行的合成器计算代码居然不够时间跑,我的天
还是1T的宇宙最强51,减半在16384Hz(一次中断约合2197个指令周期)下勉强够跑了,
但效果是声音断断续续的了,难道非要中断用汇编写。。我大写服气,汇编干不来呢,
主要是51在计算非8位数据上太吃亏了。然后为啥非要用中断频率32768Hz呢,因为
合成器中相位累加器是15位,也就是2的15次方32768,而输出音符的频率等于相位
步进乘以中断频率再除以相位累加器,那么当中断频率为32768Hz时,输出音符的频
率就直接等于相位步进了,比如中音A 432Hz(拓展一个知识,据说432Hz比440Hz更
合乎宇宙规律?)相位步进直接就取432了,简单明了。贴一下中断的关键代码:
void TMR2_GLOBAL_IRQHandler(void)
{
  unsigned char i=0;
  signed short vpp[N_SIZE];
  signed short vpp6=0;

        if(TMR_GetINTStatus(TMR2,TMR_INT_Overflow)!= RESET)
        {
                TMR_ClearITPendingBit(TMR2,TMR_INT_Overflow);

                for(i=0;i<N_SIZE;i++)
                {
                        vpp=*Notes.wp;
                        Notes.ac+=(u8)Notes.k&0xff; //k为相位步进
                        Notes.wp+=(Notes.k+Notes.ac)/256; //累计之前的相位误差
               
                        if(Notes.wp>=Notes.maxaddress)
                        {
                                Notes.wp-=128;
                                Notes.wrap=0x0;
                        }
                        vpp6+=((vpp*Notes.lvl)/512); //除以128即可,除以512减小音量降低噪声
                }

                vpp6=vpp6/6; //混合6个通道
                if(vpp6>253) vpp6=253;
                else if(vpp6<(-255)) vpp6=-255;
                OutLVOL=(vpp6/2-128)&0xff;
                TMR3->CC1 = (u32)OutLVOL*300/256;
               
                time1++;
                if (time1==0)
                {
                        time2++;
                        if (time2==0)
                        {
                                time3++;
                        }
                }
        }
}
    再贴一下相位步进表:
/*各个频率对应的相位步进表*/
const unsigned int pitch_table[]= //432Hz改版
{
           0,                                                        // MUTE
          32,  34,  36,  38,  40,  43,  45,  48,  51,  54,  57,  61, //   55Hz
          64,  68,  72,  76,  81,  86,  91,  96, 102, 108, 114, 121, //  110Hz
         128, 136, 144, 153, 162, 171, 182, 192, 204, 216, 229, 242, //  220Hz
         257, 272, 288, 305, 324, 343, 363, 385, 408, 432, 458, 485, //  440Hz
         514, 544, 577, 611, 647, 685, 727, 770, 816, 864, 915, 970, //  880Hz
        1028,1089,1153,1222,1295,1372,1453,1540,1631,1728,1831,1940, // 1760Hz
        2055,2177,2307,2444,2589,2743,2906,3079,3262,3456,3662,3880, // 3520Hz
        4110,4355,4614,4888,5179,5487,5813,6158,6525,6913,7324,7759, // 7040Hz
};

    直观一点,放上两个视频,播放的乐曲是我很喜欢的天空之城(欢快版)
    【雅特力F407开发板-波表旋律发生器1】是使用CS85711搭棚功放的效果:
https://v.youku.com/v_show/id_XNTExMTE1NTg2NA==.html
    【雅特力F407开发板-波表旋律发生器2】是PAM8403A功放小板和原始
玩具琴的对比效果:
https://v.youku.com/v_show/id_XNTExMTE2OTU4NA==.html

    最后再谈谈AT-START-F407开发板的使用感受,AT32F407VGT7无疑是一款强大的MCU,
对比STM32F4系列,有价格上的优势。因其大SRAM大FLASH的设定,应用在物联网方面应
该是一个较好的方向。如果一定要应用在电子琴上,也有一些不足的想法,AT32F407VGT7
外配SPI FLASH存放音色采样波表,根据硬件设计实时反馈进行FFT运算,最后利用芯片内
DAC输出,配合好一点的功放和喇叭,再实现些点灯跟弹功能等等,市面上500元以内的电
子琴主控估计还没有AT32F407VGT7来得强大。

使用特权

评论回复
沙发
v26g7l| | 2021-2-28 23:57 | 只看该作者
谢谢楼主分享!

使用特权

评论回复
板凳
zhengshuai888| | 2021-3-1 07:58 | 只看该作者
谢谢分享

使用特权

评论回复
地板
muyichuan2012| | 2021-3-1 09:28 | 只看该作者
“还是有底噪,估计程序上还有虫子没捉完”,楼主太幽默了,

使用特权

评论回复
5
dujq| | 2021-3-2 18:53 | 只看该作者
做音频,楼主有没有试过杰理或者蓝汛的芯片

使用特权

评论回复
6
lidi911| | 2021-3-3 07:54 | 只看该作者
得搞个琴盘啊

使用特权

评论回复
7
gddddd|  楼主 | 2021-3-3 09:24 | 只看该作者
dujq 发表于 2021-3-2 18:53
做音频,楼主有没有试过杰理或者蓝汛的芯片

之前接触过杰理MP3芯片,时间有点久了型号好像是ac1074或者更LOW一点的,杰理芯片专业针对性很强。蓝汛就没使用过了

使用特权

评论回复
8
gddddd|  楼主 | 2021-3-3 09:30 | 只看该作者
muyichuan2012 发表于 2021-3-1 09:28
“还是有底噪,估计程序上还有虫子没捉完”,楼主太幽默了, ...

是真的没弄完BUG,因为歪果仁的代码是AVR的汇编,这个真不熟,汇编指令还是找的ATTiny的手册一条一条看的,但很多标志位的用法连猜带蒙了,特别是一段专用8位有符号数*无符号数的乘法,真心看得一愣一愣的,计算结果居然是-255到255之间的,所以自己的计算方法和原始的有出入,底噪估计就是这么来的

; T0 = int8(EL) x .uint8(EH), 32clks

.macro MULT
        mov        T0H, EL
        sbrc        EL, 7
        neg        EL

        clr        T0L
        sbrc        EH, 0
        add        T0L, EL
        lsr        T0L
        sbrc        EH, 1
        add        T0L, EL
        lsr        T0L
        sbrc        EH, 2
        add        T0L, EL
        lsr        T0L
        sbrc        EH, 3
        add        T0L, EL
        clr        T0L
        sbrc        EH, 4
        add        T0L, EL
        lsr        T0L
        sbrc        EH, 5
        add        T0L, EL
        lsr        T0L
        sbrc        EH, 6
        add        T0L, EL
        lsr        T0L
        sbrc        EH, 7
        add        T0L, EL

        lsl        T0H
        mov        T0H, _0
        brcc        PC+3
        neg        T0L
        sbc        T0H, T0H
.endm

使用特权

评论回复
9
gddddd|  楼主 | 2021-3-3 10:06 | 只看该作者
; T0 = int8(EL) x .uint8(EH), 32clks //16位有符号数(T0) = 8位有符号数(EL) * 8位无符号数(EH)
                                     //被乘数EL是波形数据,取值范围-127~126,乘数EH是衰减数据,取值范围0~255
                                     //T0由T0H、T0L组成
.macro MULT        //乘法宏开始
        mov        T0H, EL    //EL保存到T0H中
        sbrc        EL, 7  //通过EL.7位判断是否负数,为0是正数则跳过下一条指令
        neg        EL         //是负数,EL=EL取补码

        clr        T0L        //清零T0L,准备累加
        sbrc        EH, 0  //通过EH.0位判断是否是0,是1则跳过下一条指令
        add        T0L, EL    //T0L=T0L+EL
        lsr        T0L        //T0L=T0l>>1 也就是T0L除以2
        sbrc        EH, 1  //
        add        T0L, EL    //
        lsr        T0L        //
        sbrc        EH, 2  //重复上面的运算,但4次之后又清零T0L,这个是什么神操作?
        add        T0L, EL    //但歪果仁这么干肯定有用的,只是我没明白!!!
        lsr        T0L        //
        sbrc        EH, 3  //
        add        T0L, EL    //
        clr        T0L        //清零T0L,哦豁!前面的白算了一遍。。。。
        sbrc        EH, 4  //通过EH.4位判断是否是0,是1则跳过下一条指令
        add        T0L, EL    //T0L=T0L+EL
        lsr        T0L        //T0L=T0l>>1 也就是T0L除以2
        sbrc        EH, 5  //通过EH.5位判断是否是0,是1则跳过下一条指令
        add        T0L, EL    //T0L=T0L+EL
        lsr        T0L        //T0L=T0l>>1 也就是T0L除以2
        sbrc        EH, 6  //通过EH.6位判断是否是0,是1则跳过下一条指令
        add        T0L, EL    //T0L=T0L+EL
        lsr        T0L        //T0L=T0l>>1 也就是T0L除以2
        sbrc        EH, 7  //通过EH.7位判断是否是0,是1则跳过下一条指令
        add        T0L, EL    //T0L=T0L+EL

        lsl        T0H        //T0H=T0H<<1 看看T0H.7是否为1,1是负数符号位,C标志位相应为1
        mov        T0H, _0    //清零T0H,这样正数的结果范围为0~255
        brcc        PC+3   //如果C标志位=0,也就是正数则跳过下面2条指令
        neg        T0L        //T0L=T0L取补码
        sbc        T0H, T0H   //T0H=T0H-T0H-C 也就是0-0-1=0xFF,结果为负数,最终T0的数值范围0xFF01~0xFFFF 对应-1~-255
.endm              //乘法宏结束 这段代码的结果是得到一个-255~255之间的16位有符号数


以上是对原乘法汇编代码的一点理解,望有懂AVR汇编的坛友予以指正

使用特权

评论回复
10
单片小菜| | 2021-3-3 12:49 | 只看该作者
电子城的模块吗?算法是咋算的?

使用特权

评论回复
11
huangcunxiake| | 2021-3-3 13:15 | 只看该作者
音效如何?

使用特权

评论回复
12
里面有晴雨| | 2021-3-3 15:09 | 只看该作者
可以录一段音效吗?我 听一下。

使用特权

评论回复
13
gddddd|  楼主 | 2021-3-3 20:27 | 只看该作者
本帖最后由 gddddd 于 2021-3-3 20:45 编辑

前面帖子中标红的优酷链接有实际效果录音视频,现在代码还有些问题,底噪太大,和核心算法应该有关系

https://v.youku.com/v_show/id_XNTExMTE1NTg2NA==.html
https://v.youku.com/v_show/id_XNTExMTE2OTU4NA==.html

使用特权

评论回复
14
名字是啥样| | 2021-3-4 12:17 | 只看该作者
楼主可以分享一下原理图吗?

使用特权

评论回复
15
zhouyong77| | 2021-3-5 08:17 | 只看该作者
搞个琴键来玩玩

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

378

帖子

1

粉丝