通信原理课程设计——基于C/C++的通信系统采用A律13折线进行pcm编码与解码_通信原理a律-程序员宅基地

一、课题内容

本课题是基于C/C++的通信系统,来实现对输入的即将要编码的值,采用A律13折线进行pcm编码与解码。

二、设计目的

1、培养采用VC6.0对pcm编码与解码进行编译与调试的方法;
2、培养学生对PCM的理解能力;
3、掌握PCM编码和译码的工作原理与系统性能测试;
4、能提高和挖掘学生对所学知识的实际应用和创新的能力;
5、熟悉VC6.0中对pcm编码与解码相关函数的具体使用方法。

三、设计要求

用基于C/C++的通信系统,来实现对A律13折线PCM编码对输入的模拟信号进行采样、量化、编码; 将编码后的信号输入信道再进行PCM解码,还原出原信号。

四、实验条件

1、一本《通信原理》(第七版)大学教科书;
2、一台安装有VC6.0的个人电脑;
3、记有pcm相关知识的笔记本。

五、系统设计

1、通信系统的原理(阐述整个通信系统原理,最后指出你主要负责哪一部分)

  • 本教材以现代通信系统为背景,系统介绍通信的基本原理,加深学生对通信基本理论的理解;密切跟踪通信技术的发展,将现代通信的最新理论与技术引入课堂,加强理论与实际的联系;利用通信系统仿真方法,激发学生的创新实践能力,更好地掌握现代通信技术。全面阐述了现代通信系统分析和设计所必需的基本原理,并对重要的数学基础知识进行了回顾。涉及的内容包括信号与信道、模拟调制系统、数字基带传输系统、数字带通传输系统、噪音对模拟通信系统的影响、新型数字带通调制技术、数字信号的最佳接收、信源编码、通过载波调制进行数字信息传输、差错控制编码等。
  • 我主要负责信源编码模块的脉冲编码调制(A律13折线PCM编码与解码)。

2. 所设计子系统的原理

1)PCM的基本原理

  • 脉冲编码调制(PCM)简称脉码调制,它是一种用二进制数字代码来代替连续信号的抽样值,从而实现通信的方式。因为此种通信方式抗干扰能力强,因此在光钎通信、数字微波通信、卫星通信中均获得了极为广泛的运用。PCM信号的形成是模拟信号经过“抽样、量化、编码”三个步骤实现的。分别完成时间上离散、幅度上离散、及量化信号的二进制表示。根据CCITT的建议,为改善小信号量化性能,采用压扩非均匀量化,有两种建议方式,分别为A律和μ律方式,我国采用了A律方式,由于A律压缩实现复杂,常使用 13 折线法编码。

2)抽样

  • 抽样,即是对模拟的信号所进行的周期性的扫描,将在时间上连续的信号变为在时间上离散的信号。

3)量化

  • 抽样信号虽然是时间轴上离散的信号,但仍然是模拟信号,其样值在一定的取值范围内,可有无限多个值。量化噪声的大小取决于把样值分级“取整”的方式,分的级数越多,即量化级差或间隔越小,量化噪声也越小。
  • 模拟信号的量化分为均匀量化和非均匀量化。

4)均匀量化

  • 均匀量化,即量化间隔相等,均匀量化输出与输入关系为均匀阶梯关系。
    在这里插入图片描述

5)非均匀量化

  • 非均匀量化的量化间隔是依据信号的不同的区间来定的。信号取值大的区间,它的量化间隔△v大;在信号的取值小的区间,它的量化间隔△v小。
    在这里插入图片描述
  • 13折线时A律的x值与折线x值的比较表
    在这里插入图片描述
  • A律13折线
    在这里插入图片描述

