STC8H开发(八): NRF24L01无线传输音频(对讲机原型)
目录
- STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解)
- STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解)
- STC8H开发(三): 基于FwLib_STC8的模数转换ADC介绍和演示用例说明
- STC8H开发(四): FwLib_STC8 封装库的介绍和使用注意事项
- STC8H开发(五): SPI驱动nRF24L01无线模块
- STC8H开发(六): SPI驱动ADXL345三轴加速度检测模块
- STC8H开发(七): I2C驱动MPU6050三轴加速度+三轴角速度检测模块
- STC8H开发(八): NRF24L01无线传输音频(对讲机原型)
关于PWM, DAC和音频
PWM是脉冲宽度调制的缩写, 因为介绍的文章很多, 自己做功课即可, 参考
大部分低端MCU不带DAC转换, 但是可以使用PWM模拟, 对于音频传输
- 人普通谈话的声波频率在500-2000Hz之间, 人耳可以听到的声波的频率范围在20Hz至20kHz之间
- 用于通话, 8kHz的带宽就能达到较好的语音传输效果
- 通过PWM模拟DAC, 因为PWM是方波, 其频率会引入底噪, 底噪的频率是PWM频率的倍数
- PWM频率在8KHz时, 在听感上底噪很大, 与传输的音频一样明显, 将PWM的频率调节到16kHz以上才能有效抑制底噪
通过MCU实现无线音频传输的实现
发送部分

接收部分

