======= 文本到FSK调制转换 =======
[1] 文本文件读取成功
├─文件名: input_text.txt
├─文件大小: 276 字节
└─起始内容: "阿里健�..."
[2] 原始数据CRC-16/KERMIT计算完成
├─校验值: 0xC0C1
└─校验字节: [0xC0, 0xC1]
[3] 数据块构建完成
├─原始数据长度: 276 字节
├─CRC16长度: 2 字节
└─总数据长度: 278 字节
[4] FEC卷积编码完成
├─输入比特数: 2230 bits (含6尾比特)
├─输出比特数: 4460 bits
├─补齐比特数: 4 bits
└─FEC字节长度: 558 bytes
[5] 帧头构建完成
├─魔术头: 0xABCDEFFE
├─数据长度: 278 bytes [0x01 0x16]
└─FEC长度: 558 bytes [0x02 0x2E]
[6] 帧头CRC16计算完成
├─校验值: 0x4095
└─校验字节: [0x40, 0x95]
[7] 完整帧组装完成
├─同步字: 2 bytes [0x55 0xAA]
├─帧头: 8 bytes
├─帧头CRC: 2 bytes [0x40 0x95]
├─FEC数据: 558 bytes
└─总帧长度: 570 bytes
错误使用 *
整数只能与同类的整数或双精度标量值组合使用。
出错 FSK_TX (第 193 行)
segment = cos(2*pi*freq*t + phase);
%% 文本到QPSK调制转换
clear all; close all; clc;
fprintf('======= 文本到FSK调制转换 =======\n');
% ===== 1. 读取文本文件 =====
filename = 'input_text.txt';
fid = fopen(filename, 'r', 'n', 'UTF-8');
if fid == -1
error('无法打开文件: %s', filename);
end
rawData = fread(fid, '*uint8')'; % 读取UTF-8编码字节
fclose(fid);
dataLength = length(rawData);
fprintf('[1] 文本文件读取成功\n');
fprintf(' ├─文件名: %s\n', filename);
fprintf(' ├─文件大小: %d 字节\n', dataLength);
fprintf(' └─起始内容: "%s..."\n', native2unicode(rawData(1:min(10,end))));
% ===== 2. 计算原始数据CRC16 (CRC-16/KERMIT) =====
function crc = calculateCRC16_KERMIT(data)
crc = uint16(0);
poly = uint16(hex2dec('1021'));
for i = 1:length(data)
byte = uint8(data(i));
reversed_byte = uint8(0);
for b = 1:8
reversed_byte = bitshift(reversed_byte, 1);
if bitand(byte, 1)
reversed_byte = bitor(reversed_byte, 1);
end
byte = bitshift(byte, -1);
end
crc = bitxor(crc, bitshift(uint16(reversed_byte), 8));
for j = 1:8
if bitand(crc, hex2dec('8000'))
crc = bitxor(bitshift(crc, 1), poly);
else
crc = bitshift(crc, 1);
end
crc = bitand(crc, hex2dec('FFFF'));
end
end
reversed_crc = uint16(0);
tmp = crc;
for b = 0:15
if bitand(tmp, 1)
reversed_crc = bitor(reversed_crc, bitshift(1, 15-b));
end
tmp = bitshift(tmp, -1);
end
crc = reversed_crc;
end
crcValue = calculateCRC16_KERMIT(rawData);
crcBytes = [bitand(bitshift(crcValue, -8), 255), bitand(crcValue, 255)];
fprintf('[2] 原始数据CRC-16/KERMIT计算完成\n');
fprintf(' ├─校验值: 0x%04X\n', crcValue);
fprintf(' └─校验字节: [0x%02X, 0x%02X]\n', crcBytes(1), crcBytes(2));
% ===== 3. 构建数据块 (原始数据 + CRC16) =====
dataBlock = [rawData, crcBytes];
dataBlockLength = length(dataBlock);
fprintf('[3] 数据块构建完成\n');
fprintf(' ├─原始数据长度: %d 字节\n', dataLength);
fprintf(' ├─CRC16长度: 2 字节\n');
fprintf(' └─总数据长度: %d 字节\n', dataBlockLength);
% ===== 4. FEC卷积编码 =====
trellis = poly2trellis(7, [133 171]); % 约束长度7
inputBits = de2bi(dataBlock, 8, 'left-msb')';
inputBits = inputBits(:)'; % 展平为行向量
originalBits = length(inputBits);
% 添加6比特尾零
inputBitsWithTail = [inputBits, zeros(1, 6)]; % 添加6比特尾零
tailBits = 6; % 记录尾比特数
% 卷积编码(码率1/2)
encodedBits = convenc(inputBitsWithTail, trellis);
encodedBitLength = length(encodedBits);
% 字节对齐 (补零至8的倍数)
paddingBits = mod(8 - mod(encodedBitLength, 8), 8);
if paddingBits > 0
encodedBits = [encodedBits, zeros(1, paddingBits)];
end
fecByteLength = length(encodedBits) / 8; % FEC字节长度
fprintf('[4] FEC卷积编码完成\n');
fprintf(' ├─输入比特数: %d bits (含%d尾比特)\n', ...
length(inputBitsWithTail), tailBits);
fprintf(' ├─输出比特数: %d bits\n', encodedBitLength);
fprintf(' ├─补齐比特数: %d bits\n', paddingBits);
fprintf(' └─FEC字节长度: %d bytes\n', fecByteLength);
% ===== 5. 构建帧头 =====
magicHeader = [hex2dec('AB'), hex2dec('CD'), hex2dec('EF'), hex2dec('FE')];
% 数据长度字段 (原始数据长度 + CRC16长度)
dataLenHigh = floor(dataBlockLength / 256);
dataLenLow = mod(dataBlockLength, 256);
% FEC长度字段
fecLenHigh = floor(fecByteLength / 256);
fecLenLow = mod(fecByteLength, 256);
% 组合帧头 (8字节)
headerBytes = [magicHeader, dataLenHigh, dataLenLow, fecLenHigh, fecLenLow];
fprintf('[5] 帧头构建完成\n');
fprintf(' ├─魔术头: 0x%02X%02X%02X%02X\n', ...
magicHeader(1), magicHeader(2), magicHeader(3), magicHeader(4));
fprintf(' ├─数据长度: %d bytes [0x%02X 0x%02X]\n', ...
dataBlockLength, dataLenHigh, dataLenLow);
fprintf(' └─FEC长度: %d bytes [0x%02X 0x%02X]\n', ...
fecByteLength, fecLenHigh, fecLenLow);
% ===== 6. 计算帧头CRC16 =====
headerCRC = calculateCRC16_KERMIT(headerBytes);
headerCRCBytes = [bitand(bitshift(headerCRC, -8), 255), bitand(headerCRC, 255)];
fprintf('[6] 帧头CRC16计算完成\n');
fprintf(' ├─校验值: 0x%04X\n', headerCRC);
fprintf(' └─校验字节: [0x%02X, 0x%02X]\n', headerCRCBytes(1), headerCRCBytes(2));
% ===== 7. 组装完整帧 =====
syncWord = [hex2dec('55'), hex2dec('AA')]; % 同步字段0x55AA
% 将FEC比特流转换为字节
fecBytes = zeros(1, fecByteLength);
for i = 1:fecByteLength
startIdx = (i-1)*8 + 1;
endIdx = i*8;
fecBytes(i) = bi2de(encodedBits(startIdx:endIdx), 'left-msb');
end
% 完整帧结构
fullFrame = [syncWord, headerBytes, headerCRCBytes, fecBytes];
frameLength = length(fullFrame);
% 打印完整帧结构
fprintf('[7] 完整帧组装完成\n');
fprintf(' ├─同步字: 2 bytes [0x55 0xAA]\n');
fprintf(' ├─帧头: 8 bytes\n');
fprintf(' ├─帧头CRC: 2 bytes [0x%02X 0x%02X]\n', headerCRCBytes(1), headerCRCBytes(2));
fprintf(' ├─FEC数据: %d bytes\n', fecByteLength);
fprintf(' └─总帧长度: %d bytes\n', frameLength);
% ===== 8. FSK调制 (实数信号) =====
% 转换为比特流
frameBits = de2bi(fullFrame, 8, 'left-msb')';
frameBits = frameBits(:)';
totalBits = length(frameBits);
% FSK参数设置
f0 = 1000; % 比特0的频率 (Hz)
f1 = 2000; % 比特1的频率 (Hz)
samplesPerSymbol = 10; % 每个符号的采样点数
fs = 10000; % 采样率 (Hz)
% % 计算总采样点数
% totalSamples = totalBits * samplesPerSymbol;
% signal = zeros(1, totalSamples); % 初始化实信号向量
%
% % 一个符号的时间向量
% t = (0:samplesPerSymbol-1) / fs;
%
% % 生成FSK信号
% for i = 1:totalBits
% if frameBits(i) == 0
% segment = cos(2*pi*f0*t);
% else
% segment = cos(2*pi*f1*t);
% end
% startIdx = (i-1)*samplesPerSymbol + 1;
% endIdx = i * samplesPerSymbol;
% signal(startIdx:endIdx) = segment;
% end
% 修改后的FSK调制代码
totalSamples = totalBits * samplesPerSymbol;
phase = 0; % 初始化相位
signal = zeros(1, totalSamples);
for i = 1:totalBits
% 计算当前符号频率
freq = frameBits(i) * (f1 - f0) + f0; % 比特0:f0, 比特1:f1
% 生成连续相位波形
t = (0:samplesPerSymbol-1) / fs;
segment = cos(2*pi*freq*t + phase);
% 更新相位 (保持连续)
phase = mod(2*pi*freq*samplesPerSymbol/fs + phase, 2*pi);
% 存入信号
startIdx = (i-1)*samplesPerSymbol + 1;
endIdx = i * samplesPerSymbol;
signal(startIdx:endIdx) = segment;
end
% ===== 9. 保存实数信号 =====
outputFile = 'FSK_newframe.dat';
fid = fopen(outputFile, 'wb');
if fid == -1
error('无法创建文件: %s', outputFile);
end
fwrite(fid, signal, 'float32'); % 只保存实数部分
fclose(fid);
numSamples = length(signal);
fileSizeBytes = numSamples * 4; % 4字节/采样点 (float32)
plot(signal(1:200));
title('FSK波形');
% 检查符号边界是否平滑
pspectrum(signal, fs, 'FrequencyResolution', 10)
% 观察主瓣宽度和旁瓣抑制
fprintf('\n[8] FSK调制完成 (实数信号)\n');
fprintf(' ├─比特0频率: %d Hz\n', f0);
fprintf(' ├─比特1频率: %d Hz\n', f1);
fprintf(' ├─符号率: %d baud\n', fs/samplesPerSymbol);
fprintf(' ├─采样率: %d Hz\n', fs);
fprintf(' └─每符号采样数: %d\n', samplesPerSymbol);
fprintf('\n[9] 处理完成!\n');
fprintf('=======================================\n');
fprintf('输出文件: %s\n', outputFile);
fprintf('采样点数: %d\n', numSamples);
fprintf('文件大小: %.8f KB\n', fileSizeBytes / 1024);
disp('==============');