6)编码

  • 在13折线法中,无论输入信号正还是负,都依8段折线(8个段落)来编码。要是输入信号抽样量化值由8位折叠二进制码表示,在此间量化值极性就要用第一位表示,抽样量化值其绝对的大小就要用其余七位(第2至8位)来表示。详细的做法是:用第2到第4位表示段落码,八个段落的起点电平由它的八种可能状态来分别表示。其它四位表示段内码,每一个段落它的16个均匀的划分地量化级由它的16种可能状态来分别的代表。这样处理的结果,8个段落被划分成128个量化级。
  • PCM编码8位二进制码的具体组成结构如下:
    C1C2C3C4C5C6C7C8
    C1是极性码,“1”表示正极性,“0”表示负极性;C2C3C4这3位二进制码表示段落码,3位二进制码共可以表示8个段落;剩余的4位二进制码,C5C6C7C8表示的是每一段内的16个量化电平,每一段内的量化电平是等间隔分布的,但是量化电平间隔的大小是随着段落序号的增加而以2倍的速度增加的。其中段落码和段内码分别如下表2和表3所示。
    在这里插入图片描述
    在这里插入图片描述
  • 为了确定样值的幅度所在的段落和量化级,必须知道每个段落的起始电平和各段内的量化间隔。在A律13折线中,由于各段长度不等,因此各段内的量化间隔也是不同的。第一段、第二段最短,只有归一化值的1/128,再将它等分16级,每个量化级间隔为=1/128(1/16)=1/2048式中,表示最小的量化间隔,称为一个量化单位,它仅有输入信号归一化值的1/2048。第八段最长,它的每个量化级间隔为(1-1/2)(1/16)=1/32=64即包含64个最小量化间隔。若以为单位,则各段的起始电平和各段内的量化间隔如图:
    在这里插入图片描述
  • 以上是非均匀量化情况,若以量化间隔进行均匀量化,则13折线正极性所包含的均匀量化级数分别为16、16、32、64、128、 256、 512、 1024,共计2048=211个量化级或量化电平,需要进行11位(线性)编码。而非均匀量化只有128个量化电平,只要编7位(非线码)。由此可见,在保证小信号量化间隔相同条件下,非均匀量化的编码位数少,所需传输系统宽带减小。

7)脉冲编码调制

在这里插入图片描述

8)译码

  • 译码是编码的逆过程。译码的作用是把收到的PCM信号还原成量化后的原样值信号,即进行D/A变换。

六、详细设计与编码

1.编码代码的思路

1)利用输入要编码的值,确定pcm码组的极性码C1;数组outputvalue[0]正数写入1负数写入0;将输入的值取绝对值。
2)因为段落码有3位8段,采用与段落起始电平Iw比较的方法,确定该值位于哪一段,通过该值和各段对应的段落起始电平与量化间隔利用switch函数将段内码outputvalue[1]到outputvalue[7]依次求出来;相当于C1C2C3C4C5C6C7。
3)而outputvalue在第二步骤上的基础加上outputvalue[0]的值;此步骤结束后,在main函数中用循环输出的方法以及通过调用函数实现就可以得到相应pcm码组。
4)计算相对于的编码后的误差以及编码电平。

2.解码代码的思路

1)利用输入解码的十进制值;
2)将该值codevalue从低位到高位依次存入数组a中;
3)求出量化段序号存入duannum中;
4)利用duannum的值、段落起始电平、量化级序号及switch()函数求出各个编码电平;
5)如果为负数,即a[0]==0时求补极为它十进制的值;
6)然后main()函数调用解码函数求出解码电平。

3. 编码与测试(写出源代码,分析核心代码完成的功能)

13折线A律PCM编码的源代码:

