数码之家

 找回密码
 立即注册
搜索
查看: 12414|回复: 61

[STM] 换药不换汤,基于STM32平台软件的DDS演奏程序,音质轻松秒杀传统蜂鸣器

    [复制链接]
发表于 2020-3-23 21:32:47 | 显示全部楼层 |阅读模式
之前我发过了《基于软件模拟DDS的蜂鸣器驱动程序》,不过这几天又做了一些测试优化,把能工作的稳定版本释放吧!并详细介绍原理。Here we go:

•使用STM32演奏音乐——
•基于DDS原理的 蜂鸣器(×) 扬声器(√) 驱动程序




效果简单展示:https://tieba.baidu.com/p/6577638558
受制于录制设备,听起来的饱和失真是不存在的。



补充内容 (2020-4-4 22:34):
最终效果展示:https://www.bilibili.com/video/bv1yp4y117M5

补充内容 (2020-4-8 22:56):
最新更新内容在47楼

补充内容 (2020-7-29 09:21):
最终代码及讲解见:https://www.mydigit.cn/forum.php?mod=viewthread&tid=182735

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 11家元 +200 收起 理由
871881392 + 10 以資鼓勵
zzy_85569381 + 20 謝謝分享
rallyezhang + 20 優秀文章
zzsese + 8 優秀文章
网络孤客 + 20 優秀文章
EMZ1 + 12 謝謝分享
fm007 + 20 優秀文章
2545889167 + 20
5bin + 30 好贴666
trg13 + 20 不知道51单片机可以实现这个功能不?简单的.

查看全部打赏

发表于 2023-3-31 11:49:16 来自手机浏览器 | 显示全部楼层
跪着看完,躺着出去
回复 支持 反对

使用道具 举报

发表于 2022-6-9 13:12:51 | 显示全部楼层
这个需要多方面的信号与系统的知识以及编程技巧
回复 支持 反对

使用道具 举报

发表于 2021-4-19 07:57:35 | 显示全部楼层
la45088d1 发表于 2021-4-19 00:32
自己瞎搞的,没有参照别人的哟。否则说不定会更完善呢。

频率并不高,用汇编的意义是?  stm32主频都比较高,用c应该没问题
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-4-19 00:32:09 | 显示全部楼层
inthsunshine 发表于 2021-4-18 20:26
基于老外的开源项目?

自己瞎搞的,没有参照别人的哟。否则说不定会更完善呢。
回复 支持 反对

使用道具 举报

发表于 2021-4-18 20:26:34 | 显示全部楼层
基于老外的开源项目?
回复 支持 反对

使用道具 举报

发表于 2020-7-29 22:29:48 | 显示全部楼层
楼主牛逼本科毕业论文都是小意思了:titter:
回复 支持 反对

使用道具 举报

发表于 2020-7-29 10:52:55 | 显示全部楼层
学习了,没事可以自己试试!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-7-19 20:39:00 | 显示全部楼层
最后的一个版本:
下载后把4个文件依次重命名为FM synthesis.7z.001,FM synthesis.7z.002,FM synthesis.7z.003,FM synthesis.7z.004,并使用7zip打开,否则无法打开。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

发表于 2020-5-14 08:38:20 | 显示全部楼层
人艰不拆了 发表于 2020-5-13 17:07
哈哈,以为你不再来了呢

我围观那个回复没有通过,我当时想说的是“闻过则喜”,不知道为什么。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-13 22:11:29 | 显示全部楼层
人艰不拆了 发表于 2020-5-13 17:07
哈哈,以为你不再来了呢

这个项目远没有结束。
如果以后我能了解到更多的声音合成原理,我打算使用FPGA开发一款真正的音调合成引擎。
现在不行。
回复 支持 反对

使用道具 举报

发表于 2020-5-13 17:07:01 | 显示全部楼层
la45088d1 发表于 2020-5-13 14:44
没有哦,因为不会C所以用了ASM。
不过可以根据ASM写C版本的,但是不一定跑得起来。 ...

哈哈,以为你不再来了呢:titter:
回复 支持 反对

使用道具 举报

发表于 2020-5-13 15:12:53 | 显示全部楼层
这简直就是一篇论文啊!
楼主NB:praise:
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-13 14:44:35 | 显示全部楼层
kengcc 发表于 2020-5-13 07:03
有C的例程吗?为什么要用汇编

没有哦,因为不会C所以用了ASM。
不过可以根据ASM写C版本的,但是不一定跑得起来。
回复 支持 反对

使用道具 举报

发表于 2020-5-13 07:03:24 | 显示全部楼层
有C的例程吗?为什么要用汇编
回复 支持 反对

使用道具 举报

