前言
本设计的目标是设计一个语音传输实时播放系统,由电子科学与技术系曾益斌老师出题。以串口转RS485的通信方式,实现100米双绞线的音频无损耗传输。本设计为福州大学电子科学与技术专业课设计,设计完成时间为2025.5.26,课程等级评价为优秀。

目录
一、设计目的和要求
1.1设计目的
通过本项目设计,理解基于RS485通讯的工作原理,并针对通讯速率和可靠性提出改进措施,进一步应用于语音通信电路中去。

- 熟悉通信系统的基本组成;
- 熟悉多个处理器编程,协同工作;
- 验证抽样定理;
1.2设计要求

- A机采集语音,通过485总线传送给B机,双绞线长度为100m,B机播放声音,要求能实时采集、实时传输、实时回放,回放音质好;
- A机能通过按键显示屏调整抽样频率,B机无按键显示屏,A机将调整的抽样频率参数发送给B机;B机能将测试分析得到的误码率参数传给A机显示,A机和B机能实现双向通信;
- 系统稳定可靠,性价比高;
二、设计原理
2.1设计原理图

图1 PCB设计图

图2 原理图
主控单片机选型为STC8H8K64U单片机,主、从机的PCB设计图均如上图所示。为了方便起见,AB机采用相同的PCB设计,但每块PCB上只有其专用的组件参与工作(如A机OLED显示、麦克风采集、键盘、RS485)。
2.2方案选择比较
由于我们在之前的学习课程《C程序设计实践》中对51单片机的掌握程度比较高,能够得心应手的设计修改代码,实现功能。在曾老师的代码设计方案基础上,程序整体的开发难度并不高,硬件开发难度也只需要部分改动即可实现功能,同时曾老师也在之前提供了音频串口验证的上位机设计,更是大大降低了我们的实践设计难度。
因此,我们小组选用两块STC8H8K64U进行设计,其余器件沿用之前C程序设计实践所使用的零部件,既能保证系统稳定可靠,也能保证系统的高性价比。
2.3工作原理介绍
2.3.1整体框架

图3 总体框架设计图
本项目由两台设备组成(以下简称发送机为A机与接收机B机),A机由单片机、麦克风和OLED显示屏、按键键盘、485通讯模块组成,B机由单片机、耳机功放、TLC5615DAC转换芯片组成。二者之间以RS485作为物理层协议通过双绞线进行通信,硬件部分构成整体框架如图所示。
设备需要在复位时进行一次CRC误码率校准,这一功能的实现方法是在两机程序进入主循环之前,执行一次初始化,A机向B机发送校准信号,进行一次数据包传输,B机接收到之后,进行CRC校验码处理,返回计算出的误码率。
半双工实现语音双向传输部分的工作原理如下:首先在程序设计中让A机、B机约定好合适的波特率(本设计采用921600bits/s,足够的带宽以保证传输数据),主机A通过ADC利用特定频率(4、6、8kHz以及最大采样频率)对语音信号进行采集,AB双方也要通过数据传输来约定好特定的采样频率,只有当两机的采样频率对应时,才能进行正确的回放。在按键按下进入传输之前,会先产生一个对码信息,B机串口识别到后,调整为与A对应的频率进行DAC转换。
在采集到一定大小的语音后打包进行发送,从机B在接收完主机A的一个完整数据包后存入缓冲区(缓冲区大小为1024bytes),再以对应频率的DAC转换速度将固定大小的语音数据包转换为数字信号播放出来。
2.3.2理论数据计算与实际验证
单片机自带的ADC精度为12位,TLC5615的精度为10位。为了对齐数据并通过串口顺利传输,我们对ADC的数据进行处理,只保留其高8位的数据,舍弃低四位数据。
char Get_ADCResult(void)
{
ADC_CONTR|=0x40; //启动AD转换,ADC_START=1
while(ADC_CONTR & 0x20 ==0)
; //等待ADC_FLAG变为1
ADC_CONTR &= 0xBF; //关闭AD转换,ADC_START=0
ADC_CONTR &= 0xDF; //将ADC_FLAG清0
return ADC_RES; //ADC为12位,返回高8位,舍去低4位
}
接下来我们计算理论能达到的最大采样率。应考虑所谓“木桶效应”,即能接受采样率上限最低的那一个组件。在查阅了资料之后,我们发现DAC(TLC5615)最大支持的DAC转换频率仅有80kHz,而单片机的ADC能达到近800kHz。因此,在硬件不出问题的情况下,理论通过软件设计可以达到80kHz左右的采样频率。在理论基础上我们进行双机测试,实际可达到76kHz左右的极限频率,最大频率被DAC转换频率所约束。
串口每次传输8位数据,加上1位的起始位与1位的停止位(不含校验位),共计10位。波特率计算公式为:

| 采样频率 | 4kHz | 6kHz | 8kHz | 70kHz |
| 波特率(bits/s) | 40 000 | 60 000 | 80 000 | 700 000 |
若是想要顺利的传输高频率采样的结果,需要足够的波特率支持,根据计算公式可得,要想要支持70kHz的ADC采样率,需要至少700 000的波特率。因此我们程序设计中,两机的波特率为921 600,足够大以保证传输的顺利。
2.3.3RS485通讯模块原理

485(一般称作RS485/EIA-485)是隶属于OSI模型物理层的电气特性规定为2线,半双工,多点通信的标准。它的电气特性用缆线两端的电压差值来表示传递信号。RS485仅仅规定了接受端和发送端的电气特性。它没有规定或推荐任何数据协议。
RS485的特点包括:
(1)接口电平低,不易损坏芯片。RS485的电气特性:逻辑“1”以两线间的电压差为+(2~6)V表示;逻辑“0”以两线间的电压差为-(2~6)V 表示。接口信号电平比RS232降低了,不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便与TTL电路连接。
(2)传输速率高。10米时,RS485的数据最高传输速率可达35Mbps,在1200m时,传输速度可达100Kbps。
(3)干扰能力强。RS485接口是采用平衡驱动器和差分接收器的组合,抗共模干扰能力增强,即抗噪声干扰性好。
(4)传输距离远,支持节点多。RS485总线最长可以传输1200m以上(速率≤100Kbps)一般最大支持32个节点,如果使用特制的485芯片,可以达到128个或者256个节点,最大的可以支持到400个节点。
本项目以RS485作为物理层协议进行通信。
2.4关键器件的选择
2.4.1主控芯片的选择

主控单片机选型为STC8H8K64U单片机,最大晶振可以达到45MHz,本设计中采用44.2368MHz的晶振频率。拥有性能强大的模拟外设:超高速ADC,支持12 位高精度15 通道(通道0~通道14)的模数转换,速度最快能达到800K(每秒进 行80 万次ADC 转换),单片机上有专门为RS485设计保留的引脚,便于调试操作。IIC(驱动OLED)、串口等功能都足够支撑本设计要实现的功能。同时有足够的定时器(本设计中用到的定时器:A机一个用于按键扫描消抖,另一个用于执行对应频率采集ADC,B机用于DAC输出)可供本设计使用。
2.4.2麦克风模块和功放模块的选择

本项目选择MAX4466作为麦克风模块。MAX4466是微功率运算放大器,经过优化,可用作麦克风前置放大器。它们提供了优化的增益带宽产品与电源电流的理想组合,以及超小型封装中的低电压工作。MAX4466具有增益稳定性,仅需24uA的电源电流即可提供200kHz的增益带宽经过解压缩,可实现+5V/V的最小稳定增益,并提供600kHz增益带宽积。此外,这些放大器还具有轨到轨输出,高AVOL,以及出色的电源抑制和共模抑制比,适合在嘈杂环境中工作。广泛应用于蜂窝电话、数字复读装置、耳机、助听器、麦克风前置放大器、便携式计算机、语音识别系统中。