#include <IOSTREAM>
#include <MATH.H>
using namespace std;
static int OutputValue[8]={0,0,0,0,0,0,0,0};
int * PCM_StudentAlawEncode(int InputValue)
{
//	unsigned char OutputValue = 0x00;
//起始电平
	int stardianping[8]={16,32,64,128,256,512,1024,2048};
	//int OutputValue[8]={0};
	/*Add your code here*/
	if (InputValue<0)//输入的值为负数
	{	
		OutputValue[0]=0;//C1=0
		InputValue=abs(InputValue);//对输入的值求绝对值
	}	
	else //输入的值为正数,C1=1
		OutputValue[0]=1;
	for (int i=0;i<=7;i++){
	if(InputValue<stardianping[i])//与起始电平比较,得到i
{
break;
}
}	
switch(i){
case 0://第一段
			OutputValue[1]=0;
			OutputValue[2]=0;
			OutputValue[3]=0;
			OutputValue[4]=InputValue/8;
			OutputValue[5]=(InputValue-OutputValue[4]*8)/4;
OutputValue[6]=(InputValue-OutputValue[4]*8-OutputValue[5]*4)/2;
	OutputValue[7]=(InputValue-OutputValue[4]*8-OutputValue[5]*4-OutputValue[6]*2)/1;						
			break;
		case 1://第二段
			OutputValue[1]=0;
			OutputValue[2]=0;
			OutputValue[3]=1;
			OutputValue[4]=(InputValue-16)/8;
	OutputValue[5]=(InputValue-16-8*OutputValue[4])/4;
	OutputValue[6]=(InputValue-16-8*OutputValue[4]-4*OutputValue[5])/2;
	OutputValue[7]=(InputValue-16-8*OutputValue[4]-4*OutputValue[5]-2*OutputValue[6])/1;
			break;
		case 2://第三段
			OutputValue[1]=0;
			OutputValue[2]=1;
			OutputValue[3]=0;
			OutputValue[4]=(InputValue-32)/16;
	OutputValue[5]=(InputValue-32-16*OutputValue[4])/8;
	OutputValue[6]=(InputValue-32-16*OutputValue[4]-8*OutputValue[5])/4;		OutputValue[7]=(InputValue-32-16*OutputValue[4]-8*OutputValue[5]-4*OutputValue[6])/2;
			break;
		case 3://第四段
			OutputValue[1]=0;
			OutputValue[2]=1;
			OutputValue[3]=1;
			OutputValue[4]=(InputValue-64)/32;		OutputValue[5]=(InputValue-64-32*OutputValue[4])/16;
	OutputValue[6]=(InputValue-64-32*OutputValue[4]-16*OutputValue[5])/8;
	OutputValue[7]=(InputValue-64-32*OutputValue[4]-16*OutputValue[5]-8*OutputValue[6])/4;
			break;
		case 4://第五段
			OutputValue[1]=1;
			OutputValue[2]=0;
			OutputValue[3]=0;
			OutputValue[4]=(InputValue-128)/64;
	OutputValue[5]=(InputValue-128-64*OutputValue[4])/32;
	OutputValue[6]=(InputValue-128-64*OutputValue[4]-32*OutputValue[5])/16;
	OutputValue[7]=(InputValue-128-64*OutputValue[4]-32*OutputValue[5]-16*OutputValue[6])/8;
			break;
		case 5://第六段
			OutputValue[1]=1;
			OutputValue[2]=0;
			OutputValue[3]=1;	
			OutputValue[4]=(InputValue-256)/128;
	OutputValue[5]=(InputValue-256-128*OutputValue[4])/64;
	OutputValue[6]=(InputValue-256-128*OutputValue[4]-64*OutputValue[5])/32;
	OutputValue[7]=(InputValue-256-128*OutputValue[4]-64*OutputValue[5]-32*OutputValue[6])/16;
			break;
		case 6://第七段
			OutputValue[1]=1;
			OutputValue[2]=1;
			OutputValue[3]=0;
			OutputValue[4]=(InputValue-512)/256;
	OutputValue[5]=(InputValue-512-256*OutputValue[4])/12;
	OutputValue[6]=(InputValue-512-256*OutputValue[4]-128*OutputValue[5])/64;
	OutputValue[7]=(InputValue-512-256*OutputValue[4]-128*OutputValue[5]-64*OutputValue[6])/32;
			break;
		case 7://第八段
			OutputValue[1]=1;
			OutputValue[2]=1;
			OutputValue[3]=1;
			OutputValue[4]=(InputValue-1024)/512;
OutputValue[5]=(InputValue-1024-512*OutputValue[4])/256;
OutputValue[6]=(InputValue-1024-512*OutputValue[4]-256*OutputValue[5])/128;		OutputValue[7]=(InputValue-1024-512*OutputValue[4]-256*OutputValue[5]-128*OutputValue[6])/64;
			break;
	}
   return OutputValue;
}
int main()
{int *a;
int temp,b;
	while(1)
	{	cout<<"输入13折线A律PCM抽样脉冲值:";
		cin>>temp;
		cout<<"13折线A律PCM编码的输出码组为:";
		a=PCM_StudentAlawEncode(temp);
		for (int j=0;j<=7;j++)
		{	cout<<a[j];
		}
		cout<<endl;	
		int i=a[1]*4+a[2]*2+a[3]*1;
			switch(i)
			{case 0:
				b=0+1*(a[4]*8+a[5]*4+a[6]*2+a[7]*1);
			cout<<"13折线A律PCM编码的编码电平为:"<<b;
			break;
		case 1:
			b=16+1*(a[4]*8+a[5]*4+a[6]*2+a[7]*1);
			cout<<"13折线A律PCM编码的编码电平为:"<<b;
			break;
		case 2:
			b=32+2*(a[4]*8+a[5]*4+a[6]*2+a[7]*1);
			cout<<"13折线A律PCM编码的编码电平为:"<<b;
			break;
		case 3:
			b=64+4*(a[4]*8+a[5]*4+a[6]*2+a[7]*1);
			cout<<"13折线A律PCM编码的编码电平为:"<<b;
			break;
		case 4:
			b=128+8*(a[4]*8+a[5]*4+a[6]*2+a[7]*1);
			cout<<"13折线A律PCM编码的编码电平为:"<<b;
			break;
		case 5:
			b=256+16*(a[4]*8+a[5]*4+a[6]*2+a[7]*1);
			cout<<"13折线A律PCM编码的编码电平为:"<<b;
			break;
		case 6:
			b=512+32*(a[4]*8+a[5]*4+a[6]*2+a[7]*1);
			cout<<"13折线A律PCM编码的编码电平为:"<<b;
			break;
		case 7:
			b=1024+64*(a[4]*8+a[5]*4+a[6]*2+a[7]*1);
			cout<<"13折线A律PCM编码的编码电平为:"<<b;
			break;
			}
			cout<<endl;	
	cout<<"13折线A律PCM编码的量化误差为:"<<(abs(abs(temp)-abs(b)))<<endl<<endl;
	}	
}	

