TA的每日心情 | 擦汗 2019-7-25 08:15 |
---|
签到天数: 4 天 连续签到: 1 天 [LV.2]偶尔看看I
|
本帖最后由 fx283 于 2019-6-25 17:38 编辑
其实这并不是我的毕设作品,为了参与这个活动才加上的标签。但是作品还是有必要分享一下。
一道全国大学生电子设计竞赛的题目:1999年的数字语音存储回放系统。
一、题目要求
先来简单看一下题目要求
基本部分
发挥部分
题目整体的结构比较简单,制作的思路也比较清晰。就直接给出详细的设计方案:
二、硬件部分
使用普通的咪头就可以完成采集,电阻分压,电容隔直。
题目要求放大倍数为46dB,也就是200倍的放大倍数,一级放大可能不太行,采用两级如下图所示的放大器电路串联。
滤波器要求的通频带是300Hz~3400Hz。使用TI的在线滤波器设计工具Webench来进行设计,之后使用洞洞板来焊接。由于此处设计比较简单,就不再贴出具体的电路图了
如果对这个在线工具感兴趣先要简单学习一下,这里有简易的教学视频
因为单片机不能采集0V以下的电压,所以需要将信号抬升到0V以上,这里就使用一个加法器电压,调节前级电路使得信号的峰峰值最大不超过3.3V,这里将信号抬升1.65V,这样采集到的音频信号就会在0V~3.3V之间了。
为了防止某一时刻突然的一个大的声响导致信号电平激增,意外烧坏单片机,所以出于安全的考虑使用一个限幅器电路,将信号电平保持在3.3V以下。
由于此处的滤波器要求的通频带和滤波器1相同,所以使用和滤波器1相同的电路。
此处要求的放大倍数为43dB,为100倍,一级放大已经可以满足要求,故此处使用一级放大电路
因为题目要求的是接一个耳机,那么可以不需要接功率放大电路,只将耳机接在放大器的后面就可以,但是演示效果不好,所以这里使用功率放大电路驱动喇叭去播放录音。使用的是功率放大器模块,PAM8403
三、软件部分
基于正点原子战舰V3开发板的触摸屏实验进行修改,硬件测试平台为太极M3开发板,引脚基本兼容战舰V3开发板,显示屏(触摸)引脚、TF卡引脚完全兼容
1、插入TF卡
2、打开电源,点击显示屏上对用的区域即可执行相应的功能
1、使用定时器产生8KHz的中断,在中断中获取数据,存储到Buffer中
2、存储512个字节后,就在主函数中将数据存入TF卡中的一个Page内
3、当结束录音时,就记录当前的Page数,并写入第一个Page中,作为录音文件的信息
4、DA出来时,同样使用这个定时器
5、直通模式,在定时器中边采集变输出
6、自动音量控制需要分析整个录音文件的均值,根据一定的关系式计算出一个因子
7、提高信噪比,将信号电平与一个门限值比较,若小于门限,则判定为噪声信号,将其置0
7、数据压缩:使用QuickLZ压缩算法,实时进行数据的压缩与解压
8、矫正:使用SINC插值滤波的方法进行矫正
- ……
- #include "AUDIO.h"
- #include "sdio_sdcard.h"
- #include "quicklz.h"
- /*
- 全局变量
- */
- //模式Sample、Play、Cross最多只能有一个为1,Info模式一直为1进行显示
- extern u8 Now_Mode[4];
- extern u8 Info_Mode[3];
- ……
-
- qlz_state_compress state_compress;
- qlz_state_decompress state_decompress;
- extern size_t QuickLZ_Size ;
- int main(void)
- {
-
- ……//一堆的初始化
- //初始化UI界面,随意触发一下界面绘制
- MODE_Scan_DISP(0 , 300 );
-
-
- while(1)
- {
- tp_dev.scan(0);
- if(tp_dev.sta&TP_PRES_DOWN) //触摸屏被按下
- {
- if(tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height)
- {
- //扫描触摸屏,获得对应的函数
- switch (MODE_Scan_DISP( tp_dev.x[0] , tp_dev.y[0] ) )//主要就是做界面的显示
- {
- case MODE_Sample:
- if(Now_Mode[0])
- MODE_Sample_ON_Function();
- else if( !Now_Mode[0] )
- MODE_Sample_OFF_Function();
- break;
- ……
- default:break;
- }
- }
- }
-
- //写入操作移出中断
- if(ADC_FINISH_FLAG)
- {
- ADC_FINISH_FLAG = 0;
- if( QuickLZ_Flag )
- {
- QuickLZ_Size = qlz_compress(ADC_BUFF,(char*)DATA_BUFF,512, &state_compress);
- SD_WriteDisk(DATA_BUFF,TF_Page_Count,1);
- }
- else
- SD_WriteDisk(ADC_BUFF,TF_Page_Count,1);
-
- TF_Page_Count++;
- time_count++;
- sprintf(str,"%7.1f",(float)time_count*0.064);
- ……………………
-
- }
-
- //读出操作移出中断
- if(DAC_FINISH_FLAG)
- {
- DAC_FINISH_FLAG = 0;
-
- if( QuickLZ_Flag )
- {
- while(SD_ReadDisk(DATA_BUFF,TF_Page_Count,1)!=0);
- if(TF_Page_Count != TF_End_Page)
- qlz_decompress((char*)DATA_BUFF, DAC_BUFF , &state_decompress);
- else
- for(i=0;i<512;i++)
- DAC_BUFF[i] = DATA_BUFF[i];
- }
- else
- while(SD_ReadDisk(DAC_BUFF,TF_Page_Count,1)!=0);
-
- ……………………
-
- if( TF_Page_Count > TF_End_Page )//播放完毕,自动触发结束函数
- {
-
- TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE);
- TIM_ITConfig(TIM4,TIM_IT_Update,DISABLE);
-
- if(SINC_Flag)
- MODE_Scan_DISP( 200 , 250 );
- else
- MODE_Scan_DISP( 50 , 100 );
- INFO_SINC_Function_OFF();
- MODE_Play_OFF_Function();
- }
- }
- }
- }
复制代码 所有与音频采集处理、界面显示有关的函数全部都放在了这个Audio文件中,方便移植
程序最终实现的效果如下图所示:
四、功能设计
因为单片机是串行操作,读取ADC的值和存储ADC的值不能同时进行,只要存储器写入一个字节的速度小于1/8K的时间,那么存储就不是问题,否则就会出现采集得快、存储得慢等,数据丢失等一系列问题。实际测试时发现,使用大容量存储介质SD卡的时候,需要一次写入512个字节。写入读出的速度测试如下:
大于1/8K的125us,所以不可避免会出现在写入数据时数据丢失的问题,所以计划采用乒乓操作的思想进行处理,详细原理不再赘述。
自动音量控制(AVC)是输出限幅装置的一种,其作用是将不同强度的语声调整到最适听取的水平。例如:在不调节电视机音量的情况下,有的电视节目声音很大,有的电视节目又声音很小。使用AVC功能后,电视机可以根据节目输入的音量水平,自动调节输出音量水平,保持声音的稳定,减少或消除爆音,同时放大较小的声音至适宜的范围。
软件中首先将所有的音频数据统一处理,计算其平均功率,之后根据一定的计算规则生成一个比例因子,将此比例因子与音频数据相乘,控制数据的大小,使得信号得以实现自动音量控制。
QuickLZ是世界上速度最快的压缩库,每个核心达到308 Mbyte / s。易于使用且易于集成。其C语言版本的代码,可以在无障碍得在各种平台快速移植。如Windows上的Visual Studio,Linux上的gcc,ARM等。软件中使用此压缩算法QuickLZ V1.5.0。
算法处理512个数据的速度测试:
但是它有个最大的缺点:太占用资源,STM32F103ZET6一共64KB的RAM,它自己占用了56KB,下图中最后两个是此算法压缩和解压的结构体变量:
通过提高ADC的采样率可以使得信号的失真度降低。如果AD的采样率一定,那么就可以使用插值滤波器对信号进行处理。软件中另外开启一个32KHz的定时器,使得其DAC的速率变为32KHz,在每两个原采样点之间插入了3个零值。从频域的角度来说,并没有改变信号的单周期频谱,但是却将频谱进行了细化,具体的原理在数字信号处理教材中有讲解,此处不再赘述。
五、系统测试
最后附上系统整体测试的视频
|
|