clc;
clear;
close all;
%% 参数设置
fs = 1280000; % 采样率
sample_num = 50; % 每个符号的采样点数
Rb = fs / sample_num; % 符号速率
len_symbol = 400; % 符号个数
Fc = Rb * 2; % 载波频率
% 计算总采样点数时考虑滤波器延迟
span = 6; % 滤波器跨度
N = len_symbol * sample_num + span * sample_num; % 增加滤波器延迟的补偿
dt = 1 / fs;
t = 0:dt:(N-1)*dt; % 时间轴
%% 生成模拟输入信号
Fs_audio = 8000; % 音频采样率
t_audio = 0:1/Fs_audio:0.05; % 50ms音频信号
f1 = 500; f2 = 1000; % 两个频率成分
input_analog = 0.6*sin(2*pi*f1*t_audio) + 0.4*sin(2*pi*f2*t_audio);
% 重采样到符号速率
input_analog_resampled = resample(input_analog, Rb, Fs_audio);
len_analog = min(length(input_analog_resampled), len_symbol);
input_analog_resampled = input_analog_resampled(1:len_analog);
%% PCM 13折线编码
[sampleData, a13_moddata] = PCM_13Encode(input_analog_resampled, Rb, Rb);
% 如果PCM编码数据长度不足,用0填充
if length(a13_moddata) < len_symbol * 8
a13_moddata = [a13_moddata, zeros(1, len_symbol*8 - length(a13_moddata))];
else
a13_moddata = a13_moddata(1:len_symbol*8);
end
% 将PCM编码数据转换为DBPSK输入比特
dataBit = a13_moddata;
%% SRRC滤波器参数
rolloff = 0.35; % 滚降系数
span = 6; % 滤波器跨度(符号数)
sps = sample_num; % 每符号采样点数
% 创建SRRC滤波器
srrc_filter = rcosdesign(rolloff, span, sps, 'sqrt');
%% DBPSK调制(包含SRRC滤波)
[modSignal, diffCode, srrc_output, t_mod] = DBPSK_Modulation_SRRC(dataBit, Fc, sample_num, fs, srrc_filter, span);
% 调整时间轴以匹配调制信号长度
t = t_mod;
%% 加噪
Snr = 15;
modSignal_noisy = awgn(modSignal, Snr, 'measured');
%% DBPSK解调(包含SRRC滤波)
[demodBit, I_filtered, sampled_data] = DBPSK_Demodulation_SRRC(modSignal_noisy, Fc, sample_num, len_symbol, t, fs, Rb, srrc_filter, span);
%% PCM 13折线解码
% 确保解调数据长度正确
if length(demodBit) >= length(a13_moddata)
demodBit = demodBit(1:length(a13_moddata));
else
% 如果解调数据较短,用0填充
demodBit = [demodBit, zeros(1, length(a13_moddata) - length(demodBit))];
end
pcm_decoded = PCM_13Decode(demodBit);
output_analog = resample(pcm_decoded, Fs_audio, Rb);
% 确保输出长度匹配输入
min_len = min(length(input_analog), length(output_analog));
input_analog = input_analog(1:min_len);
output_analog = output_analog(1:min_len);
%% 误码统计
errorNum = sum(xor(dataBit(1:length(demodBit)), demodBit));
BER = errorNum / length(dataBit);
fprintf('误码数: %d, 总比特数: %d, 误码率: %.6f\n', errorNum, length(dataBit), BER);
%% 双踪显示:模拟信号的输入与输出波形
figure('Position', [100, 100, 1400, 1000]);
% 1. 模拟信号的输入与输出波形
subplot(3,4,1);
plot((0:length(input_analog)-1)/Fs_audio, input_analog, 'b-', 'LineWidth', 1.5);
hold on;
plot((0:length(output_analog)-1)/Fs_audio, output_analog, 'r--', 'LineWidth', 1.5);
title('模拟信号输入(蓝)与输出(红)波形');
xlabel('时间 (s)');
ylabel('幅度');
legend('输入信号', '输出信号', 'Location', 'best');
grid on;
% 2. 接收眼图
subplot(3,4,2);
% 使用解调后的基带信号生成眼图
eye_signal = I_filtered;
eye_duration = 2; % 2个符号周期的眼图
eye_samples = sample_num * eye_duration;
num_eyes = floor(length(eye_signal) / eye_samples);
for i = 1:min(30, num_eyes)
start_idx = (i-1)*eye_samples + 1;
end_idx = min(start_idx + eye_samples - 1, length(eye_signal));
if end_idx > length(eye_signal)
break;
end
eye_segment = eye_signal(start_idx:end_idx);
time_eye = (0:length(eye_segment)-1) / fs;
hold on;
plot(time_eye*1e6, eye_segment, 'b-', 'LineWidth', 0.5);
end
title('接收眼图');
xlabel('时间 (\mus)');
ylabel('幅度');
grid on;
% 3. 发射SRRC滤波器输入输出信号(两光标线标注码元宽度)
subplot(3,4,3);
% SRRC输入信号(差分编码后的BPSK符号)
srrc_input = kron(1-2*diffCode, ones(1,sample_num));
plot_idx = 1:min(10*sample_num, length(srrc_input));
plot(t(plot_idx)*1e6, srrc_input(plot_idx), 'b-', 'LineWidth', 1.5);
hold on;
plot(t(plot_idx)*1e6, srrc_output(plot_idx), 'r-', 'LineWidth', 1.5);
% 添加光标线标注码元宽度
symbol_start = sample_num/2;
symbol_end = 3*sample_num/2;
line([t(symbol_start)*1e6, t(symbol_start)*1e6], [-2, 2], 'Color', 'k', 'LineStyle', '--', 'LineWidth', 1);
line([t(symbol_end)*1e6, t(symbol_end)*1e6], [-2, 2], 'Color', 'k', 'LineStyle', '--', 'LineWidth', 1);
text(t(2*sample_num)*1e6, 1.5, sprintf('码元宽度: %.1f\\mus', (t(symbol_end)-t(symbol_start))*1e6), ...
'HorizontalAlignment', 'center', 'BackgroundColor', 'white');
title('SRRC滤波器输入(蓝)输出(红)信号');
xlabel('时间 (\mus)');
ylabel('幅度');
legend('输入', '输出', 'Location', 'best');
grid on;
% 4. 数字源码与已调信号波形(两光标线标注码元宽度)
subplot(3,4,4);
yyaxis left
stem(1:min(20, length(dataBit)), dataBit(1:min(20, length(dataBit))), 'filled', 'MarkerSize', 4);
ylabel('数字源码');
axis([0 21 -0.5 1.5]);
yyaxis right
plot_idx2 = 1:min(2*sample_num, length(modSignal));
plot(t(plot_idx2)*1e6, modSignal(plot_idx2), 'r-', 'LineWidth', 1.5);
ylabel('已调信号');
% 添加光标线标注码元宽度
line([t(sample_num/2)*1e6, t(sample_num/2)*1e6], [-1.5, 1.5], 'Color', 'k', 'LineStyle', '--', 'LineWidth', 1);
line([t(3*sample_num/2)*1e6, t(3*sample_num/2)*1e6], [-1.5, 1.5], 'Color', 'k', 'LineStyle', '--', 'LineWidth', 1);
text(t(sample_num)*1e6, 1.2, sprintf('码元宽度: %.1f\\mus', (t(3*sample_num/2)-t(sample_num/2))*1e6), ...
'HorizontalAlignment', 'center', 'BackgroundColor', 'white');
title('数字源码与已调信号');
xlabel('时间 (\mus)');
grid on;
% 5. 已调信号频谱
subplot(3,4,5);
NFFT = 2^nextpow2(length(modSignal));
f = (-NFFT/2:NFFT/2-1) * (fs/NFFT);
Y = fftshift(fft(modSignal, NFFT));
plot(f/1e6, abs(Y));
title('已调信号频谱');
xlabel('频率 (MHz)');
ylabel('幅度');
grid on;
% 6. SRRC滤波器频率响应
subplot(3,4,6);
[H, w] = freqz(srrc_filter, 1, 1024);
freq_axis = w/pi * (fs/2) / 1e6;
plot(freq_axis, 20*log10(abs(H)), 'LineWidth', 1.5);
title('SRRC滤波器频率响应');
xlabel('频率 (MHz)');
ylabel('幅度 (dB)');
grid on;
% 7. 星座图
subplot(3,4,7);
symbolPoints = I_filtered(sample_num/2:sample_num:end);
if length(symbolPoints) > 100
symbolPoints = symbolPoints(1:100);
end
plot(real(symbolPoints), imag(symbolPoints), 'o', 'MarkerSize', 3);
grid on;
title('解调信号星座图');
xlabel('同相分量');
ylabel('正交分量');
axis equal;
% 8. 误码率曲线
subplot(3,4,8);
SNR_range = 0:2:12; % 减少范围以避免计算时间过长
BER_results = zeros(size(SNR_range));
for i = 1:length(SNR_range)
snr_val = SNR_range(i);
modSignal_noisy_temp = awgn(modSignal, snr_val, 'measured');
demodBit_temp = DBPSK_Demodulation_SRRC(modSignal_noisy_temp, Fc, sample_num, len_symbol, t, fs, Rb, srrc_filter, span);
% 确保长度匹配
if length(demodBit_temp) >= length(dataBit)
demodBit_temp = demodBit_temp(1:length(dataBit));
else
demodBit_temp = [demodBit_temp, zeros(1, length(dataBit) - length(demodBit_temp))];
end
errorNum_temp = sum(xor(dataBit, demodBit_temp));
BER_results(i) = errorNum_temp / length(dataBit);
end
semilogy(SNR_range, BER_results, 'bo-', 'LineWidth', 2);
hold on;
theory_BER = 0.5 * erfc(sqrt(10.^(SNR_range/10)));
semilogy(SNR_range, theory_BER, 'r--', 'LineWidth', 2);
grid on;
title('DBPSK系统误码率曲线');
xlabel('信噪比 (dB)');
ylabel('误码率');
legend('仿真', '理论', 'Location', 'southwest');
% 9. PCM编码过程显示
subplot(3,4,9);
plot((0:length(sampleData)-1)/Rb, sampleData, 'b-o', 'MarkerSize', 2);
hold on;
stairs((0:length(pcm_decoded)-1)/Rb, pcm_decoded, 'r-', 'LineWidth', 1.5);
title('PCM编码前后信号');
xlabel('时间 (s)');
ylabel('幅度');
legend('原始抽样', 'PCM解码', 'Location', 'best');
grid on;
% 10. 差分编码过程
subplot(3,4,10);
stem(1:min(20, length(dataBit)), dataBit(1:min(20, length(dataBit))), 'b', 'filled', 'MarkerSize', 3);
hold on;
stem(1:min(20, length(diffCode)), diffCode(1:min(20, length(diffCode))), 'r', 'filled', 'MarkerSize', 3);
title('差分编码过程');
xlabel('比特索引');
ylabel('幅度');
legend('原始数据', '差分编码', 'Location', 'best');
grid on;
axis([0 21 -0.5 1.5]);
% 11. 解调过程各点波形
subplot(3,4,11);
plot_idx3 = 1:min(5*sample_num, length(I_filtered));
plot(t(plot_idx3)*1e6, I_filtered(plot_idx3), 'b-', 'LineWidth', 1.5);
hold on;
% 标记抽样点
sample_points = sample_num/2:sample_num:length(I_filtered);
valid_samples = sample_points(sample_points <= length(I_filtered) & sample_points <= max(plot_idx3));
plot(t(valid_samples)*1e6, I_filtered(valid_samples), 'ro', 'MarkerSize', 4, 'LineWidth', 2);
title('解调滤波后信号');
xlabel('时间 (\mus)');
ylabel('幅度');
legend('滤波信号', '抽样点', 'Location', 'best');
grid on;
% 12. 信号功率谱密度对比
subplot(3,4,12);
[Pxx_input, F_input] = pwelch(input_analog, [], [], [], Fs_audio);
[Pxx_output, F_output] = pwelch(output_analog, [], [], [], Fs_audio);
plot(F_input/1000, 10*log10(Pxx_input), 'b-', 'LineWidth', 1.5);
hold on;
plot(F_output/1000, 10*log10(Pxx_output), 'r--', 'LineWidth', 1.5);
title('输入输出信号功率谱密度');
xlabel('频率 (kHz)');
ylabel('功率谱密度 (dB/Hz)');
legend('输入', '输出', 'Location', 'best');
grid on;
修改上面的代码,使其调用下面的代码
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FileName : DA_OUT.m
% Description : DA输出函数。功能:用于将PC产生数据输出到DA,用示波器观察。
% Function List :
% [] = DA_OUT(CH1_data,CH2_data,divFreq,dataNum,isGain)
% Parameter List:
% Output Parameter
% Input Parameter
% CH1_data 信源数据
% CH1_data 载波频率
% divFreq 分频值
% dataNum 数据长度
% isGain 增益开关,0表示不对值放大,1表示对值放大
% History
% 1. Date : 2018-09-18
% Author : tony.liu
% Version :1.1
% Modification: 初稿
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [] = DA_OUT(CH1_data,CH2_data,divFreq,dataNum,isGain)
%% dataNum数据长度,由于硬件ROM大小限制,设计要求dataNum范围100~30720
ROM_MAX_LEN=30720;
ROM_MIN_LEN=100;
if dataNum>ROM_MAX_LEN
disp('数据长度,超过长度限制范围100~30720');
dataNum=ROM_MAX_LEN;
end
if dataNum<ROM_MIN_LEN
disp('数据长度,超过小于限制范围100~30720');
dataNum=ROM_MIN_LEN;
end
%% divFreq取值范围0~1024
if (divFreq>1024)||(divFreq<0)
disp('fs采样率参数配置超过允许范围');
divFreq=0;
end
%% 处理使CH1_data和CH2_data 数据长度和dataNum值一致,
%% (如果处理前CH1_data和CH2_data 数据长度“小于”dataNum值,则补0,这样方便观察数据起始头)
%% (如果处理前CH1_data和CH2_data 数据长度“等于”dataNum值,则数据显示连续)
%% (如果处理前CH1_data和CH2_data 数据长度“大于”dataNum值,则截取有效长度dataNum)
temp_data=zeros(1,30720);
CH1_data_temp= [CH1_data ,temp_data];
CH2_data_temp= [CH2_data ,temp_data];
CH1_out_data=CH1_data_temp(1,1:dataNum);
CH2_out_data=CH2_data_temp(1,1:dataNum);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
test_Set_router = uint8(hex2dec({'00','00','99','bb', '68','00','00','06', '00','00','00','00', '00','00','00','00', '00','00','00','00'})); %06 DA 网口发送信号
%%%%%%%%%%%%%%%%%%%%%
%%发送数据命令参数
divFreqL=mod(divFreq,256);
divFreqH=(divFreq-divFreqL)/256;
divFreqL=dec2hex(divFreqL);
divFreqH=dec2hex(divFreqH);
dataNumL=mod(dataNum,256);
dataNumH=(dataNum-dataNumL)/256;
dataNumL=dec2hex(dataNumL);
dataNumH=dec2hex(dataNumH);
test_tx_command = uint8(hex2dec({'00','00','99','bb', '65','0A','03','ff', divFreqH,divFreqL,dataNumH,dataNumL, '00','00','00','00', '00','00','00','00'})); %发射参数
test_Send_IQ = uint8(hex2dec({'00','00','99','bb', '64','00','00','00', '00','00','00','00', '00','00','00','00', '00','00','00','00'})); %发送启动命令
SAMPLE_LENGTH = dataNum;
SEND_PACKET_LENGTH = 180;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%创建配置UDP对象,并打开
udp_obj = udp('192.168.1.121',13345,'LocalHost','192.168.1.21','LocalPort',12345,'TimeOut',100,'OutputBufferSize',61440,'InputBufferSize',61440*10);
fopen(udp_obj);
dataIQ = zeros(1,SAMPLE_LENGTH*2);
dataIQ(1,1:2:end) = CH1_out_data(1,:);
dataIQ(1,2:2:end) = CH2_out_data(1,:);
if isGain==1
dataIQ = dataIQ.*(2047/max(abs(dataIQ))); %放大峰值至2000,接近理论峰值2047
end
dataIQ = fix(dataIQ); %浮点数强制取整
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%防止溢出,并对负数进行补码操作.将有符号12位数据,转化为无符号12位数据
%eg -2048~2047,转化为0~4095
% 0~2047 不变
% -2048~-1 对应转为 2048~4095
for n = 1 : SAMPLE_LENGTH*2
if dataIQ(n) > 2047
dataIQ(n) = 2047;
elseif dataIQ(n) < 0
dataIQ(n) = 4096 + dataIQ(n);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%按接口定义排列比特序
%I路:b11~b0 空4bits
dataIQ(1,1:2:SAMPLE_LENGTH*2-1) = dataIQ(1,1:2:SAMPLE_LENGTH*2).*16;
%Q路:b7~b0 空4bits b11~b8
dataIQ(1,2:2:SAMPLE_LENGTH*2) = fix(dataIQ(1,2:2:SAMPLE_LENGTH*2)./256) + rem(dataIQ(1,2:2:SAMPLE_LENGTH*2),256).*256;
dataIQ = uint16(dataIQ);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%发送命令参数
fwrite(udp_obj, test_Set_router, 'uint8');
fwrite(udp_obj, test_tx_command, 'uint8');
fwrite(udp_obj, test_Send_IQ, 'uint8');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%发送数据
if SAMPLE_LENGTH*2<SEND_PACKET_LENGTH
fwrite(udp_obj, dataIQ(1,1:(SAMPLE_LENGTH*2)), 'uint16');
else
for pn = 1:fix(SAMPLE_LENGTH*2/SEND_PACKET_LENGTH)
fwrite(udp_obj, dataIQ(1,((pn-1)*SEND_PACKET_LENGTH+1) : (pn*SEND_PACKET_LENGTH)), 'uint16');
end
fwrite(udp_obj, dataIQ(1,(pn*SEND_PACKET_LENGTH+1 ): (SAMPLE_LENGTH*2)),'uint16');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%关闭UDP对象
echoudp('off')
fclose(udp_obj);
delete(udp_obj);
clear udp_obj;
end