信道编码译码及MATLAB仿真

文章目录

  • 前言
  • 一、什么是信道编码?
  • 二、信道编码的基本逻辑—冗余数据
    • 1、奇偶检验码
    • 2、重复码
  • 三、编码率
  • 四、4G 和 5G 的信道编码
    • 1、卷积码
    • 2、维特比译码(Viterbi)—— 概率译码
    • 3、LTE 的咬尾卷积码
    • 4、LTE 的 turbo 码
  • 五、MATLAB 仿真
    • 1、ploy2trellis 函数
      • ①、无负反馈的函数调用方法
      • ②、有负反馈的函数调用方法
    • 2、convenc() 函数
    • 3、vitdec() 函数
    • 4、MATLAB 仿真


前言

本文对数字通信技术中的信道编码及译码进行学习记录。

数字通信,就是把一切声音,图像,文字,都变成 0,1 这种二进制代码,这种转换过来的数据,我们可以称之为原始数据 bit 那么,这种原始的 bit,是否可以直接调制,转换成电磁波发送出去呢?答案是不可以,因为电磁波传输过程中,一定会存在于扰噪声,从而产生差错

下图为数字通信系统模型
在这里插入图片描述

数字通信系统模型

一、什么是信道编码?

首先引用书上的定义对信道编码进行一下讲解:

信道编码(Channel Coding)的作用是进行差错控制。数字信号在传输过程中会受到噪声等影响而发生差错。为了减小差错,信道编码器对传输的信息码元按一定的规则加入保护成分(监督码元),组成所谓“抗干扰编码”。接收端的信道译码器按相应的逆规则进行解码,从中发现错误或纠正错误,提高通信系统的可靠性。

下面我们举个例子形象描述一下。
假设,我们把 “你好” 这两个字转换成 0,1 代码,比如用 00 和 01 分别代表你和好,在我们发送 00 时,因干扰原因,导致我们发送的数据变成了 01,那么我们发送的信息本来应该是“你”,而被接收端识别成了“好”,如下图所示:
在这里插入图片描述
我们为了抗干扰,就需要增加一个步骤,来让我们的数据具备“一定程度上纠正干扰产生的差错的能力”,这个步骤就叫信道编码

二、信道编码的基本逻辑—冗余数据

在进行信道编码时,需要增加冗余数据来达到抗干扰的效果,以下图为例,在运输花瓶时,为避免花瓶运输路途中破碎,我们增加一个泡沫箱子,再打包后通过快递进行发送,这里面的泡沫箱子及顺丰快递箱子就可以类似于冗余数据。
在这里插入图片描述
我们这里列举一些常用的冗余数据。

1、奇偶检验码

原始数据 100101100

  • 奇校验:1001011001,校验位为 1,让 1 的总数变成奇数 5
  • 偶校验:1001011000,校验位为 0,让 1 的总数保持为偶数 4

增加的 1bit 位,为校验位,也就是冗余 bit

假设使用奇校验:1001011001

  • 传输过程中,错 1 位:1011011001,可以发现错误
  • 传输过程中,错 2 位:0011011001,发现不了错误

奇偶校验码只具备检错的能力,而不具备纠错能力

2、重复码

原始信息 1 或者 0
编码

  • 1 ——> 111
  • 0 ——> 000

当受到干扰导致错 1 位的时候,可以达到纠错的效果
在这里插入图片描述
当受到干扰导致错 2 位的时候,不可以达到纠错的效果
在这里插入图片描述

三、编码率

R = K / N R=K/N R=K/N
K K K:有用 bit 数据
N N N:编码后的 bit 数据

以前面的码为例,原始数据 100101100 共 9 bit,奇校验: 1001011001 共 10 bit,编码率 R = 9 / 10 = 0.9 R=9/10=0.9 R=9/10=0.9

