本文转自ARM中文社区,作者:Xiaoya

链接:https://community.arm.com/cn/b/blog/posts/nucleof429-2-pwm

事实上大部分MCU都可以实现语音播放

下面是一段音频数据的波形

局部放大图:

以一定的速度采样(ADC)这些波形进行存储,就是音频数据了,所以播放就是按原来采样的速率再用DAC输出对应的数据即可。

这里的音频有两个主要的参数,采样速率采样位数

采样速率:指1s中采样多少个数据点,比如1s种采集16000个点,那么采样率就是16KHz。采样速率越高,越能抓到频率较高的声音,比如CD的采样率就是44.1KHz,确保人耳能听到的声音都会被抓到。

采样位数:指音频幅度最大值与最小值分为了多少阶,比如满幅度是3.3V,如果是8Bit位数,那么每一阶就是3.3V/256 = 12.89mv,采样位数越高,声音细节越好。所以采样速率和位数越高,声音还原越逼真,但存储的数据量也越大,一首三四分钟的歌曲,如果不采用编码按原始波形数据存储,数据量有好几十兆大小,这涉及到音频编码的问题,这里不展开讲了,有兴趣的同学可以找相关资料。

接下来看怎么播放,最简单的当然是把采样(ADC)的数据按原样输出(DAC)了。但我们有些芯片本身不带有DAC,所以只能用PWM代替DAC,PWM即脉冲宽度调制。这里只需要把DAC的幅度值转换成PWM的占空比即可,例如16KHz 8Bit的声音转换成16Khz 256阶占空比的PWM。但有一个问题,如果用16KHz的PWM播放语音,声音是可以播放,但有一个16Khz的谐波存在,这个声音会被人耳听到,所以需要更高频率的PWM,数据还是按照16Khz更新。

我这里使用32KHz的PWM,用16KHz 8Bit PCM格式的音频数据,8Bit的数据对应一个Byte,16KHz采样,1秒种占用存储空间就是16K Byte,F429有2M Byte的Flash存储空间,理论上可以存储2048K/16K = 128秒的音频。

下面是用NucleoF429实现音频播放的具体过程:

一、配置PWM

1、用STM32CubeMx建立工程,配置两个定时器TIM1和TIM2,TIM用于PWM产生,TIM2用于16KHz数据更新。

TIM1选择PWM互补输出(单通道也可以),将PE8和PE9复用为PWMN和PWMP。

TIM1在APB2总线上,TIM2在APB1总线上

所以TIM1和TIM2的时钟频率分别为180M和90M,系统时钟用HSE输入的8MHz。

将TIM1设置为32KHz,即31.25us。8Bit占空比,一个LSB为31.25us / 256 = 0.1220703125us = 8.192MHz,TIM1 180M / 8.192M = 21.97265625,这里取整数22。所以实际的PWM频率为1/(180 / 22) *256 =  31.289us = 31.96KHz

TIM2 为90MHz,45分频后为2MHz即0.5us,周期125即62.5us = 16KHz。

NVIC开启TIM2中断。生成工程名和目录后生成Keil工程。

二、播放语音

1、先编译后,编写TIM中断服务程序。

完成后,开启TIM2中断和PWM,(PWM是互补输出,需要单独开启各个通道)

用逻辑分析仪测量输出波形。

如图所示,TIM1 PWM为31.96KHz,TIM2为62.5us即16KHz,结果正确。

接下来处理音频:

这里使用的音频是PCM格式,是未进行压缩编码的原始数据,可以直接给PWM输出。

音频处理的软件有许多,只要能把格式转为PCM即可,下面是我用Cool Edit这款软件做的音频格式转换。

选择菜单 文件-->批量转换

选择新的采样率和采样位数。

选择PCM格式。设置输出目录后运行批处理完成转换。

完成后的音频文件用WinHeX这个软件打开。

图中红框中的44个Byte为PCM格式的文件头信息,后面的的数据为音频数据,数据全选后利用WinHex的可选格式复制

将数据以C数组的形式导出,在工程目录下新建.h文件,将复制的文件粘帖到.H文件并在工程中Include进来,定义起始和结束地址,数组的大小即为文件结束地址,数组用const修饰,可以将数据存储到Flash中。

在TIM2中,以16KHz的速度更新PWM数据即可实现音频播放。

编译工程,下载到NucleoF429板子上,在PE8或PE9上接一个喇叭即可听到声音。

以上用的音频采样是16K 8Bit,要想提高音质,提高采样和Bit数即可,音量可以用外接三极管或功放放大,音频数据也可以用ADC采集后存储到SPI Flash后播放,实现录音回放。

为了方便阅读,附件中包含了此文的PDF文档,Source Code也在附件中,可以直接下载到Nucleo运行。

