%% 1. 读取文本文件并进行UTF-8编码
text = fileread('input_text.txt'); % 读取文本文件
rawData = unicode2native(text, 'UTF-8'); % 转换为UTF-8字节序列
disp(['原始数据长度: ', num2str(length(rawData)), ' 字节']);
%% 2. 计算CRC-CCITT (0xA001)校验码
polynomial = hex2dec('A001'); % CRC-CCITT多项式
initialValue = hex2dec('FFFF'); % 初始值
crc = uint16(initialValue);
% 高效CRC计算
for i = 1:length(rawData)
crc = bitxor(crc, uint16(rawData(i)));
for j = 1:8
carry = bitand(crc, 1);
crc = bitshift(crc, -1);
if carry
crc = bitxor(crc, polynomial);
end
end
end
% 附加CRC到原始数据 (大端序)
crcHigh = bitand(bitshift(crc, -8), 255);
crcLow = bitand(crc, 255);
dataWithCRC = [rawData, crcHigh, crcLow];
disp(['添加CRC后数据长度: ', num2str(length(dataWithCRC)), ' 字节']);
%% 3. FEC卷积编码 (码率1/2)
trellis = poly2trellis(7, [171, 133]); % 标准卷积码生成多项式
% 转换为比特流
bitData = de2bi(dataWithCRC, 8, 'left-msb')'; % 按字节转换为比特
bitData = bitData(:); % 转换为列向量
tailBits = zeros(6, 1); % 6个尾比特清零状态
bitData = [bitData; tailBits]; % 添加尾比特
% 卷积编码
encodedBits = convenc(bitData, trellis);
disp(['编码后比特数: ', num2str(length(encodedBits))]);
%% 4. 构建帧头
syncWord = [hex2dec('55'), hex2dec('AA')]; % 同步字段0x55AA
dataLength = length(rawData); % 原始数据长度
% 长度字段(大端序)
lenHigh = bitand(bitshift(dataLength, -8), 255); % 高字节
lenLow = bitand(dataLength, 255); % 低字节
frameHeader = [syncWord, lenHigh, lenLow];
disp(['帧头: ', num2str(frameHeader)]);
%% 5. 组装完整帧 (含比特填充)
% 添加填充比特使总比特数为8的倍数
numBits = length(encodedBits);
numPadding = mod(8 - mod(numBits, 8), 8); % 计算填充比特数
paddedBits = [encodedBits; zeros(numPadding, 1)]; % 填充0比特
% 转换为字节序列
encodedBytes = bi2de(reshape(paddedBits, 8, [])', 'left-msb')';
% 组装完整帧
fullFrame = [frameHeader, encodedBytes];
disp(['完整帧长度: ', num2str(length(fullFrame)), ' 字节']);
%% 6. QPSK调制
% 将字节流转换为比特流
frameBits = de2bi(fullFrame, 8, 'left-msb')';
frameBits = frameBits(:);
frameBits = double(frameBits); % 转换为双精度
% 确保比特数为偶数
if mod(length(frameBits), 2) ~= 0
frameBits = [frameBits; 0]; % 补零
disp('注意: 比特流补零以保证偶数长度');
end
% 标准Gray编码映射
I_bits = frameBits(1:2:end); % 奇数位 (I路)
Q_bits = frameBits(2:2:end); % 偶数位 (Q路)
% 双极性映射 (0->+1, 1->-1)
I = 1 - 2 * I_bits;
Q = 1 - 2 * Q_bits;
% 功率归一化 (保证符号能量为1)
symbols = (I + 1j * Q) / sqrt(2);
disp(['QPSK符号数: ', num2str(length(symbols))]);
%% 7. 保存IQ数据
iqData = reshape([real(symbols); imag(symbols)], 1, []);
fid = fopen('QPSK_TX.dat', 'wb');
fwrite(fid, iqData, 'float'); % 存储为浮点数
fclose(fid);
disp('IQ数据已保存至 QPSK_TX.dat');
%% 8. 绘制信号
% 星座图
figure('Name', 'QPSK调制信号', 'Position', [100, 100, 1200, 800]);
subplot(2,2,1);
plot(symbols, '.');
axis([-1.5 1.5 -1.5 1.5]); axis square;
title('QPSK星座图');
xlabel('同相分量'); ylabel('正交分量'); grid on;
hold on;
% 绘制理想星座点
idealPoints = [(1+1j), (-1+1j), (1-1j), (-1-1j)] / sqrt(2);
plot(real(idealPoints), imag(idealPoints), 'ro', 'MarkerSize', 10, 'LineWidth', 1.5);
legend('调制符号', '理想位置');
% 前100个比特
subplot(2,2,2);
stem(frameBits(1:min(100, end)));
title('前100个传输比特');
xlabel('比特索引'); ylabel('幅值'); grid on;
% IQ信号时域波形
subplot(2,2,[3,4]);
t = 1:length(symbols);
plot(t, real(symbols), 'b', 'LineWidth', 1.5); hold on;
plot(t, imag(symbols), 'r', 'LineWidth', 1.5);
title('IQ信号时域波形');
xlabel('符号索引'); ylabel('幅值');
legend('I路信号', 'Q路信号'); grid on;
% 保存图像
saveas(gcf, 'QPSK_TX_Signals.png');
disp('信号图像已保存至 QPSK_TX_Signals.png');
这是我发送端的流程,现在我需要逆向恢复出文本,并观察是否正确恢复
最新发布