重复码编码率 R = 1 / 3 R=1/3 R=1/3

  • 1/3 编码,表示 3 个编码后的比特中,包含 1 个有效比特;
  • 1/4 编码,表示 4 个编码后的比特中,包含 1 个有效比特;

编码率越低,包含的几余信息越多,纠错的能力越强,抗干扰的能力越强,传输的有效数据越小

四、4G 和 5G 的信道编码

4G 的信道编码包括卷积码和 turbo 码,5G 的信道编码包括 polar 和 ldpc 码。
在这里插入图片描述

1、卷积码

卷积码一般使用 n , K , N n,K,N nKN表示卷积编码器。

  • K K K 表示:输入的 K 个 bit (需要编码的原始 bit 数
  • n n n 表示:输出的 n n n 个 bit 编码后的 bit 数
  • 编码率 R = K / n R=K/n R=K/n
  • N N N:编码约束度 (实际上就是寄存器的个数)

卷积码将 K K K 个信息码元编为 n n n 个码元时,这 n n n 个码元不仅与当前的 K K K 个信息有关,也与前面的 N − 1 N-1 N1 段信息有关

参考下面的例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、维特比译码(Viterbi)—— 概率译码

维特比译码是根据接收序列,在网格图上找出一条与接收序列汉明距离最小的一种算法

汉明距离 Hamming:两个码组对应码位上具有不同二进制码元位数,为两码组的距离,简称码距
举个例子:
码 1:000
码 2:101
这两个码的码距为 2

下面我们继续举个例子:

  • 假设发送信息位是 1101
  • 编码后发送的序列为 111 110 010 100
  • 接收序列:111 010 010 110

注意:上面接收序列由于干扰导致出现了差错,现在我们看一下维特比译码是如何纠错的

每一种序列,都是网格图上的一条路径,0 用实线,1 用虚线
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因此,最后解码序列为:111 110 010 100,达到了纠错的效果

如果更复杂的,可能会出现有两个汉明距离,那么我们就会随机选作为它的译码,导致出现错了,这也就是为什么维特比译码叫做概率译码

3、LTE 的咬尾卷积码

在这里插入图片描述

4、LTE 的 turbo 码

在这里插入图片描述

五、MATLAB 仿真

在进行卷积编码的过程中,使用的函数是 convenc() 函数和 vitdec() 函数,同时需要 poly2trellis() 函数。

1、ploy2trellis 函数

先看 poly2trellis() 函数,用来生成卷积编码所需要的网表。ploy2trellis 函数有两种调用形式:

trellis=poly2trellis(ConstraintLength,CodeGenerator);
trellis=poly2trellis(ConstraintLength,CodeGenerator,...FeedbackConnection)

后者应用于有负反馈的情形

这个函数相当于定义了编码器中寄存器的结构,一般来说,在查看卷积编码的相关资料中都是类似于(2,1,3)这种结构,但是这个函数只需要两个参数:

  • ConstraintLength参数代表约束长度
  • CodeGenerator 代码生成器,指定为八进制数的KN矩阵、多项式字符向量的KN单元阵列或KN字符串阵列。CodeGenerator 为编码器的 K 个输入比特流中的每一个指定 N 个输出连接。

通俗理解这两个参数的含义和作用,首先约束长度决定了再译码时候的回溯深度的大小,根据不同的编码速率有不同的关系,技术文档中对此有介绍:
在这里插入图片描述
根据设定的 nk,和 L 值来确定,如对于 (2,1,3) 结构类型的卷积编码器,其中 rate = k/n = 1/2,对应第一种计算方式,那么回溯深度为 5*(L-1),结果为10,在进行译码的时候利用这个值对齐或者截断,这个在下面使用过程中会有。

回到函数本身,如设计 (2,1,7) 类型的编码器,可以用:

L = 7;
trellis = poly2trellis(L,[171 133]);

其中的第二个参数是 8 进制数据的表现形式,对应二进制为[111_1111, 101_1011]。可以理解为进入1bit数据,输出2bit数据,所以这个是2维的,同时这个7bit每一位代表寄存器的抽头,可以根据这个画出编码器的连接形式。

ploy2treliis 顾名思义:多项式 ploy 到网格图 trellis
卷积码的生成多项式可以由一系列多项式描述,我们将多项式转化为 trellis 结构,这种结构又可以作为 matalb 中线形卷积编码函数 convenc 和或者其解码(如 Viterbi 解码函数 vitdec)的输入。

①、无负反馈的函数调用方法

在这里插入图片描述

  • (3,2,4)卷积码,2 进 3 出,记忆长度(约束长度)L=max{4,3}+1=5
  • 输入数据共两个对应两行寄存器,第一行有 4 个移位寄存器,第二行 3 个,分别对应约束长度(4+1,3+1)=(5,4)。那么 ConstraintLength 就应该是[5,4]。
  • 第一位输出由第一行寄存器的“贡献”(生成序列)为(10,011)=23
  • 第二位输出由第一行寄存器的“贡献”(生成序列)为(11,101)=35
  • 第三位输出由第一行寄存器的“贡献”(生成序列)为(00,000)=0

==========================================================

  • 第一位输出由第二行寄存器的“贡献”(生成序列)为(0,000)=0
  • 第二位输出由第二行寄存器的“贡献”(生成序列)为( 0,101)=5
  • 第三位输出由第二行寄存器的“贡献”(生成序列)为( 1,011)=13

那么 CodeGenerator 就是[23,35,0; 0,5,13]

运行

trellis=poly2trellis([5,4],[23,35,0;0,05,13])

输出如下:

trellis = 包含以下字段的 struct:numInputSymbols: 4numOutputSymbols: 8numStates: 128nextStates: [128×4 double]outputs: [128×4 double]
  • numInputSymbols: 4
    • 输入状态数
    • 表示两路输入共有 4( 2 k 2^k 2k k k k为输入的路数)种状态分别为 00,01,10,11
  • numOutputSymbols: 8
    • 输出状态数
    • 表示输出共有 8( 2 n 2^n 2n n n n为输出的路数)种状态分别为 000,001,010,011,100,101,110,111
  • numStates: 128
    • 寄存器状态数
    • 当前状态数是 128( 2 7 2^7 27,7 是寄存器的总个数) 状态是 7 为二进制数
  • nextStates: [128x4 double]
    • 下一个状态
    • nextState 是 numStates-by-2k 的矩阵。他表示所有当前状态和当前输入组合所产生的下一状态。相当于马尔科夫链的状态转移表。行表示各种不同的当前状态,依次表示从全 0 状态到全 1 状态。
  • outputs: [128x4 double]
    • 输出
    • outputs 也是 numStates-by-2k 的矩阵。他表示所有当前状态和当前输入组合所产生的输出(8进制表示)。行和列的意义的nextState相同。
>> trellis.nextStates(1:5,:) ans =0    64     8    720    64     8    721    65     9    731    65     9    732    66    10    74

上面我们列出了nextStates的 1-5 行

  • (1,1)的元素表示在全 0 状态(0000000)时,输入 00 时的下一个状态还是全 0(0000000),即所有的寄存器的结果还都是 0;
  • (1,2)的元素表示在全 0 状态(0000000)时,输入 01 时的下一个状态是 64(1000000)
    ……
  • (2,1)的元素表示在 1 状态(0000001)时,输入为 00 时的下一个状态时全 0(0000000)
    ……

②、有负反馈的函数调用方法

考虑如下卷积码生成图
在这里插入图片描述

  • 同理,记忆长度(约束长度)L=4+1=5,生成
  • 第一位输出由寄存器的“贡献”(生成序列)为(11,111)=37
  • 第二位输出由寄存器的“贡献”(生成序列)为(11,011)=33
  • 那么 CodeGenerator 就是 [37,33]
  • 负反馈多项式为为(11,111)=37

运行

trellis = poly2trellis(5,[37 33],37)

输出如下:

trellis = 包含以下字段的 struct:numInputSymbols: 2numOutputSymbols: 4numStates: 16nextStates: [16×2 double]outputs: [16×2 double]

结构体中的变量含义与第一节一致。

2、convenc() 函数

再看 convenc() 函数

codedout = convenc(msg,trellis)
codedout = convenc(msg,trellis,puncpat)

简单使用卷积编码就用这个第1种调用方式就可以了,其中

  • msg参数是需要编码的信息,这个需要输入0,1二进制数据。
  • trellis参数就是上面函数生成的结果,传输到这里。

在使用时,需要注意的是 msg 数据的长度要是k的整数倍,同时利用上面的约束长度,计算回溯深度,利用回溯深度在信息后面添加0

3、vitdec() 函数

最后看译码函数

decodedout = vitdec(codedin,trellis,tbdepth,opmode,dectype)
decodedout = vitdec(codedin,trellis,tbdepth,opmode,'soft',nsdec)
decodedout = vitdec(codedin,trellis,tbdepth,opmode,dectype,puncpat)

译码函数的参数相对校多,主要是需要设置模式:

  • codedin参数是需要译码的结果,模式选择硬判决的时候必须输入是整数,模式选择软判决的时候可以输入小数。
  • trellis参数与编码函数的一致。
  • tbdepth这个参数参数就是回溯深度,前面利用约束长度计算的结果。
  • opmode 这个参数有三个不同的选项,分别为conttermtrunc
  • dectype参数用来设置是硬解码hard还是软解码soft,硬解码输入的数据都是01,软解码可以说输入小数。

有一点需要注意的是,对于termtrunk模式,回溯深度tbdepth必须是一个正整数,并且小于或等于输入编码中的输入符号数,说白了就是在编码前的信息msg长度就得大于等于回溯深度,要不然不够译码的。

这三个参数的差别,term模式下没有延时,就是译码的第一个数据就是编码的第一个数据。trunc参数也没有延时,cont参数有延时,是回溯深度。还有差别就是连续编码的区别。

4、MATLAB 仿真

利用(2,1,7)结构的形式进行卷积编译码,如下是测试代码,选择conthard模式。

close all;
clear;
clc;msg_source = [randi([0 1],1,50),zeros([1,30])]; % 这行代码生成一个长度为80的随机二进制消息序列。它使用randi函数在0和1之间随机生成50个比特,并在后面添加30个零。% 这些变量定义了卷积码的编码率。在这个例子中,n表示输出比特数,k表示输入比特数,因此编码率为1/2。
n = 2;
k = 1;
rate = k/n; % rate为 1/2% 这些变量定义了卷积码的约束长度和回溯深度。在这个例子中,约束长度为7,回溯深度为5*(7-1)=30。
L = 7;
tblen = 5*(L-1); % 回溯深度trellis = poly2trellis(L,[171 133]); % 使用poly2trellis函数生成一个约束长度为7的卷积码的Trellis结构。生成多项式为[171 133],定义了卷积码的生成过程。
code_data = convenc(msg_source,trellis); % 使用convenc函数对消息序列进行卷积码编码。它将msg_source输入到卷积码编码器中,使用之前生成的Trellis结构,得到编码后的数据序列code_data。
zero=zeros(1,2*tblen);  % 生成一个长度为2*tblen的零向量。
code_data=[code_data(:,1:end),zero]; % 在编码数据的末尾添加了零,以增加解码过程的缓冲区大小
d = vitdec(code_data,trellis,tblen,'cont','hard'); % 使用vitdec函数对编码数据进行卷积码译码。它使用之前生成的Trellis结构和回溯深度,采用硬判决方式进行译码,得到译码后的数据序列d。
d = d(tblen*k+1:end); % 从译码数据中去除多余的部分,保留原始消息序列的长度。
figure(1);
stairs(msg_source(1:end),':*r'); % 绘制原始消息序列的阶梯图,使用红色星号表示
hold on;    % 保持图形窗口的当前内容,以便后续的绘图命令在同一窗口中显示。
stairs(d,':+b');    % 绘制译码后的消息序列的阶梯图,使用蓝色加号表示。
ylim([-0.1,1.1]);
grid on;
legend('原始信息','恢复信息');

仿真结果:
请添加图片描述
可以看到编码后的 80bit 数据译码后与原数据一一对应。

参考文献:
1、【小白也能看懂】信道编码—卷积码等相关内容
2、卷积码matlab实现之ploy2trellis函数
3、信道编码:MATLAB使用卷积编译码函数


我的qq:2442391036,欢迎交流!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/130744.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

0008Java安卓程序设计-ssm基于Android平台的健康管理系统

文章目录 **摘要**目录系统实现开发环境 编程技术交流、源码分享、模板分享、网课教程 🐧裙:776871563 摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,…

Git 的基本操作 ——命令行

Git 的工作流程 详解如下: 本地仓库:是在开发人员自己电脑上的Git仓库,存放我们的代码(.git 隐藏文件夹就是我们的本地仓库) 远程仓库:是在远程服务器上的Git仓库,存放代码(可以是github.com或者gitee.com 上的仓库,或者自己该公司的服务器…

【ElasticSearch系列-05】SpringBoot整合elasticSearch

ElasticSearch系列整体栏目 内容链接地址【一】ElasticSearch下载和安装https://zhenghuisheng.blog.csdn.net/article/details/129260827【二】ElasticSearch概念和基本操作https://blog.csdn.net/zhenghuishengq/article/details/134121631【三】ElasticSearch的高级查询Quer…

PTA:前序序列创建二叉树

前序序列创建二叉树 题目输入格式输出格式输入样例(及其对应的二叉树)输出样例 代码 题目 编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以二叉链表存储)。 例如如下的先序遍…

SpringCloudAlibaba - 项目完整搭建(Nacos + OpenFeign + Getway + Sentinel)

目录 一、SpringCloudAlibaba 项目完整搭建 1.1、初始化项目 1.1.1、创建工程 1.1.2、配置父工程的 pom.xml 1.1.3、创建子模块 1.2、user 微服务 1.2.1、配置 pom.xml 1.2.2、创建 application.yml 配置文件 1.2.3、创建启动类 1.2.4、测试 1.3、product 微服务 1…

如何使用CodeceptJS、Playwright和GitHub Actions构建端到端测试流水线

介绍 端到端测试是软件开发的一个重要方面,因为它确保系统的所有组件都能正确运行。CodeceptJS是一个高效且强大的端到端自动化框架,与Playwright 结合使用时,它成为自动化Web、移动甚至桌面 (Electron.js) 应用程序比较好用的工具。 在本文中…

代码随想录算法训练营第23期day38|动态规划理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

目录 一、动态规划理论基础 1.动态规划的解题步骤 2.动态规划应该如何debug 二、(leetcode 509)斐波那契数 1.递归解法 2.动态规划 1)确定dp数组以及下标的含义 2)确定递推公式 3)dp数组如何初始化 4&#x…

