基于matlab通信系统仿真信源编解码课程设计报告.docx
- 文档编号:29367973
- 上传时间:2023-07-22
- 格式:DOCX
- 页数:22
- 大小:252.43KB
基于matlab通信系统仿真信源编解码课程设计报告.docx
《基于matlab通信系统仿真信源编解码课程设计报告.docx》由会员分享,可在线阅读,更多相关《基于matlab通信系统仿真信源编解码课程设计报告.docx(22页珍藏版)》请在冰豆网上搜索。
基于matlab通信系统仿真信源编解码课程设计报告
一、设计题目
◆基于MATLAB通信系统仿真——信源编解码。
二、实验内容及要求
◆内容:
完成对一模拟信号的抽样、量化、编码,然后利用Huffman信源编码对其进行数据压缩,再利用(15,11)的线性分组码进行信道编码,然后采用DPSK调制方式调制,接着通过信道;在接收端进行其逆过程,即先解调(可采用相干解调或差分相干解调),再依次为信道译码,Huffman信源译码,PCM译码。
◆要求:
利用相关知识,建立系统模型,完成各个模块的代码设计。
三、实验过程(详细设计)
◆通信系统模型:
◆
本实验主函数框图:
◆分步设计:
Ø抽样部分([sg1,sg2]=Sampling(fs)):
函数功能:
对原始信号进行抽样;
函数参数:
fs抽样频率(须大于等于两倍的信号最高频率);
函数返回值:
sg1表示原始信号,sg2表示抽样信号;
实现:
根据抽样频率fs在一个周期里抽取fs个值即可。
Ø进制转换部分([h]=dextobin(n,n_no)):
函数功能:
将十进制数转换成二进制数;
函数参数:
n表示待转换的十进制数,n_no表示要将n转换为二进制数的位数;
函数返回值:
h表示n的n_no位二进制数;
实现:
首先判定n是否为整数,如果不是则将其先进行四舍五入处理,然后将处理后的n’转换成位数与n_no相同的二进制数,前面多余的位用零表示。
ØPCM编码部分([pc]=PCM_code(sg2)):
函数功能:
对抽样值sg2进行PCM编码;
函数参数:
sg2表示通过抽样函数Sampling抽样后的离散值;
函数返回值:
pc表示sg2中的每一个值通过PCM编码后的8位二进制码组的十进制数形式(说明:
之所以转换成十进制数,是为了在Huffman编码时的方便)。
实现:
以一个实际的数为例,首先确定这个数拥有多少个量化单位(1/2048),然后编码,如果为负则第一位为0,否则为1;接着根据刚才计算得到的量化单位判断其段落,得到段落码;最后确定段内码,方法:
先计算每一端的量化间隔
(注意:
此处的
是一量化单位为基础的,而不是最小量化间隔)
为段落值,然后再利用计算式
,得到段内段落数
,再将
转换成二进制数,完成编码。
ØHuffman数据压缩部分:
说明:
本部分包含两个函数Huff_P和Huff_code两个函数,下面将一一介绍;
[P,Str,B]=Huff_P(Str):
函数功能:
计算Str中每一种元素的概率;
函数参数:
Str是一个数组,元素为PCM_code函数返回的pc;
函数返回值:
P表示每个元素的概率矩阵,Str同参数一样,B表示Str中的元素种类;
实现;利用系统函数unique得到Str中的元素的种类,再利用双重循环计算每一种元素个数,再除以中的元素的个数,便得到每一种元素的概率。
[Code,Final_code,Length_code,Bnew]=Huff_code(P,Str,B):
函数功能:
对B中的每一种元素进行Huffman编码;
函数参数:
P表示概率矩阵,Str同Huff_P函数中的参数一致,B表示元素种类;
函数返回值:
Code表示建立的码字表,Final_code表示对B中的每一种元素编码后的0、1比特流,Length_code表示Code中每一行码字的长度,Bnew表示根据概率矩阵P降序排列后的元素。
实现:
首先构造一个六行的Huffman树,第一行存放结点编号,第二行存放该结点的概率值,第三行记录该结点的父结点,第四行记录该结点是左结点还是右结点,第五行标记该结点是否为父结点,第六行存放概率P降序排列后的新矩阵。
然后根据Huffman树记录的编码过程,完成对B的编码和对Str的编码。
Ø产生生成矩阵和监督矩阵部分([G,H]=GH()):
函数功能:
产生(15,11)码生成矩阵G和监督矩阵H;
函数参数:
无;
函数返回值:
生成矩阵G和监督矩阵H;
实现:
将单位矩阵与监督矩阵分开完成,然后再合并到一起。
首先生成两个大小分别为(4,4)和(11,11)的单位矩阵;然后在利用循环生成监督矩阵,方法如下:
将3至15除了4和8之外的这十一个数分别调用dextobin函数将其转换成二进制数,这些二进制数即作为监督元。
将监督元直接附在(11,11)单位矩阵的后面即可得到生成矩阵G,将监督元转置然后再将(4,4)的单位矩阵附在其后面即可得到监督矩阵。
Ø信道编码部分([M,H]=code(bits)):
函数功能:
信道编码,完成(15,11)的信道编码;
函数参数:
bits表示比特流;
函数返回值:
编码后的比特流M和监督矩阵H;
实现:
首先调用GH()函数产生生成矩阵G和监督矩阵H,然后判断传入的比特流能否被11整除;如果能,则直接对其进行编码,每次取11位分别与监督矩阵G相乘;如果不能被11整除则先在比特流的最后填上若干位,使其能够被11整除,在进行编码。
这么做的好处在于,不会因为比特流最后几位不够11位而被丢弃,造成数据的流失,即保证了数据的完整性。
ØDPSK调制解调部分([IN,cs,demodu3]=DPSK_modu(pc,SNR)):
函数功能:
对pc进行DPSK调制;
函数参数:
pc表示经过信道编码后的比特流,SNR表示信噪比;
函数返回值:
IN表示低通滤波器的延迟,cs表示经过信道加噪后的调制信号,demodu3表示经过低通滤波器滤波后的解调信号。
实现:
1)本实验设定一个比特位用两个载波周期进行调制,比特率为1000,采样频率为32倍的比特率,所以每个比特位采样64个点,利用正弦信号进行调制。
2)调制完成之后,将已调信号通过信道加噪。
3)通过信道之后,就进行相干解调,即利用同频同相的载波去乘已调信号,必须得对应位相乘。
考虑到信号经过滤波器后会产生延迟,如果不改变信号的矩阵的长度,则必然会造成信号的丢失。
所以先利用公式:
求解出延迟,式中IN表示延迟,lowpass表示设计的低通滤波器。
接着将原信号的后面人工添加IN个0,待通过低通滤波器后被挤掉的只是人工添加的那些零,而我们的有用的数据则不会丢失。
然后将解调信号送至低通滤波器,滤除高频部分。
Ø信道译码部分([Dcode,S]=decode(demodu3,cs,IN,n,H)):
函数功能:
抽样判决,信道检错、纠错、译码;
函数参数:
demodu3表示解调后的信号,cs表示经过信道后的信号,IN表示滤波器的延迟,n表示信息位数,H为监督矩阵;
函数返回值:
Dcode表示经过抽样判决,信道检错、纠错、译码之后得到比特流,S则表示接收码字的伴随式。
实现:
1)抽样判决:
选取每段的中间点作为抽抽样点,考虑到滤波器的延迟,因此循环的开始点为IN+16(因为前面每个比特位抽样32个点,所以其中点为16)。
设定判决门限为0,大于0的则将抽样点周围的32点(包含该抽样点)置为1,小于0的则将抽样点周围的32点(包含该抽样点)置为0,以32为间隔重复,知道信号最后。
2)获取码字序列:
抽取上一步中每一段序列中的一个值作为码字序列。
3)检错纠错:
利用自己设计的dextobin函数生成(15,11)线性分组码的错误图样E,并将上一步得到的码字序列转换成15列的码字矩阵,并利用此矩阵和监督矩阵的转置相乘,便得到伴随式矩阵。
判断每一行伴随式与监督矩阵的哪一列相等,再将相应行的码字与错误图样作模二和,便得到正确的码字。
4)译码:
因为本实验采用的是系统线性分组码,所以码字的前11位即是信息位,因此译码就相对比较简单,可以直接扔掉码字的后四位即可。
ØHuffman译码部分:
[HDecode]=Huff_decode(Code,Final_code,Length_code,Bnew,Str):
函数功能:
完成Huffman译码;
函数参数:
Code表示Huff_code函数建立的码字表,Final_code表示Huff_code中对B中的每一种元素编码后的0、1比特流,Length_code表示Code中每一行码字的长度,Bnew表示根据概率矩阵P降序排列后的元素。
函数返回值:
HDecode表示经Huffman译码后的十进制数矩阵。
实现:
利用传入的码表Code,每次取一种码字,与经过信道译码后的0、1比较(每次取码字长度的0、1序列比较),如果不符合则取下一条码字,知道译出为止。
ØPCM译码部分([dc]=PCM_decode(sg1,HC)):
函数功能:
对经过Huffman译码后的十进制数进行PCM译码,还原信号。
函数参数:
sg1表示原始信号,这里传入原始信号,只是为了与接收到的信号进行比较;HC表示经Huffman译码后的十进制数。
函数返回值:
dc表示恢复的信号值。
实现:
首先将HC变成8位的码组,调用dextobin即可;然后确定段落数,取码组的第2,3,4位转换成十进制数,得到的十进制数即是段落数,再计算段量化间隔;最后确定段内段数,再计算出还原值。
四、测试结果及设计分析
◆抽样部分:
说明:
此处抽样信号采用stem函数来画图,主要是为了方便观察。
另外每个周期的抽样点数为20。
◆进制转换部分:
将8装换成二进制数,假设需要转换的位数为3和5,得到两个结果如下:
图一:
图二:
说明:
从以上两幅图片可以看出,同一个数在不同需转换的最大值情况下,得到的二进制数的位数可能不同。
◆
线性分组码的生成矩阵和监督矩阵部分:
说明:
由以上结果不难看出,本实验采用的是系统码。
◆DPSK调制解调部分:
ØBPSK与DPSK调制的比较:
说明:
由于BPSK调制存在相位模糊的问题,因此引入DPSK消除相位模糊。
Ø
解调、滤波后的波形:
说明:
由于数据量比较大,所以只画出部分图形。
不过无论是调制,解调,还是滤波后的波形,在图形上都是一一对应的,横坐标不同是因为滤波器的延迟作用。
◆PCM译码部分:
还原的信号与原始信号:
说明:
根据以上两幅图的对比可知,恢复的信号与原始信号大部分是一致的,说明该系统的特性良好,各函数也都设计正确;而上面大约在横坐标57的地方出现了失真。
分析其原因,应该是在通过信道的时候,由于噪声的影响,导致判决错误,接着出现错误的信道译码,错误的Huffman译码,错误的PCM译码,最后导致信号失真。
◆设计分析:
对于这个实验的设计,主要采用函数的设计思想,每个功能独立成块。
这样做的好处在于,一、整个程序结构显得比较明朗,清楚;二、可以随意添加其他功能,只需添加相应的功能模块即可;三、便于程序的维护,例如某一个地方出错,只需改动相应的函数即可。
PCM编码部分,根据PCM编码原理首先将抽样值归一化,然后计算其量化单位,再编码。
先确定编码的第一位,为正则为1,为负则为0;然后确定其段落码和段内码。
因为先将抽样值归一化,再计算其量化间隔,且采用的是256个量化电平,对于普通的信号,能够较好地减少其量化噪声。
PCM编码之后,即进行数据压缩,原理将每个抽样值的8位码组转换成十进制数,将此十进制数当作一个符号,由PCM编码原理可知,所有的抽样的8位码组的十进制数范围在0—255之间,在进行Huffman编码,达到数据压缩的目的。
信道编码部分,采用的是(15,11)的线性分组码,其生成矩阵和监督矩阵利用了代码来产生而不是人工输入,这样即减少了工作量,也减少了出错的概率,同时还可生成其他线性分组码的生成矩阵和监督矩阵。
在本实验中采用的正弦波来进行DPSK调制,之所以没有采用余弦,是因为经调制后,正弦调制波更好观察。
在实际应用中,DPSK调制可以避免PSK相位模糊的问题,因此得到广泛的运用。
再一个就是在实验过程中,必须要考虑到滤波器的延迟问题,一是为了画图,但更重要的是要保证有用的数据不会因为滤波器的延迟问题而丢失,解决的办法是在数据最后至少添加IN个长度的冗余位。
另外,本设计也存在一些不足之处。
比如信道译码部分,其纠错能力有限,当信噪比比较低的时候,容易出现错误译码。
五、实验心得体会
附录:
主要代码
%函数功能:
对sg2进行PCM编码;
%函数参数:
sg2:
要编码的值。
function[pc]=PCM_code(sg2)
sg=(sg2/max(sg2)).*2047;
n=length(sg);
pc=[];
forj=1:
n
x=sg(j);
c=zeros(1,8);
ifx~=0
%------确定第一位
ifx<0
c
(1)=0;
x=x*(-1);
else
c
(1)=1;
end
ifabs(x)>=16
%------确定段落码
m=fix(log2(x))-2;%确定在哪一段内;
[h]=dextobin(m-1,3);
c(1,[2,3,4])=h;
dat=2^(m-2);%确定段量化间隔;
m2=fix((x-2^(m+2))/dat);%m2为段内段数;
else
dat=1;
m2=x;
end
%------确定段内码
[h]=dextobin(m2,4);
c(1,[5,6,7,8])=h;
end
c_n=c
(1)*128+c
(2)*64+c(3)*32+c(4)*16+c(5)*8+c(6)*4+c(7)*2+c(8);
pc=[pc,c_n];
end
end
%函数功能:
PCM解码;
%函数参数:
pc:
待解码十进制数;
function[dc]=PCM_decode(sg1,HC)
pc=[];
forj=1:
length(HC)
[h]=dextobin(HC(j),8);
pc=[pc,h];
end
N=length(pc)/8;
dc=[];
fori=1:
N
x=pc((i-1)*8+1:
i*8);
%-------确定段落
m=x
(2)*4+x(3)*2+x(4)+1;
%-------确定段内段数
m2=x(5)*8+x(6)*4+x(7)*2+x(8);
%-------确定量化间隔并解码
ifm~=1
dat=2^(m-2);%dat为量化间隔;
c=2^(m+2)+m2*dat;
else
dat=1;
c=m2*dat;
end
%-------确定正负
ifx
(1)==0
c=c*(-1);
end
dc=[dc,c];
end
figure,subplot(2,1,1);
plot(sg1,'c');axis([0,length(sg1),-1,1]);title('原始信号');
subplot(2,1,2);
plot(dc/2047);axis([0,length(dc),-1,1]);title('恢复信号');
end
function[Code,Final_code,Length_code,Bnew]=Huffman_code(Str)
[P,Str,B]=Huff_P(Str);
[Code,Final_code,Length_code,Bnew]=Huff_code(P,Str,B);
End
%函数功能:
构造Huffman树;
%函数参数:
P:
每种符号的概率;
function[Code,Final_code,Length_code,Bnew]=Huff_code(P,Str,B)
[P1,P2]=sort(P,'descend');%将P降序排列,并返回每个值原来的位置;
n=length(P1);
P_cor=zeros(2,length(P1));%用P_cor来存储每个符号概率和每个概率在P中的位置;
P_cor(1,:
)=P1;
P_cor(2,:
)=P2;
Bnew=[];
fori=1:
n
Bnew=[Bnew,B(P2(i))];
end
%///////////////////////////////////构造Huffman树//////////////////////////////////////////////////////////////////////////////////
%构造一个tree(6,2*n-1)的Huffman树矩阵;tree(1,:
)用于存放结点编号,从1到2*n-1;tree(2,:
)用于存放该结点的概率值;
%tree(3,:
)用于存放该节点的父结点;tree(4,:
)用于记录该结点是左结点还是右结点,“0”表示左,“1”表示右;
%tree(5,:
)记录该结点是否为根结点,是则记为“1”,否则记为“0”;tree(6,:
)用于存放P2;
%////////////初步构造tree;///////////////////////
tree=ones(6,2*n-1);%2*n-1表示构造的Huffman树的结点的个数;
tree(1,:
)=1:
(2*n-1);
tree(2,1:
n)=P_cor(1,:
);
tree(5,(n+1):
end)=0;
tree(6,1:
n)=P_cor(2,:
);
tree(6,n+1:
end)=0;
%/////////////构造矩阵P_pro/////////////////////
%P_pro用于记录每次两个最小概率相加后的概率分布情况;
P_pro=ones(n-1,2*n-1);
P_pro(1,:
)=sort(tree(2,:
));
fori=2:
n
P_pro(i,:
)=[P_pro(i-1,1)+P_pro(i-1,2),P_pro(i-1,3:
2*n-1),1];
P_pro(i,:
)=sort(P_pro(i,:
));
end
%/////////////完成Huffman树的构造//////////////
m1=0;m2=0;
st=tree(2,:
);%令st=tree(2,:
),对st操作,以免破坏tree的结构;
fori=(n+1):
(2*n-1)
min1=find(st==P_pro(i-n,1));
iflength(min1)==1%如果最小的那个概率没有相同的,则继续找出次小的;
m1=min1;
min2=find(tree(2,:
)==P_pro(i-n,2));
m2=min2
(1);%避免次小的概率有相同的;
else
m1=min1(1,1);
m2=min1(1,2);
end
tree(2,i)=tree(2,m1)+tree(2,m2);
st(i)=tree(2,m1)+tree(2,m2);
st(m1)=-1;
st(m2)=-1;
tree(5,i)=1;
tree(3,m1)=i;tree(3,m2)=i;
tree(4,m1)=1;tree(4,m2)=0;
tree(5,m1)=0;
tree(5,m2)=0;
end
Huff_tree=tree;
%///////////////////////////////////////对B进行编码////////////////////////////////////////////////////////////////////////////////////////
Code=-ones(length(P2),length(P2));
Bitstream=[];%码字比特流;
Length_code=[];%根据Huff_tree(6,:
)的顺序,记录每个符号码字的长度;
L_avg=0;%平均码长;
H_avg=0;
fori=1:
length(P2)
Huff_code=[];
key=1;
m=find(Huff_tree(6,:
)==P2(i));
while(Huff_tree(5,m)~=1)
Huff_code(key)=Huff_tree(4,m);
key=key+1;
m=Huff_tree(3,m);
end
Length_code=[Length_code,key-1];
Code(i,1:
key-1)=fliplr(Huff_code);
L_avg=L_avg+Huff_tree(2,i)*(key-1);
end
%////////////////////////////////////对Str进行编码////////////////////////////////////////////
Final_code=[];
[nx,ny]=size(Code);
fori=1:
length(Str)
forj=1:
length(B)
ifB(j)==Str(i)
v=find(Huff_tree(6,:
)==j);
l=Length_code(v);
Final_code=[Final_code,Code(v,1:
l)];
end
end
end
H_avg=sum(P.*(-log2(P)));
Code_eff=H_avg/L_avg;
End
%函数功能:
输入一串字符,并计算每个符号的概率;
%函数参数:
无;
function[P,Str,B]=Huff_P(Str)
%disp('Pleaseinputastringofcharacters:
');
%Str=input('');
B=unique(Str);
%for循环的作用;计算每个符号的个数,包括空格;
fori=1:
length(Str)
forj=1:
length(B)
ifB(j)==Str(i)
P1(j)=length(strfind(Str,Str(i)));
end
end
end
P=P1/length(Str);
n=length(P);
fori=1:
n
ifP(i)<0
fprintf('\nTheprobabilitiesinhuffmancannotlessthan0!
\n');
%如果输入的概率数组中有小于0的值,则重新输入概率数组;
Str=input('pleaseinputanumber:
');
end
end
function[HDecode]=Huff_decode(Code,Final_code,Length_code,Bnew,Str)
[nx,ny]=size(Code);
HDecode=[];
D_Bits=[Final_code,-ones(1,max(Length_code))];
forj=1:
length(Str)
fori=1:
nx
k=Length_code(i);
while(D_Bits(1:
k)==Code(i,1:
k))
HDecode=[HDecode,Bnew(i)];
D_Bits=D_Bits(k+1:
end);
end
end
end
end
%函数功能:
进行DPSK调制解调
%函数参数:
pc:
经过PCM编码后的0、1比特流;
function[IN,cs,demodu3]=DPSK_modu(pc,SNR)
%------------相对码
n=length(pc);
pc;
pc2=zeros(1,n+1);
fori=1:
n
pc2(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 matlab 通信 系统 仿真 信源 解码 课程设计 报告