13折线A律PCM解码的源代码:

#include <iostream>
#include <MATH.H>
using namespace std;
extern int PCM_StudentAlawDecode(unsigned char CodeValue){
	int DecodeValue = 0;
	int duannum=0;//量化段序号
	/*Add your code here*/
	int a[8];
	for (int i=0;i<8;i++){
a[7-i]=((CodeValue>>i)&0x01);//将CodeValue的值转换为二进制每次右移i位与0X01的二进制做与运算,相当于把CodeValue的值转换为二进制从低位到高位依次存入数组a中。
}
	duannum=a[1]*4+a[2]*2+a[3]+1;//求出量化段序号存入duannum中。
	switch(duannum){//根据段落码求解码电平=编码电平+各段对应量化间隔的一半
case 1:
		DecodeValue=(a[4]*8+a[5]*4+a[6]*2+a[7])+1/2;
		break;
	case 2:
		DecodeValue=16+(a[4]*8+a[5]*4+a[6]*2+a[7])+1/2;
		break;
	case 3:
		DecodeValue=32+2*(a[4]*8+a[5]*4+a[6]*2+a[7])+2/2;
				break;
		case 4:
	DecodeValue=64+4*(a[4]*8+a[5]*4+a[6]*2+a[7])+4/2;
				break;
		case 5:
	DecodeValue=128+8*(a[4]*8+a[5]*4+a[6]*2+a[7])+8/2;
				break;
		case 6:
	DecodeValue=256+16*(a[4]*8+a[5]*4+a[6]*2+a[7])+16/2;
				break;
		case 7:
	DecodeValue=512+32*(a[4]*8+a[5]*4+a[6]*2+a[7])+32/2;
				break;
		case 8:
	DecodeValue=1024+64*(a[4]*8+a[5]*4+a[6]*2+a[7])+64/2;
				break;			
	}
	if (a[0]==0){	
DecodeValue=0-DecodeValue;
	}
	return DecodeValue;
}
void main(){
int b;
unsigned char temp;
int int_temp;
while(1){
cout<<"输入13折线A律PCM编码的十进制:";
	cin>>int_temp;
	temp=int_temp;
	b=PCM_StudentAlawDecode(temp);
cout<<"7位非线性PCM编码(除极性码外)的解码电平为:"<<b<<endl<<endl;
	}	
}

