GNSS接收机设计:(4) 同步

本文详细阐述了卫星导航信号中的位同步和帧同步原理,包括伪距计算、码环定位、帧同步码的搜索和判断,以及使用MATLAB实现的帧同步过程。重点介绍了如何通过预导序列(Preamble)进行帧同步,并处理可能的相位模糊和错误检测问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、位同步&帧同步原理

伪距=信号收发时间差×光速。得到伪距,最重要是找到发送时间,故而需要同步。

码环能找到当前信号在一个CA码周期中的位置,但是一个数据比特有20个CA码,所以还必须要确定它是在第几个码周期中——位同步。

若相干积分1ms,也即是输出代表比特电平宽1ms(其实就是每个CA码为1ms),但正常的数据是1bit宽度为20ms,故要把20个电平(CA码)合成1个比特,因此要找到哪20个是一组——位同步。

【知道20个一组≈知道频率;不知道哪里开始数20个≈不知道相位】

1. 帧同步原理

根据卫星导航电文格式,每个子帧的第一个字是遥测字,而遥测字的首8个比特是值固定为10001011的同步码(Preamble),只需要搜索数据找到Preamble即可将比特正确拼接为字,即实现帧同步。载波环解调得到的数据可能存在180°相位模糊,所以实际上只要搜索到10001011或者其反相就可以。

但是因为导航数据比特有可能恰好随机拼成预导序列,为了避免错判,在找到preamble后还需要再进行奇偶校验来进一步确认。(实际上这里还可以继续加第三第四重保险,不过现在暂时不考虑这么复杂的情况)

2. 帧同步代码

帧同步主要通过findPreamble.m来实现:

(1)准备工作

设定搜索的起始偏移量,说明搜索开始的地方是哪里。创建矩阵firstSubFrame 用于存储每个通道找到的第一个子帧位置索引(因为子帧的开头是遥测字,遥测字的开头是同步码,所以找到同步码=找到了遥测字=找到了子帧)。

定义Preamble的比特值= [1 -1 -1 -1 1 -1 1 1];然后将它扩展为与样本速率匹配的长度,也就是复制20份,以便进行相关运算。

preamble_ms = kron(preamble_bits, ones(1, 20));

(这里最初以为是把preamble整体重复20次,后来分析应该是将preamble的每个比特值重复20次,之后下一个值再重复20次,例如[1 , -1]就变成[1,1,1,1,1…,-1,-1,-1,-1…])

解释:preamble表面上是8个±1数值,但其实每个数都是1个比特,而一个比特包含20个数据单元,也就是20ms,所以对于一个“1”,它应该扩展成“111111111111...”,才能和导航电文数据匹配上,进行相关操作。

(2)循环搜索同步码

对于可以处理的通道:

从searchStartOffset位置开始,对通道的I_P(即长度为36000ms的导航数据-这里在跟踪中初始化是zeros(1,settings.msToProcess)而msToProcess=36000)进行判决,阈值为0,输出±1的电平值;

计算导航数据和preamble序列的互相关值,来找同步码的位置,对于相关结果中大于阈值的位置,将其存储在index变量中。

(3)拼接

对于每一个找到的位置, 首先计算它与所有找到的位置的偏移,如果偏移为6000,表示在当前位置之前有一个完整的子帧,也就是先把一看就不对的结果排除掉。【解释:每个子帧前8比特是preamble,所以如果找到的位置正确的话,两个位置之间应该正好差一个子帧,也就是6000才对】 然后需要取遥测字和交接字以及上1子帧最后两个比特用于奇偶校验。

6000的解释:1子帧=10字,1字=30比特,1比特=20数据单元,所以1个子帧=6000个1ms数据单元

对于取出来的这些数据单元,先将其拼成20行62列的矩阵,再对每列进行求和,得到的向量中每个元素就是一个比特的值,因此得到62比特。

矩阵尺寸的解释:根据上面列出的换算法则,遥测+交接2个字 = 2*30*20 = 1200个数据单位,最后2个比特 = 2*20 = 40,1200+40=1240=20*62

然后进行判决,阈值为0,就得到电平为±1的一系列比特值。

最后检查子帧的导航消息的校验和是否正确,需要调用navPartyChk函数。如果正确,说明找对了, 就将index信息存储到firstSubFrame中,作为子帧起始点。如果无法找到有效的同步码,需要从activeChnList列表中移除当前通道,并提示错误信息。

二、MATLAB实现

下面的代码是帧同步:

searchStartOffset = 0;  %搜索起始偏移量,说明搜索开始的地方是哪里
% 创建矩阵 用于存储每个通道找到的第一个子帧
firstSubFrame = zeros(1, settings.numberOfChannels);

% 定义Preamble的比特值
preamble_bits = [1 -1 -1 -1 1 -1 1 1];
%将预导序列扩展为与样本速率匹配的长度,以便进行相关运算。
preamble_ms = kron(preamble_bits, ones(1, 20));
%找到可以处理的通道号,也就是在前面已经成功捕获和跟踪的通道
activeChnList = find([trackResults.status] ~= '-');

for channelNr = activeChnList  %开始循环

    % 从searchStartOffset位置开始,取出通道的I_P数据。
    bits = trackResults(channelNr).I_P(1 + searchStartOffset : end);

    % 这两个就是个判决的过程,阈值为0
    bits(bits > 0)  =  1;
    bits(bits <= 0) = -1;

    % 计算位移相关性,找到预导序列的位置,因为相关性反映相似程度
    tlmXcorrResult = xcorr(bits, preamble_ms);

    % 清除索引变量
    clear index
    clear index2
    % 计算相关性结果的长度:
    xcorrLength = (length(tlmXcorrResult) +  1) /2;

    % 找到相关性结果中大于阈值的位置,并将其存储在index变量中:
    index = find(...
        abs(tlmXcorrResult(xcorrLength : xcorrLength * 2 - 1)) > 153)' + ...
        searchStartOffset;

    % 对于找到的位置,执行下面的循环
    for i = 1:size(index) 

        
        index2 = index - index(i);   %:计算与当前位置的偏移

    % 如果存在一个偏移为6000的位置(表示找到了一个完整的子帧)
        if (~isempty(find(index2 == 6000)))  
    % 从信号中提取完整子帧的数据:
            bits = trackResults(channelNr).I_P(index(i)-40 : ...
                                               index(i) + 20 * 60 -1)';
    % 将数据重新形状为20行,每行包含一个比特:
            bits = reshape(bits, 20, (size(bits, 1) / 20));
            bits = sum(bits); % 对每列进行求和,以得到每个比特的值

        % 判决:
            bits(bits > 0)  = 1;
            bits(bits <= 0) = -1;

    % 检查子帧的导航消息的校验和是否正确:
            if (navPartyChk(bits(1:32)) ~= 0) && ...
               (navPartyChk(bits(31:62)) ~= 0) 
                
            % 将找到的第一个子帧的索引存储到firstSubFrame中
                firstSubFrame(channelNr) = index(i);
                break;    
            end
            
        end 
    end 

% 如果无法找到有效的预导序列,从活跃通道列表中移除该通道,并打印提示信息
    if firstSubFrame(channelNr) == 0
        activeChnList = setdiff(activeChnList, channelNr);
        
        disp(['Could not find valid preambles in channel ', ...
                                                  num2str(channelNr),'!']);
    end
    
end 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值