发表于 2020-4-17 11:28:44 来自手机浏览器 | 显示全部楼层
真棒,牛逼克拉斯:victory:
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-8 22:53:38 | 显示全部楼层
后续内容更新:

1,源码更新(
2,工程讲解更新:

       一个完整的歌曲音调查找表数据结构如下图所示:段内数据有三部分组成,标识数据(段起始及结束,歌曲标题起始结束,段长度),歌曲标题数据以及音调记录数据组成。

        一个完整的段,第一个字必然是段起始标志0xFFFFFF3C,第二个字必然是段长度,以字为单位。随后第三个字一定是0xFFFFFF69表示歌曲标题数据开始,歌曲数据结束则用0xFFFFFF96表示。段尾的最后一个数据一定是0xFFFFFFC3代表当前段结束。

        歌曲数据则是由ASCII按照小端模式依次填充到每一个字中,字符串从左向右,最左边填充最低的字节地址,最右边填充最高的字节地址,不是4的倍数不足的字节数填充0补齐一个字,正好是4的倍数则在末尾额外增加一个全0的字标志字符串终止。

         在标志0xFFFFFF69与0xFFFFFFC3之间的数据全部是音调记录数据,其总字数总是2的倍数。


5,程序架构行为分析

i.程序运行环境初始化及整体框架行为


         程序起始需要解决两个问题,变量初值指定,关键外设初始化。所以在程序起始阶段需要做的事是对全局变量进行初始化使之为合适初值,使得后续程序正常运行。并且做一些内核密切的配置,如系统时钟的选择,中断优先级分配。

         整体框架行为如右图所示,上电后Cortex-M3自动从FLASH加载两个字的数据,分别是PC(Programcounter)初值和堆栈指针初值(R13or SP),随后跳转Reset_Handler(复位向量),再由复位句柄引发跳转,开始执行SysInit,该函数负责对程序整体运行环境的初始化,做了上述的准备工作。

        随后由SysInit控制跳转到main函数开始执行用户程序。用户程序中,先初始化用户程序需要的外设,由PeripheralInit完成,然后开始正式进行歌曲准备播放工作。

        歌曲播放之前,需要知道FLASH中定义的歌曲段信息,所以调用SongSegBaseAddrSeek扫描指定地址和长度的FLASH区域,得到所有定义的歌曲信息,创建索引记录并保存在私有空间中,随后进入一个循环。循环中不断读取当前播放的状态,如果是空闲状态,就调用PlaySongs函数,传入歌曲索引号触发播放,并且索引号在每次播放后自增指向下一首歌,到头后重置。


ii.SysTick中断服务程序行为分析


        如右图示,在每个中断(使用片内DAC则在SysTick中断中触理,使用片外的IISDAC则在对应的SPI中断中处理)发生后,都会固定地调用音调生成函数ToneDatBufFeed处理完音调生成并输出,随后返回。

        音调生成函数在每次执行时都会检查特定标志位决定是否允许音调生成,随后调用实时采样值生成,输出函数TonesGenerate,进行当前音调的实时采样值的生成并输出。TonesGenerate返回后,判断返回值,如果是0无需特殊处理直接结束本次处理;如果是1则进行进一步处理。

        非0的返回值意味着当前音调结束,下一个音调应该被播放,随后直接从指定的地址加载两个字的数据,并判断第一个字是否为段结束标志0xFFFFFFC3,未结束时直接将加载的数据写入指定的buff结束处理;发现当前段结束时,调用ToneGenCtrl关闭指定中断以及相关硬件,设置特定标准位禁止后续音调发生,结束处理。

  实际上,使用IISDAC输出还面临则左右声道的问题,历程中只在某个声道传输时调用音调生成,另一个声道固定填充静音数据。




iii.实时采样值生成输出函数行为分析


        如右图示,每次执行后都检查音调剩余持续时间计数器,并决定解析来的动作。

        计数器为0时当前音调结束,计数器减一变为-1,函数直接返回,返回值为1通知上层函数重装新的音调记录到指定buff。

        计数器不为0且为正时,计数器减1,进入正常流程,得到各次谐波混合体的实时采样值与幅度实时采样值后就调制并输出。

        计数器为-1时,则调用音调参数设置函数重设音调发生参数,随后进入正常流直到结束。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

发表于 2020-4-1 15:57:20 | 显示全部楼层
:shocked:  牛逼,去我收藏吃灰吧
回复 支持 反对

使用道具 举报

发表于 2020-4-1 08:53:54 | 显示全部楼层
好复杂,慢慢学习。谢谢楼主。
回复 支持 反对

使用道具 举报

发表于 2020-3-31 23:13:38 | 显示全部楼层
用汇编写ARM程序,膜拜了
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-18 14:59 , Processed in 0.280801 second(s), 14 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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