以下实现的是单声道 8kHz 8bit 采样的音频信号传输
发送部分
发送部分需要实现的是8kHz采样, 并通过NRF24L01将每秒的8000字节数据发送出去.
语音输入
语音输入可以使用驻极体话筒加S9013放大输入或者直接使用MAX9814. 在测试阶段建议使用后者, 可以保证采样输入不失真, 在调通后再用驻极体话筒电路替换.
ADC音频采样
因为ADC采样需要实现准确的每秒8000采样, 所以不能用DMA方式, 在STC8H(包括STM32等其它MCU)下, 无法在DMA情况下精确调节每秒的采样个数, 因为ADC的采样频率, 采样周期和转换周期在不同MCU中都是固定的, 所以很难正好做到8kHz的采样. 具体的实现中有两种方式:
1.定时器驱动采集
通过定时器设置为8kHz, 在中断中发起ADC转换, 是比较容易实现的. 这时候需要将ADC也实现为中断方式, 因为ADC的转换时间比较长, 如果在定时器中断中做同步的ADC转换, 容易影响主进程. 需要有定时器的中断处理和ADC的中断处理, 定时器的中断处理单纯用于发起转换, ADC的中断才用于读出结果.
2.连续采集定时读取
通过定时器设置为8kHz, 将ADC的采集设置为循环方式(中断采集, 但是在中断时再次发起), 在定时器中断中仅仅读取采集结果. 这种方式也能实现8kHz的采样. 因为这种方式实际上会多消耗电量, 所以使用中还是使用了前一种方法.
NRF24L01发送
NRF24L01在设置为1Mbps带宽时实际传输速度能达到23k字节每秒, 因此对于8bit 8kHz采样的传输是没问题的. 因为NRF24L01传输时的响应和重发机制, 在信号不好时, 容易卡顿, 为了避免中间传输时间的波动影响, 在实际实现中使用了双数组做缓冲. 采样到发送之间的逻辑为
- 两个256字节数组作为全局变量, 同时定义变量指向当前写入的数组编号和写入位置
- ADC中断读取结果时, 往当前编号的数组和位置中写入并移动位置, 当写满一个数组时, 将此数组标记为可发送, 并切换到下一个数组继续写入
- 在主进程中, 判断当前是否有可发送的数组, 如果可发送, 则在循环中按32个字节一组将数据全部发送.
因为在正常收发的信号强度下, NRF24L01的发送速度是比采样速度快的, 所以基本上NRF24L01的发送是发送 -> 等待 -> 发送的状态
接收部分
接收部分要实现的是将NRF24L01接收到的数据进行存储, 并按照8kHz的频率, 将每个值设为PWM输出的占空比, 实现DAC模拟
RNF24L01接收
因为NRF24L01发送是集中发送, 所以在接收时也需要有缓冲, 接收的机制和发送相似
- 两个256字节数组作为全局变量, 同时定义变量指向当前写入的数组编号和写入位置
- NRF24L01通过中断接收数据, 在接收时, 往当前编号的数组和位置中写入并移动位置, 当写满一个数组时, 将此数组标记为可用, 并切换到下一个数组继续写入
PWM模拟DAC还原
初始化一个PWM输出, PWM周期为256对应8bit的占空比调节范围, 确保PWM频率不低于16kHz. 在8kHz定时器的中断中, 判断当前读取的数组和位置, 每次读取一个值, 并将其设置为PWM占空比. 如果数组不可用, 就不做任何操作, 如果此时将占空比设为0, 会产生噪音.
音频输出
测时阶段, 可以在PWM输出上串联一个200R的电阻后值连喇叭, 可以听到输出的音频. 这个电阻不能太小, 测试中如果阻值小于100R, 会导致MCU供电不足反复重启. 在确定音频输出没问题后, 可以替换为 PAM8403 音频放大模块.
在使用 PAM8403 模块时
- 模块需要独立供电, 测试中如果与MCU都使用USB2TTL供电, 会使MCU供电不足而导致声音输出异常
- 模块与MCU的输出可以不共地, 即模块MCU的PWM输出和地, 可以直接接入PAM8403的音频输入
- 因为是单声道信号, 所以只能用PAM8403的一个声道, L或者R都可以
演示代码
- GitHub FwLib_STC8/tree/master/demo/spi/nrf24l01_audio
- Gitee FwLib_STC8/tree/master/demo/spi/nrf24l01_audio
接线说明
在测试中发送部分使用的是 STC8H3K32S2, 接收部分使用的是 STC8H1K08, 你可以使用STC8H系列的任意一个型号
共同的连接部分(NRF24L01)
8H3K32S2/8H1K08 NRF24L01
P35(SS, Ignored) => CSN 16
P34(MOSI) => MOSI 15
P33(MISO) => MISO 14
P32(SPCLK) => CLK 13
P36(INT2) => IRQ 17
P37(IO) => CE 18
发送部分
STC8H3K32S2 MAX9814
P11(ADC1) => MIC
3.3V => VDD
3.3V => GAIN
GND => A/R
GND => GND
ADC, 如果是STC8H3K32S2, 使用ADC采样需要将AVcc, AGnd 和 ADC_Vref+ 正确连线
AVcc => 3.3V
AGnd => GND
ADC_Vref+ => 3.3V
P11 => Output(MAX9814) or MIC
接收部分
STC8H1K08 PAM8403
P10(PWM1P) => 200R => L or R Input
GND => _|_ Input
Ext 3.3V/5V => VCC
Ext GND => GND
注意:
- MCU的pin脚布局不一定相同, STC8H3K32S2和STC8H1K08都是20pin的封装, 但是pin脚布局就不一样
- 烧录发送部分和接收部分时, 注意要调换 nrf24l01.c 中的 RX_ADDRESS 和 TX_ADDRESS
效果演示
B站视频 https://www.bilibili.com/video/BV1kZ4y1Z78v
STC8H开发(八): NRF24L01无线传输音频(对讲机原型)的更多相关文章
- STC8H开发(九): STC8H8K64U模拟USB HID外设
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(十): SPI驱动Nokia5110 LCD(PCD8544)
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(十一): GPIO单线驱动多个DS18B20数字温度计
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(十二): I2C驱动AT24C08,AT24C32系列EEPROM存储
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(十三): I2C驱动DS3231高精度实时时钟芯片
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(十四): I2C驱动RX8025T高精度实时时钟芯片
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(十五): GPIO驱动Ci24R1无线模块
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(十六): GPIO驱动XL2400无线模块
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(五): SPI驱动nRF24L01无线模块
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
随机推荐
- 【LeetCode】1101. The Earliest Moment When Everyone Become Friends 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 并查集 日期 题目地址:https://leetcod ...
- 【九度OJ】题目1473:二进制数 解题报告
[九度OJ]题目1473:二进制数 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1473 题目描述: 大家都知道,数据在计算机里中存 ...
- Problem 2236 第十四个目标
Problem 2236 第十四个目标 Accept: 4 Submit: 6Time Limit: 1000 mSec Memory Limit : 32768 KB Problem D ...
- Towards Evaluating the Robustness of Neural Networks
目录 概 主要内容 基本的概念 目标函数 如何选择c 如何应对Box约束 attack attack attack Nicholas Carlini, David Wagner, Towards Ev ...
- uniapp以及微信小程序中scroll-view隐藏滚动条 自定义滚动条
隐藏滚动条 1.全局隐藏滚动条,在app.vue中 ::-webkit-scrollbar{ display: none; } 2.局部隐藏藏滚动条 样式没有使用scoped属性时, 否则无效. .u ...
- js处理复杂数据格式数组嵌套对象,对象嵌套数组,reduce处理数据格式
let list=[ {id:1,name:'a'}, {id:1,name:'b'}, {id:1,name:'c'}, {id:2,name:'A'}, {id:2,name:'B'}, {id: ...
- URL中使用IPv4,IPv6和主机名
在浏览器的Http请求的URL中如何使用IPv4,IPv6和主机名, 因为IPv6的地址需要加[],导致用法有点区别, 下面通过具体的例子总结一下不同情况下的用法. 1.假设有台Linux主机名配置如 ...
- MD5,SHA1及SHA256等哈希加密方法实现:Java,C#,Golang,Python
哈希算法又称散列算法,它可以从任何数据中快速的创建一个凭证,而这个凭证很难被推倒出来,因为一丁点的变化会导致凭证的差别恨到,也就是说哈希算法具有不可逆性,因此它在密码数据校验方面用的很广,比如我们常用 ...
- Storm集群开启HA高可用
Storm开启HA高可用,包括Nimbus和UI开启两个及以上的进程. 基于已经安装好的Storm集群,开启关键节点角色的HA高可用. Storm安装请参考Storm集群安装Version1.0.1 ...
- CSS基础 背景图片的相关属性
属性名: background-size: 宽度 高度; 属性值 说明 数字+px 简单方便,常用 百分比 相当于盒子自身的百分比,如:百分百,就是就算是图片变形也要显示 contain 动比例缩放, ...