C++虚表与虚表指针详解

类的虚表 每个包含了虚函数的类都包含一个虚表。 当一个类(B)继承另一个类(A)时,类B会继承类A的函数的调用权。所以如果一个基类包含了虚函数,那么其继承类也可调用这些虚函数,换句话说&…

基于ASP.NET MVC + Bootstrap的仓库管理系统

基于ASP.NET MVC Bootstrap的仓库管理系统。源码亲测可用,含有简单的说明文档。 适合单仓库,基本的仓库入库管理,出库管理,盘点,报损,移库,库位等管理,有着可视化图表。 系统采用Bo…

MySQL导入数据库报错Error Code: 2006

Error Code: 2006 - MySQL server has gone away 因为导入的某张表数据过大导致导入中途失败 , 修改max_allowed_packet 即可解决。 SET GLOBAL max_allowed_packet 1024*1024*200;

【数据结构】数组和字符串(十五):字符串匹配2:KMP算法(Knuth-Morris-Pratt)

文章目录 4.3 字符串4.3.1 字符串的定义与存储4.3.2 字符串的基本操作4.3.3 模式匹配算法0. 朴素模式匹配算法1. ADL语言2. KMP算法分析3. 手动求失败函数定义例1例2例3 4. 自动求失败函数(C语言)5. KMP算法(C语言)6. 失败函数答案…