4. 运行结果及分析

1️⃣ A律13折线PCM编码输出结果为:
在这里插入图片描述
2️⃣ A律13折线PCM解码输出结果为:
在这里插入图片描述


(这个是我们的通信原理的课程设计,代码思路较简单而且容易理解与系统的原理基本是对应的,有问题欢迎讨论。)

HAPPY EVERY DAY,加油!

在这里插入图片描述


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_44830040/article/details/105425305

智能推荐

SQL 调优1_show parameter dbw-程序员宅基地

文章浏览阅读440次。SQL 调优1调整的方法调整的工具内存组件调整 shared_pool data_buffer pga IO性能文件确定调整的方法:调整的流程 架构设计 建模 程序 数据库 硬件调整 每次只调整一个地方 top 消耗资源最多 执行的次数最多 执行的时间最长 达到优化的目标就不优化了 优化的过程中一定不要产生新的_show parameter dbw

ZOJ-3772 Calculate the Function(线段树,矩阵乘法)-程序员宅基地

文章浏览阅读260次。Calculate the FunctionTime Limit: 2 Seconds Memory Limit: 65536 KBYou are given a list of numbers A1 A2 .. AN and M queries. For the i-th query:The query has two parameters Li and R_calculate the function

linux命令实现git代码copy到svn仓库并提交_git文件考到svn路徑下,怎麽留下copy路徑-程序员宅基地

文章浏览阅读534次。项目需要,将git仓库master代码copy到svn仓库的主干上,需要在linux上实现,只能老老实实敲命令了。1. 解决方案 非常原始,首先创建/git目录,然后clone git仓库master最新代码,copy到/svn目录下,删除.git文件,然后使用svn add,commit到svn的分支上。2. 直接写命令:#创建git文件夹并进入目录,mkdir -p:递归创建目录,即使上级目录不存在,会按目录层级自动创建目录mkdir -p /code/..._git文件考到svn路徑下,怎麽留下copy路徑

win10linux双系统时间,win10与linux双系统切换时间不一致的调整-程序员宅基地

文章浏览阅读956次。按照Linux系统之后再切换回到win10后,我发现win10的时间不再是北京时间,而是比北京时间多了整整8小时,之后百度找到了问题来源,这里给出解决方法。如果安装了 Windows 和 Linux(比如 Ubuntu)双系统,有时会出现两个系统的时间不一致的情况。这是因为,两个操作系统对电脑硬件时间的定义不一样,Windows 认为电脑硬件时间是“本地时间”,因此它启动后直接用该时间作为“系统时..._win10+linux电脑时间不对

别浪费自己的高学历_别浪费自己的高学历,你最该拥有这些能力-程序员宅基地

文章浏览阅读237次。转自:科学堂原文链接:http://scienceroom.net/dont-waste-your-high-academic-records-666.html很多人在问念研究生能学到什么,短短的两年时间,上课学不到多少有用的,科研也没怎么搞,到底念研究生能学到什么?一开始念硕士博士的时间都是有这 些迷惘的,甚至有些人连这些问题想也没想。如果用点心思,不管我们将来搞不搞_别浪费自己的高学历,你最该拥有这些能力