本项目选择MAX4410作为功放模块。MAX4410是一片低失真,低电压,低功耗的高保真耳机放大芯片,它不但可以做耳机放大,也可以当功放前级使用,效果也不比运放前级差,实现一板两用。板子设计有3.5耳机座输出和2.54mm排针输出,可以根据不同需要选择。
2.5程序设计流程以及关键代码解释
程序分为四部分进行设计:CRC8校验码部分、语音数据的采集(ADC)部分、语音播放(DAC)部分、其余硬件部分(OLED、按键等)。其中双向传输部分介绍了485通信的实现以及半双工总线上数据避让措施的实现,语音数据的采集与播放部分主要介绍了通过定时器设定不同采样频率,实现实时语音采集与播放。
2.5.1CRC8校验实现
首先在A机和B机代码中都添加CRC8校验函数(采用标准多项式0x07)
// CRC8校验函数(多项式x^8 + x^2 + x + 1,即0x07)
unsigned char Calc_CRC8(unsigned char *data, unsigned int len) {
unsigned char crc = 0x00;
while(len--) {
crc ^= *data++;
for(unsigned char i = 0; i < 8; i++) {
if(crc & 0x80) {
crc = (crc << 1) ^ 0x07;
} else {
crc <<= 1;
}
}
}
return crc;
}
在A机代码中添加测试数据包发送功能:
// 在main函数中主循环前添加:
if(Key_Down==1) {
TR0 = 0; // 停止定时器
OLED_CLS();
OLED_P8x16Str(0,1,"CRC Testing...",14);
// 发送测试数据包(包含CRC校验码)
unsigned char testData[] = {/*此处使用函数生成合适量的数据*/}; // 测试数据
unsigned char crc = Calc_CRC8(testData, sizeof(testData));
// 发送数据包(数据+CRC)
for(int i=0; i<sizeof(testData); i++) {
Uart_SendByte(testData[i]);
}
Uart_SendByte(crc);
// 等待B机返回误码率结果
Delay1000ms();
Key_Down = 0;
}
B机计算误码率并返回:
// 全局变量添加
unsigned int totalBits = 0;
unsigned int errorBits = 0;
// 修改UART_ISR函数:
void UART_ISR() interrupt 4 {
static unsigned char rxBuffer[32];
static unsigned char rxIndex = 0;
static unsigned char expectingLength = 0;
if(RI) {
RI = 0;
unsigned char received = SBUF;
if(rxIndex == 0 && received == 0x55) { // 检测包头
rxBuffer[rxIndex++] = received;
expectingLength = 6; // 假设固定长度数据包
}
else if(rxIndex > 0) {
rxBuffer[rxIndex++] = received;
// 完整数据包接收
if(rxIndex == expectingLength) {
// 验证CRC
unsigned char crc = Calc_CRC8(rxBuffer, expectingLength-1);
if(crc != rxBuffer[expectingLength-1]) {
// CRC校验失败,计算误码率
errorBits++;
}
totalBits += (expectingLength-1)*8;
// 计算并返回误码率
float ber = (float)errorBits / totalBits;
Uart_SendByte((unsigned char)(ber * 100)); // 返回百分比
rxIndex = 0;
}
}
}
在A机接收到误码率之后,在串口处理函数中进行误码率显示,控制OLED显示误码率。
2.5.2ADC采集设计
单片机自带的ADC精度为12位,TLC5615的精度为10位。为了对齐数据并通过串口顺利传输,我们对ADC的数据进行处理,只保留其高8位的数据,舍弃低四位数据。
1.char Get_ADCResult(void)
2.{
3. ADC_CONTR|=0x40; //启动AD转换,ADC_START=1
4. while(ADC_CONTR & 0x20 ==0)
5. ; //等待ADC_FLAG变为1
6. ADC_CONTR &= 0xBF; //关闭AD转换,ADC_START=0
7. ADC_CONTR &= 0xDF; //将ADC_FLAG清0
8. return ADC_RES; //ADC为12位,返回高8位,舍去低4位
9.}


如图,配置不同频率的定时器函数
之后通过按键逻辑调用不同的定时器初始化函数,来调整采样频率,DAC同理。
2.5.3DAC输出设计
// 音频缓冲区定义
#define BUFFER_SIZE 1024
unsigned char xdata audio_buffer[BUFFER_SIZE];
unsigned int buf_write_index = 0;
unsigned int buf_read_index = 0;
bit buffer_full = 0;
bit rate_change_flag = 0; // 采样率改变标志
先设置一个音频缓冲区来得到一定量的音频数据,再执行DAC转换。
B机音频输出的定时器函数与ADC的完全相同,此处不再加以展示。
DAC写入函数:
// TLC5615 DAC写入函数
void TLC5615_DAC(unsigned int Data) {
unsigned char i;
Data <<= 6; // 左移6位,保留10位有效数据
TLC5615_CS = 0;
TLC5615_SCLK = 0;
for (i = 0; i < 12; i++) {
TLC5615_DIN = (bit)(Data & 0x8000);
TLC5615_SCLK = 1;
Data <<= 1;
TLC5615_SCLK = 0;
}
TLC5615_CS = 1;
TLC5615_SCLK = 0;}
下面这段串口中断服务程序检测串口传来的数据是指示命令还是音频数据。如果是指示命令,则切换对应输出频率,如果是音频数据则执行DAC写入。
// 串口中断服务函数
void UART_ISR() interrupt 4 {
static bit is_rate_command = 1; // 标记当前是否为采样率命令
if (RI) {
RI = 0; // 清除接收中断标志
if(is_rate_command) {
// 处理采样率命令
switch(SBUF) {
case SAMPLE_RATE_10K:
current_sample_rate = SAMPLE_RATE_10K;
rate_change_flag = 1;
break;
case SAMPLE_RATE_4K:
current_sample_rate = SAMPLE_RATE_4K;
rate_change_flag = 1;
break;
case SAMPLE_RATE_8K:
current_sample_rate = SAMPLE_RATE_8K;
rate_change_flag = 1;
break;
case SAMPLE_RATE_40K:
current_sample_rate = SAMPLE_RATE_40K;
rate_change_flag = 1;
break;
default:
// 无效命令,保持当前采样率
break;
}
is_rate_command = 0; // 下一个字节是音频数据
} else {
audio_buffer[buf_write_index++] = SBUF;
if (buf_write_index >= BUFFER_SIZE)
buf_write_index = 0;
if (buf_write_index == buf_read_index)
buffer_full = 1;
// Uart_SendByte(0xAA); // 发送数据接收确认
}
}
}
下面这段代码是定时器中断服务函数,检查是否有数据可播放,并决定是否通过DAC输出。
2.5.4其他部分设计
以下是键盘扫描函数,配合定时器1进行每10ms的按键扫描(仍需在主循环中调用),通过获取按键的下降沿上升沿,来实现按键消抖处理:
void Key_Proc()
{
if(Key_Slow_Down) return;
Key_Slow_Down=1;
Key_Val=Key_Read();
Key_Down=Key_Val&(Key_Val^Key_Old);
Key_Up=~Key_Val&(Key_Val^Key_Old);
Key_Old=Key_Val;
}
/////////////////////////////////////////
void Timer1_Isr(void) interrupt 3
{
if(++Key_Slow_Down==10)
Key_Slow_Down=0;
}
初始化整机以及设计整个OLED的UI界面,实现按键控制:
void main()
{
OLED_Init();
Uart_Init();
ADC_Init();
Key_Init();
Timer1_Init();
OLED_P8x16Str(0,10,"Waiting...",10);//上电时进行误码率计算等待...
while(1)
{
Key_Proc();//调用按键扫描
if(Key_Down==1)//按键1按下的操作
{
TR0 = 0; // 停止定时器
OLED_CLS();
OLED_P8x16Str(0,1,"Choose frequency",16);
Key_Down = 0;
}
if(Key_Down==2)//按键2(之后同理)
{
if(a<3)
a++;
else if(a==4)
a=1;
Switch_Sample_Mode();//调用频率选择函数
Key_Down=0;
a_old=a;
}
if(Key_Down==3)
{
if(a>1)
a--;
else if(a==4)
a=3;
Switch_Sample_Mode();
Key_Down=0;
a_old=a;
}
if(Key_Down==4)
{
a=4;
Switch_Sample_Mode();
OLED_CLS();
Key_Down=0;
}
}
}
采样频率选择函数:
void Switch_Sample_Mode() {
if(a!=a_old)
{
OLED_CLS();
TR0 = 0; // 停止定时器
switch (a)
{
case 1:
{Uart_SendByte(0x01);
OLED_P8x16Str(0,1,"Frequency 4k",12);
Delay1000ms();
Delay1000ms();
OLED_CLS();
Timer0_Init_4k();
break;}
case 2:
{Uart_SendByte(0x02);
OLED_P8x16Str(0,1,"Frequency 6k",12);
Delay1000ms();
Delay1000ms();
OLED_CLS();
Timer0_Init_8k();
break;}
case 3:
{Uart_SendByte(0x03);
OLED_P8x16Str(0,1,"Frequency 8k",12);
Delay1000ms();
Delay1000ms();
OLED_CLS();
Timer0_Init_10k();
break;}
case 4:
{Uart_SendByte(0x04);
OLED_P8x16Str(24,1,"Perfect:",8);
OLED_P8x16Str(0,3,"Frequency 40k",13);
Delay1000ms();
Delay1000ms();
OLED_CLS();
Timer0_Init_40k();
break;}
}
TR0 = 1; // 重启定时器
}
}
软件程序的基本设计如上,可以完全的执行CRC8校验,并实现按键切换采样频率,ADC转换,串口传输数据以及DAC输出,并按照要求实现了对应的OLED屏幕显示功能。
三、设计测试结果
3.1上位机测试方法
为了有利于问题的检验,应该按照分步走的方式,逐步实现两机功能。A机部分代码实现后,在现有的基础上,使用电脑上位机代替B机来进行交互,避免出现错误时找不到具体原因(排除B机错误的干扰,专对A机进行测试),这是上位机的一大优势所在。


上位机以及对应参数调整方法
通过调整上位机的参数,使其和A机的采样频率进行对齐,再调整波特率对齐和串口号正确,保证上位机和单片机的正常传输。设置好单次获取音频的长度大小,就可以在电脑对应文件夹下产生一个音频wav文件,可以通过播放wav文件来听采样的音质效果,从而进一步调整参数。通过上位机验证之后,便可以确保A机采样、发送数据无障碍。
之后在单独对B机进行调试,通过电脑的串口助手,记录下A机的采样数据,按照波特率发送给B机,验证B机是否能成功播放音频。在验证完之后,将两机进行串口连接,调试对应的功能,包括两机对码、误码率校准等。在一切完成之后,再加入RS485通信模块,对于新出现的问题再进行一步步调试。
这样分步走的形式,大大降低了排查错误的工作量,每次针对一个功能进行调试,分模块进行测试,可以快速地发现问题,解决问题。
3.2半双工总线上数据避让的方法
本系统设计中,主、从机都有数据发送的需求(A机发送音频数据、B机返回误码率数据),虽然说串口是全双工的总线,但是我们有距离传输的要求,通过RS485的差分信号传输可以拓展传输距离(本设计中为100m)。为了数据的顺利传输,我们需要设计程序,使系统在任一时刻只有一个设备发送数据(作为主机)。我们设计主机只在上电时发送一次CRC校验码包的数据,此时从机静默。主机发送完数据后也进入静默,等待从机返回误码率信息。主机在接收到从机的误码率信息后开始向从机传输音频数据。这样的逻辑通过事件触发动态切换发送权,符合半双工通信的基本规则。
3.3背景噪音的处理方法
在设计过程中,我们得到的音频输出总有背景电流底噪,持续且稳定。我们在反复测试后,发现问题并不出现在软件系统之中,而是来自于OLED。当我们没进行OLED显示设计时,并没有出现电流底噪,而设计OLED显示之后,出现背景噪声。通过查阅资料,我们得知,这个背景噪声的来源是OLED屏幕的电源噪声:OLED 屏幕在刷新时(尤其是动态显示)会突然消耗较大电流,导致电源电压波动,并且麦克风或 ADC(模数转换器)对电源噪声敏感,电压波动会被误采集为背景噪声。
我们的处理方法很简单,在采集和传输音频的时候停止对OLED的刷新,在按键触发之后再进行OLED显示界面的变化。通过设计实践发现该方法可行有效,背景噪声显著降低。
3.4长距双绞线产生信号紊乱的处理方法
我们在测试短双绞线(1-2m)时,信号可以稳定传输且误码率接近于0,但是在接入100m双绞线时,出现信号大幅紊乱的情况:

我们查阅RS485的数据手册发现,当信号在传输线末端遇到阻抗突变时,未匹配的阻抗会导致信号反射回总线。这种反射会与原始信号叠加,造成波形畸变,引发数据错误或通信中断。例如,在长距离传输中,反射信号可能多次往返总线,加剧干扰。RS-485通信电缆的特性阻抗标准为120欧,终端电阻的作用是吸收信号能量,使总线末端阻抗与电缆特性阻抗一致,从而消除反射。

我们将RS485上的120Ω端接电阻部分进行短接,添加了这个反射电阻,在进行测试,果然信号恢复了正常。
3.5出现音频异常降调的原因与解决办法
在尝试将采样频率拉到70kHz的时候,设置好AB机参数并确认无误后,发现了一个奇怪的现象:放出的声音音调降低了非常多。经测试,A机能通过麦克风正常采样并发送音频数据,B机的功放也正常。
我们尝试寻找原因。不难发现音调发生降调的原因是A、B机采样、转换速率不能匹配导致的(在此之前A机与电脑上位机匹配时也出现过这个情况,是参数不匹配导致的)。经测试,我们发现简化串口中断函数的功能(CRC校验码等)后,可以正常播放出不失真的音频。我们得出原因为:CPU的极限性能在此时体现,B机没有足够的资源来运行足够快的70kHzDAC转换,需要简化一些其他功能,以保证DAC程序能以相应的速度运行。
3.6采样最高频率的测试与验证方法
在曾老师的指导下,我们开始探索该系统的可采样频率极限,以及限制因素。
一开始我们探索的最高可测频率70kHz,更多的是出于直观感知,而缺乏具体的数据理论计算和具体测试。
我们一开始认为,约束极限采样频率的因素有三个:ADC最大采样速率、DAC最大转换速度、单片机最大传输速率(波特率)。我们通过资料查询验证,本系统的ADC采样速率上限极高,能达到800kHz;DAC是TLC5615芯片,DAC建立时间为12.5us,最高频率只能达到80kHz左右;单片机的通信速率我们采用921600的波特率。根据短板效应,这里制约最大传输速率的原因应该出自DAC的转换速率。
但是曾老师为我们指出,最大采样频率的约束并不在此。他提示我们要测出定时器最小定时时间,CPU此时处于满负荷工作,并且测试在这个最小定时时间内能否跑完DAC的转换程序代码。

在曾老师的指点下,我们通过翻转引脚的方式来测波形,观察DAC程序执行的速度。

通过示波器得到,引脚的翻转频率接近90kHz,即可证明执行DAC代码段的最高频率可以达到至少90kHz(翻转引脚也占用时长)。接下来我们再测试70kHz的定时器能否进行70kHz的DAC输出。


在70kHz定时器中执行DAC代码段仍然可以顺利输出,频率符合要求。说明该系统能支持70kHz的采样频率。
四、总结
4.1对电路设计结果的总结
本次电子系统设计能通过100m双绞线,以RS485半双工总线的差分信号进行远距离串口数据传输,波特率达到921600,实现误码率(<0.1%)计算以及不同频率的音频采集、播放切换。OLED屏幕能实现所要求的信息显示和按键切换功能。
在本次系统设计中,主要解决了CRC校验码计算问题、音频采样噪声问题、半双工总线数据避让问题、最大音频采样速率制约因素的问题。
对于最大音频采样速率限制因素的实验结论是:DAC程序的最大执行速度可以达到近90kHz,但是这是在最理想的情况下,即没有其他功能模块,如串口中断、OLED刷新、按键扫描定时器的情况下,所以在我们题目背景要求下做不到。所以限制采样频率的主要因素有以下几点:
- 单片机的极限处理性能(程序执行速度);
- DAC的建立时间(数据手册为12.5us);
- 两机传输的最大波特率(数据带宽);
- ADC采样速度(ADC最快可达800khz)。
其中本题限制我们最高采样频率的因素是CPU的处理速度。
4.2电路设计存在的问题
PCB设计的不够合理,只打了一块PCB进行模块分用,不符合我们课程设计的要求,空间利用率不够高。
RS485模块需要加焊上120欧姆的反射电阻消除信号反射,降低误码率。
4.3对采样定理的验证
通过本系统可以进行奈奎斯特采样定理的验证。奈奎斯特采样定理描述道:如果采样频率fs大于信号最高频率fmax的两倍(即fs> 2fmax),则原始信号可以从采样中无失真地重建。人耳能听到的频率范围通常为20Hz~20kHz,本设计有4个可切换的频率采样通道,通过按键可以切换采样频率,有4、6、8、40kHz四个通道。
当进行4kHz采样时,人声可以大致进行分辨(能大致听清文字,带有略微失真);在6kHz采样时,人声可以被清晰地还原(文字能清楚听见);在8kHz时,声音的较多细节都能被还原出来,人声可以听清咬字,且不失真;在40kHz采样下,可以对音频(音乐)进行良好的还原,背景的音乐伴奏、鼓点等也能被不失真地放出。
4.4对设计的进一步完善
曾老师提示我们,如果要让这个系统获得更高的采样频率,DAC要用并行而不是串行,ADC、DAC要用DMA方式实现,而不是用CPU实现。
在微机原理与嵌入式系统基础这门课中,我们学习到,并行IO设备的速度远高于串行,本设计的DAC选型使用的是串行10位的TLC5615芯片,因此最高速率不如并行DAC快。同时,应该使用DMA而不是CPU来执行ADC、DAC,通过DMA直接对外设的访问,将数据读入存储器,速率可以得到显著提升。同时我们也了解到,在电子竞赛中,做高速的ADC只能用DMA实现。
4.5设计答辩问答环节
曾老师:系统的传输波特率是多少?误码率是多少?最高实现回放频率是多少?
答:系统的波特率为921600,误码率硬件当场测试为0.2%,最高实现回放频率为40kHz(后验证为70kHz)。
曾老师:ADC是几位的?每次传输几位?高x位还是低x位?
答:ADC是12位的;每次传输8位的数据位,因为51单片机UART为8+2位;传输高8位,高8位包含更大权值,即使丢失低4位,误差也小。
曾老师:RS485是全双工还是半双工的传输?传输的是什么信号?
答:(此处答错)RS485是全双工,因为RS485是串口的延伸,串口是全双工,所以RS485也是全双工。传输的是差分信号。
正确答案:RS485是半双工通信。
曾老师:如果差分信号一条是+5V,那么另一条应该是多少伏?
答:(此处答错)应该是GND吧,即0V。
正确答案:另一条为-5V。
曾老师:系统软件是否有设置缓冲区,如果有,缓冲区多大?
答:有设置缓冲区,大小为1024。
// 音频缓冲区定义
#define BUFFER_SIZE 1024
unsigned char xdata audio_buffer[BUFFER_SIZE];
unsigned int buf_write_index = 0;
unsigned int buf_read_index = 0;
bit buffer_full = 0;
bit rate_change_flag = 0; // 采样率改变标志
附加题:
曾老师:DAC输出信号:
A.时间连续、幅度连续
B.时间连续 、幅度不连续
C.时间离散、幅度连续
D.时间离散、幅度不连续
答:B。时间连续,幅度不连续。
其他题目总结:
1.验证抽样定理:抽样频率大于原始模拟信号最高频率2倍以上时,抽样信号能不失真地还原回原来的模拟信号。在本系统中,抽样信号在哪里得到,还原回原来的模拟信号是在哪里,原始模拟信号在哪里?
答:抽样信号通过ADC采集麦克风的信号获得,在通过DAC把数字信号转换为模拟信号输出,原始的模拟信号是通过麦克风采集声音信号获得。
2.串口发送时,除了发送8位数据位,还要加上一位起始位和一位停止位,所以一次是发送10位,当采样频率为40kHz,传送ADC12bit中的高8bit ,传输速率为256000bit/s,问能否实现40kHz的采样频率?(给出计算公式)
![]()
所以不能实现
3.麦克风输出信号、存储器存储信号、DAC输出信号、音频输出信号、双绞线传输信号分别选什么
A.时间连续、幅度连续
B.时间连续 、幅度不连续
C.时间离散、幅度连续
D.时间离散、幅度不连续
| 麦克风 | 存储器 | DAC | 音频 | 双绞线 |
| 时间连续 | 时间离散 | 时间连续 | 时间连续 | 时间连续 |
| 幅度连续 | 幅度离散 | 幅度离散 | 幅度连续 | 幅度离散 |
五、心得体会
在本项目中,我主要承担了程序设计编程开发、总体框架设计、硬件设计以及撰写报告的任务。通过本次实践,我对团队合作有了新的见解和理解。过去,我很少参与团队项目,大多数时间都是独立研究和学习;但在团队项目中,可以通过多个成员的视角来检查错误,可以跳出“当局者迷”的困境,各位成员可以发挥所长,真正的做到扬长避短。在团队合作中重要的是与团队成员的任务衔接,并保持交流与沟通。
在实践设计时,要减少对AI工具的依赖,AI可以帮我们梳理框架整理内容,但是不能用来作用于细节程序的设计。在实践探索过程中,不能仅依赖老师传授的知识,而应通过实践和自主学习来完成项目。通过参与这个项目,我对模拟/数字信号处理、串口通信、RS485通信以及51单片机有了更深入的理解,并显著提升了自学能力。最后,我要感谢老师们在课堂内外的耐心指导,我向您们致以最崇高的敬意和感谢!
六、附录
6.1实物图

评分表:



作者邮箱:lingui_fzu@qq.com

4400

被折叠的 条评论
为什么被折叠?