STM32F103C8T6第二天:按键点灯轮询法和中断法、RCC、电动车报警器(振动传感器、继电器、喇叭、433M无线接收发射模块)

1. 点亮LED灯详解(307.11) 标号一样的导线在物理上是连接在一起的。 将 PB8 或 PB9 拉低,就可以实现将对应的 LED 灯点亮。常用的GPIO HAL库函数: void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);//I/…

产品经理入门学习(二):产品经理问题思考维度

参考引用 黑马-产品经理入门基础课程 1. 抓住核心用户 1.1 为什么要抓住核心用户 什么是用户? 所有和产品有关系的群体就是用户,他们是一群既有共性,又有差异的群体组合 做产品为什么要了解用户? 了解用户的付费点、更好的优化产…

【软考中级】软件设计师-下午题

下午题 试题一 黑洞:加工有输入无输出 白洞(奇迹):加工有输出无输入 灰洞:数据流输入的加工不足以产生输出 结构化语言: IF *** THEN ELSE IF *** THEN ******* END IF END IF 数据流的父子图平衡,如果父子图平衡就不…

【CIO人物展】黄淮学院副CIO周鹏:构建数智化平台赋能学校高质量发展

周鹏 本文由黄淮学院副CIO周鹏投递并参与《2023中国数智化转型升级优秀CIO》榜单/奖项评选。丨推荐企业—锐捷网络 大数据产业创新服务媒体 ——聚焦数据 改变商业 黄淮学院是2004年经教育部批准成立的一所省属全日制普通本科高校。学校位于素有“豫州之腹地、天下之最中”之美…