【改进篇】Python实现VRP常见求解算法——量子粒子群算法(QDPSO)_python群算法求解vrptw-程序员宅基地

文章浏览阅读342次。基于python语言,实现经典量子粒子群算法(QDPSO)对车辆路径规划问题(CVRP)进行求解,优化代码结构,改进Split函数_python群算法求解vrptw

随便推点

PCB的WIP系統如何做?_pcb wipdata-程序员宅基地

文章浏览阅读2.6k次。由於最近在處理一個線路板(PCB)的軟件.由於線路板的生產要求很多,而且要經過很多的工藝流程.如果確保能正常交貨以及了解生產的各種狀態,以及了解現場各個工序的狀態,這幾乎成了PCB企業的一個難題.生產管理是整個生產的關鍵.以至於有一些生產經理,用了系統後感覺很麻煩,感覺還不如手工做得好,於是就放棄了WIP.實行手工過帳.但是走了一段時間後,感覺需要的數據不能及時了解到.不如用系統,於是WIP系統也_pcb wipdata

InnoDB: Error: io_setup() failed with EAGAIN after 5 attempts_[error] innodb: io_setup() failed with eagain afte-程序员宅基地

文章浏览阅读1.5k次。在一台服务器中以各数据库的备份文件为数据文件启动多个MySQL实例供SQL Review使用。之前运行一直没有问题(最多的时候有23个MySQL实例同时运行),后来新配置了一台服务器,启动其对应的实例时失败。部分错误日志如下:……140505 16:05:59 InnoDB: Using Linux native AIO140505 16:05:59 InnoDB: Warning: io_se..._[error] innodb: io_setup() failed with eagain after 5 attempts. [error] inno

原生js轮播图的实现_原生轮播-程序员宅基地

文章浏览阅读284次。原理就是当点击到小圆点时,得到相应的i值,这个i值也就是span的index值,我们拿他和全局变量index作比较,然后重新设置wrap.style.left的值,然后把i值复制给全局变量index,最后显示当前的小原点即可。值得注意的是这里涉及到了闭包的概念,如果直接使用for循环,则不能得到正确的结果。很多网站都有轮播图,我这里为大家简答的介绍一下,如果有些的不对的地方请大家及时提出意见,也希望给大家带来帮助。小圆点部分是那个可以点击切换部分这个是根据图片来设置圆点的个数的不是自己想设置多少。..._原生轮播

ssldump0.9b3版本的源码分析-程序员宅基地

文章浏览阅读668次。一、目录结构Base 提供一些数据收集和调试打印的功能 Common 提供一些链表、字符串结构、位域、调试、错误打印、时间戳、线程操作等功能 Dummy 无 Null 提供了分析数据的功能,跟ssl目录中的analyze部分很像,还不明白具体的用处 Ssl 对tcp连接的往返数据进行顺序解析https的过程 Wi..._ssldump0.9b3

全志H616方案香橙派orangepi zero2的26pin接口 SPI测试_香橙派zero2 的26pin 修改功能-程序员宅基地

文章浏览阅读1.2k次。1) 由 26pin 接口的原理图可知,Orange Pi Zero 2 可用的 spi 为 spi12) 先查看下 linux 系统中是否存在 spidev1.1 的设备节点,如果存在,说明 SPI1 已 经设置好了,可以直接使用3) 再在 wiringOP 的 examples 中编译 spidev_test 测试程序4) 先不短接 SPI1 的 mosi 和 miso 两个引脚,运行 spidev_test 的输出结果如下所示, 可以看到 TX 和 RX..._香橙派zero2 的26pin 修改功能

C++ 赋值、浅拷贝、深拷贝和零拷贝解析_c++零拷贝-程序员宅基地

文章浏览阅读2.3k次。1. 浅拷贝浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。2. 深拷贝深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的,示意图大致如下:3. 赋值与浅拷贝差异赋值:把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的_c++零拷贝

推荐文章

热门文章

相关标签