公众号后台回复关键词:PWM语音,即可获取源码下载链接。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

使用PWM实现语音播放相关推荐

  1. PWM实现语音播放原理

    采用PWM进行播放语音原理 1.概述 2.声音原理 3.DAC产生声音的原理是什么 4.PWM又是如何实现的DAC的 5.PWM的频率与底噪的关系 6.PWM音乐曲目解析 7.后续 1.概述 大多数微 ...

  2. 乐鑫Esp32学习之旅 23 安信可 esp32-a1s 音频开发板移植最新 esp-adf 音频框架,小试牛刀如何实现在线文字转语音播放。

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 " ...

  3. 多功能料理锅语音播放芯片——NV040C

    多功能料理锅就是一锅搭配多个锅盘,可以实现火锅.烤肉.花式煎蛋.丸子等多种烹饪功能. 多功能料理锅语音方案设计需求: 多功能锅本身体积有限,按钮比较少,相应功能的字体要贴按钮旁边,字体也是比较小的,这 ...

  4. Windows如何 cmd 查找文件路径 开机启动 CMD语音播放 CMD切换到管理员!

    1,语音播放: CreateObject("SAPI.SpVoice").Speak"崭新的开始,你好!" 单词别拼写错误啦! 把这个拖到开机启动项里就可以开后 ...

  5. python输出到语音播放_用Python写一个语音播放软件

    单位经常使用广播进行临时事项的通知(将文字转换为语音然后通过功放广播),但是市面上多数语音播放软件都是收费的,要么发音失真,要么不够稳定--经常出现莫名其妙的故障,容易给工作带来被动.学Python这 ...

  6. python语音播报-用Python写一个语音播放软件

    单位经常使用广播进行临时事项的通知(将文字转换为语音然后通过功放广播),但是市面上多数语音播放软件都是收费的,要么发音失真,要么不够稳定--经常出现莫名其妙的故障,容易给工作带来被动.学Python这 ...

  7. python软件界面-用Python写一个语音播放软件

    原标题:用Python写一个语音播放软件 单位经常使用广播进行临时事项的通知(将文字转换为语音然后通过功放广播),但是市面上多数语音播放软件都是收费的,要么发音失真,要么不够稳定--经常出现莫名其妙的 ...

  8. Avalonia跨平台入门第二十篇之语音播放问题

    在前面分享的几篇中咱已经玩耍了Popup.ListBox多选.Grid动态分.RadioButton模板.控件的拖放效果.控件的置顶和置底.控件的锁定.自定义Window样式.动画效果.Expande ...

  9. python 语音播放_基于Python编写的语音播放软件

    单位经常使用广播进行临时事项的通知(将文字转换为语音然后通过功放广播),但是市面上多数语音播放软件都是收费的,要么发音失真,要么不够稳定--经常出现莫名其妙的故障,容易给工作带来被动.学Python这 ...

最新文章

  1. Python持续点火,跟进还是观望?
  2. Android.mk 用法介绍
  3. 《LeetCode力扣练习》第3题 C语言版 (做出来就行,别问我效率。。。。)
  4. CTFshow 信息收集 web10
  5. Nginx 通过 Lua + Redis 实现动态封禁 IP
  6. 前端学习(1374):express参数中get参数的获取
  7. HDU - 5441 Travel 离线处理+并查集
  8. git fork clone 区别_我的Git笔记
  9. 一次SocketException:Connection reset 异常排查
  10. 计算机基础——4.1 数字通信入门
  11. 找到投资人的几种途径和方法
  12. JS实现环绕地球飞行的3D飞行线动画效果(JS+HTML)
  13. 爬取新浪滚动新闻--每个详情页标题以及内容
  14. 3.1 机器学习 --- 决策树
  15. 深度学习与自然语言处理教程(8) - NLP中的卷积神经网络(NLP通关指南·完结)
  16. rem 与 px 换算关系
  17. 成像质量、像素个数、感光元件尺寸的关系
  18. CNI(Container Network Plugin)
  19. 解决docker的Get https://registry-1.docker.io/v2/: net/http: request canceled 报错
  20. 图像去雾(二)Retinex图像增强算法

热门文章

  1. [已解决]Vistual Stdio 2015 installer Bootstrapper Packages 路径
  2. 情怀真的可以吃~致文青
  3. ehcache memcache redis 三大缓存男高音
  4. 使用MinGW编译Psycopg2
  5. kafka 日志相关配置
  6. 【机器学习】XGBoost集成算法——(理论+图解+python代码比较其他算法使用天池蒸汽数据)
  7. 位运算中的左移和右移的计算详解
  8. 堆和栈的区别(经典干货)
  9. 单链表的头插法和尾插法实现代码(无头结点)
  10. 源码安装mysql数据库_Linux下源码安装mysql数据库