地理信息系统原理-空间数据结构(7)

​四叉树编码 1.四叉树编码定义 四叉树数据结构是一种对栅格数据的压缩编码方法,其基本思想是将一幅栅格数据层或图像等分为四部分,逐块检查其格网属性值(或灰度);如果某个子区的所有格网值都具有相同的值&#xff0…

Linux----------------Shell重定向输入输出

(一) 标准输入 以键盘读取用户输入的数据,然后再把数据拿到 Shel程序中使用。 标准输出 Shell 程序产生的数据,这些数据一般都是呈现到显示器上供用户浏览查看 输入输出重定向 输入方向就是数据从哪里流向程序。数据默认从键…

【使用Python编写游戏辅助工具】第五篇:打造交互式游戏工具界面:PySide6/PyQT高效构建GUI工具

前言 这里是【使用Python编写游戏辅助工具】的第五篇:打造交互式游戏工具界面:PySide6/PyQT高效构建GUI工具。本文主要介绍使用PySide6来实现构建GUI工具。 在前面,我们实现了两个实用的游戏辅助功能: 由键盘监听事件触发的鼠标连…

IntelliJ IDEA 2023 最新版如何试用?IntelliJ IDEA 2023最新版试用方法及验证ja-netfilter配置成功提示

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

[极客大挑战 2019]Http 1

题目环境: 看起来挺花里胡哨的 F12查看源代码寻找隐藏文件 这是啥子呀,果然防不胜防 点击隐藏文件Secret.php 它不是来自这个地址的请求 报头:https://Sycsecret.buuoj.cn 需要抓包,在抓包前了解部分数据包参数 GET:到 Host:来自 …