QPSK调制的C实现

正交相移键控qpsk



正交相移键控(Quadrature Phase Shift Keyin,QPSK)是一种数字调制方式。它分为绝对相移和相对相移两种。由于绝对相移方式存在相位模糊问题,所以在实际中主要采用相对移相方式DQPSK。目前已经广泛应用于无线通信中,成为现代通信中一种十分重要的调制解调方式。
外文名 Quadrature Phase Shift Keying 简    介 卫星数字信号调制方式 原    理 实际的调谐解调电路 -特点 信号分布与调制数字比特之间映射 简    称 QPSK
目录
1 QPSK-简介
2 QPSK-原理
3 QPSK-特点
4 QPSK-OQPSK
5 QPSK-应用
QPSK-简介


  在数字信号的调制方式中QPSK是最常用的一种卫星数字信号调制方式,它具有较高的频谱利用率、较强的抗干扰性、在电路上实现也较为简单。偏移四相相移键控信号简称“O-QPSK”。全称为offset QPSK,也就是相对移相方式OQPSK。
相关:在HFC网络架构中,从用户线缆调制解调器发往上行通方式调制,并用TDMA方式复用到上行通道。
相关:在基于DVB-S的卫星通信电视系统中,卫星输出的电磁波信号就是使用QPSK调制方式的[1] 
QPSK-原理
QPSK数字解调包括:模数转换、抽取或插值、匹配滤波、时钟和载波恢复等。
在实际的调谐解调电路中,采用的是非相干载波解调,本振信号与发射端的载波信号存在频率偏差和相位抖动,因而解调出来的模拟I、Q基带信号是带有载波误差的信号。这样的模拟基带信号即使采用定时准确的时钟进行取样判决,得到的数字信号也不是原来发射端的调制信号,误差的积累将导致抽样判决后的误码率增大,因此数字QPSK解调电路要对载波误差进行补偿,减少非相干载波解调带来的影响。此外,ADC的取样时钟也不是从信号中提取的,当取样时钟与输入的数据不同步时,取样将不在最佳取样时刻进行所得到的取样值的统计信噪比就不是最高,误码率就高,因此,在电路中还需要恢复出一个与输入符号率同步的时钟,来校正固定取样带来的样点误差,并且准确的位定时信息可为数字解调后的信道纠错解码提供正确的时钟。校正办法是由定时恢复和载波恢复模块通过某种算法产生定时和载波误差,插值或抽取器在定时和载波误差信号的控制下,对A/D转换后的取样值进行抽取或插值滤波,得到信号在最佳取样点的值,不同芯片采用的算法不尽相同,例如可以采用据辅助法(DA)载波相位和定时相位联合估计的最大似然算法。
QPSK-特点
数字调制用“星座图”来描述,星座图中定义了一种调制技术的两个基本参数:
(1)信号分布;(2)与调制数字比特之间的映射关系
星座图中规定了星座点与传输比特间的对应关系,这种关系称为“映射”,一种调制技术的特性可由信号分布和映射完全定义,即可由星座图来完全定义。四相相移调制是利用载波的四种不同相位差来表征输入的数字信息,是四进制移相键控。QPSK是在M=4时的调相技术,它规定了四种载波相位,分别为45°,135°,225°,315°,调制器输入的数据是二进制数字序列,为了能和四进制的载波相位配合起来,则需要把二进制数据变换为四进制数据,这就是说需要把二进制数字序列中每两个比特分成一组,共有四种组合,即00,01,10,11,其中每一组称为双比特码元。每一个双比特码元是由两位二进制信息比特组成,它们分别代表四进制四个符号中的一个符号。QPSK中每次调制可传输2个信息比特,这些信息比特是通过载波的四种相位来传递的。解调器根据星座图及接收到的载波信号的相位来判断发送端发送的信息比特。
首先将输入的串行二进制信息序列经串-并变换,变成m=log2M个并行数据流,每一路的数据率是R/m,R是串行输入码的数据率。I/Q信号发生器将每一个m比特的字节转换成一对(pn,qn)数字,分成两路速率减半的序列,电平发生器分别产生双极性二电平信号I(t)和Q(t),然后对coswct和sinwct进行调制,相加后即得到QPSK信号。
QPSK是一种频谱利用率高、抗干扰性强的数调制方式, 它被广泛应用于各种通信系统中. 适合卫星广播。例如,数字卫星电视DVB-S2 标准中,信道噪声门限低至4. 5 dB,传输码率达到45M b[1] 


  实施
采用QPSK 调制方式,同时保证了信号传输的效率和误码性能。
一般的QPSK的实施,也表明高阶PSK的实施。在星座图中的正弦和余弦波用来传输方面的书面符号:
这就产生了四个阶段π/ 4,3π/ 4,5π/ 4和7π/ 4需要。
这个结果与单位的基础上功能在一个两维的信号空间被用作信号的同相分量和正交分量信号的第二首的基础功能。
因此,信号星座组成的信号空间4点,1/2的因素表明,两家运营商之间的分裂,同样的总功率。
这些基础功能,为BPSK比较清楚地表明如何观看可以作为两个独立的BPSK信号的QPSK。注意的BPSK信号空间分不需要分裂BPSK的星座图中显示的两家运营商在该计划的符号(位)能源的。
QPSK系统,可以实现在许多方面。发射机和接收机结构的主要组成部分的说明如下。
QPSK概念发射机结构。的二进制数据流分割成相和正交相的组成部分。这些都是再分别调制到两个正交的基函数。在此实现中,两个血窦。之后,这两个信号叠加,产生的信号是QPSK信号。注意:使用极不返回到零编码。可以摆在这些编码器的二进制数据源,但已放置后,说明涉及数字调制的数字和模拟信号之间的概念差异。
对于QPSK接收机结构。匹配的过滤器,可以与相关器代替。每个检测装置使用的参考阈值,以确定是否检测到1或0。
误码率
QPSK的,虽然可以作为解调看,这是比较容易看到它作为两个独立的调制正交载波。这种解释,偶数(或奇数)位用于调节承运人在相位分量,而奇数(或偶数)位被用来调制载波的正交相位分量。BPSK的两家航空公司,它们可以是独立的解调。
因此,QPSK的误码概率是相同的BPSK:
然而,为了达到相同的概率为BPSK的误码,QPSK的使用电源(因为两位同时传输)的两倍。
符号错误率计算公式如下:


  QPSK时域信号
如果信号信噪比高(实际QPSK系统是必要的)符号错误的概率可近似:
调制信号为一个随机的二进制数据流的短段如下。两个载波是一个余弦波和正弦波,通过信号空间分析上述表示。在这里,奇数位已被分配到同相分量和正交分量(以1号的第一个位)的偶数位。总的信号- 两个组成部分的总和- 显示在底部。可以看出,相位跳变的PSK改变了每个组件在每个位周期的开始阶段。仅最上面的波形匹配的BPSK上面给出的描述。
用于QPSK的时序图。时间轴下方所示的二进制数据流。两个组件用自己的位分配的信号显示的顶部和总,在底部的混合信号。注意:在第一阶段的一些位期间边界的突然变化。
这个波形传达的二进制数据是:1 1 0 0 0 1 1 0。
奇数位,在这里强调,在相分量:11000110
即使位,在这里强调,作出贡献的正交相位分量:11000110
QPSK-OQPSK
OQPSK是在QPSK基础上发展起来的一种恒包络数字调制技术。恒包络技术是指已调波的包络保持为恒定,它与多进制调制是从不同的两个角度来考虑调制技术的。恒包络技术所产生的已调波经过发送带限后,当通过非线性部件时,只产生很小的频谱扩展。这种形式的已调波具有两个主要特点,其一是包络恒定或起伏很小;其二是已调波频谱具有高频快速滚降特性,或者说已调波旁瓣很小,甚至几乎没有旁瓣。采用这种技术已实现了多种调制方式。OQPSK信号,它的频带利用率较高,理论值达1b/s/Hz。在QPSK中,当码组0011或0110时,产生180°的载波相位跳变。这种相位跳变引起包络起伏,当通过非线性部件后,使已经滤除的带外分量又被恢复出来,导致频谱扩展,增加对相邻波道的干扰。为了消除180°的相位跳变,在QPSK基础上提出了OQPSK。
一个已调波的频谱特性与其相位路径有着密切的关系,因此,为了控制已调波的频率特性,必须控制它的相位特性。恒包络调制技术的发展正是始终围绕着进一步改善已调波的相位路径这一中心进行的。
OQPSK也称为偏移四相相移键控,是QPSK的改进型。它与QPSK有同样的相位关系,也是把输入码流分成两路,然后进行正交调制。不同点在于它将同相和正交两支路的码流在时间上错开了半个码元周期。由于两支路码元半周期的偏移,每次只有一路可能发生极性翻转,不会发生两支路码元极性同时翻转的现象。因此,OQPSK信号相位只能跳变0°、±90°,不会出现180°的相位跳变。
QPSK-应用
QPSK数字电视调制器在对数据流的处理上采用能量扩散的随机化处理、RS编码、卷积交织、收缩卷积编码、调制前的基带成形处理等,保证了数据的传输性能。QPSK数字电视调制器采用了先进的数字信号处理技术,完全符合DVB-S标准,接收端可直接用数字卫星接收机进行接收。它不但能取得较高的频谱利用率,具有很强的抗干扰性和较高的性能价格比,而且和模拟FM微波设备也能很好的兼容。
性能特点:
1、进行原有的电视微波改造,可用30M带宽传送5至8套DVD效果的图像;
2、用调频微波的价格达到MMDS的效果,实现全向发射;
3、可进行数字加密,对图象绝无任何损伤。
中国的3G制式(CDMA2000,WCDMA,TD-SCDMA)均在下行链路上采用QPSK调制。
========

C语言实现QPSK

[cpp]  view plain  copy
  1. #include "math.h"  
  2. #include "stdlib.h"  
  3. #include "stdio.h"  
  4. #include  "time.h"  
  5. #include  "malloc.h"  
  6. #include  "string.h"  
  7. #include  "iostream.h"  
  8.   
  9. #define source_length 1000000   
  10. #define symbol_length source_length/2  
  11. #define SNR_start 1  
  12. #define SNR_end 10  
  13. #define SNR_step 1   
  14. #define PI 3.1415926  
  15. #define Coderate 1  
  16.   
  17. typedef struct {  
  18.     double Rpart;  
  19.     double Ipart;  
  20. }complex;  
  21.   
  22.  int source[source_length];//message(),modulate(),error()  
  23.  int change[source_length];//modulate()  
  24.  int resource[source_length];    //demodulate(),error()  
  25.  complex modulatesym[symbol_length];   //demodulate(),channel(),moudulate()  
  26.  int snr;//channel(),error()  
  27. int errorbit, errorsym;//error()  
  28.  double BER,SER;//error()  
  29.   
  30. void message();  
  31. void modulate(int source[source_length]);  
  32. void channel(complex modulatesym[symbol_length],int snr);  
  33. void demodulate();  
  34. void error();  
  35.   
  36. //随机信号产生  
  37. void message()  
  38. {  
  39.     int i;  
  40.     //以当前时间作为时间种子  
  41.     srand((unsigned)time(NULL));  
  42.     //产生0,1随机信号  
  43.     for(i=0;i<source_length;i++)  
  44.     { source[i]=rand()%2;  
  45.         //cout<<source[i];  
  46.     }  
  47.     //cout<<endl;  
  48. }  
  49.   
  50. //调制  
  51. void modulate(int source[source_length])  
  52. {  
  53.     int i,j;  
  54.     //0->-1,1->1  
  55.   for(i=0;i<source_length;i++)  
  56.   {     
  57.     change[i]=1-2*source[i];  
  58.       
  59.   }       
  60.       
  61.    for(j=0;j<symbol_length;j++)  
  62.    {     
  63.        modulatesym[j].Rpart=change[2*j];//cout<<change[2*j];  
  64.        modulatesym[j].Ipart=change[2*j+1];//cout<<change[2*j+1];  
  65.    }  
  66.   // cout<<endl;  
  67. }  
  68.   
  69. //调制信号通过信道  
  70. void channel(complex modulatesym[],int snr)  
  71. {  
  72.     long int j;  
  73.     double r1,r2;  
  74.     double amp,phase;  
  75.     double sn,SNR,noise[2];  
  76.     SNR=snr+10*log10((double)Coderate);  
  77.     sn=pow(10.0,SNR/10.0);  
  78.     for(j=0;j<symbol_length;j++)  
  79.     {  
  80.         r1=(double)rand()/RAND_MAX;  
  81.         r2=(double)rand()/RAND_MAX;  
  82.         if(r1<=1.0e-8)   r1=1.0e-8; //防止出现log0的操作  
  83.         phase=2.0*PI*r2;  
  84.         amp=sqrt(-log(r1)/sn);  
  85.         noise[0]=amp*cos(phase);  
  86.         noise[1]=amp*sin(phase);  
  87.         modulatesym[j].Rpart=modulatesym[j].Rpart+noise[0];//cout<<modulatesym[j].Rpart;  
  88.         modulatesym[j].Ipart=modulatesym[j].Ipart+noise[1];//cout<<modulatesym[j].Ipart;  
  89.           
  90.     }  
  91.     //cout<<endl;  
  92. }  
  93.   
  94. //解调  
  95. void demodulate()  
  96. {      
  97.     for(int j=0;j<symbol_length;j++)  
  98.     {  
  99.        if (modulatesym[j].Rpart>0)  
  100.           resource[2*j]=0;  
  101.        else //if(modulatesym[j].Rpart<=0)  
  102.            resource[2*j]=1;  
  103.     }  
  104.     for(int i=0;i<symbol_length;i++)  
  105.     {  
  106.        if (modulatesym[i].Ipart>0)  
  107.            resource[2*i+1]=0;  
  108.        else //if(modulatesym[j].Ipart<=0)  
  109.            resource[2*i+1]=1;  
  110.        }  
  111. }  
  112.   
  113. void error()  
  114. {  
  115.   long int i,j;  
  116.   errorbit=0;  
  117.   errorsym=0;  
  118.   
  119.   for(i=0;i<source_length;i++)  
  120.   { if(resource[i]!=source[i])  
  121.         errorbit++;  
  122.   }  
  123.   for(j=0;j<=symbol_length;j++)  
  124.   {  
  125.       if(resource[2*j]!=source[2*j]||resource[2*j+1]!=source[2*j+1])  
  126.           errorsym++;  
  127.   }  
  128.   
  129.   BER=(double)errorbit/source_length;  
  130.   SER=(double)errorsym/symbol_length;  
  131. cout<<"snr="<<snr<<endl;  
  132. cout<<"source_length="<<source_length<<endl;  
  133. cout<<"symbol_length="<<symbol_length<<endl;  
  134. cout<<"errorbit="<<errorbit<<endl;  
  135. cout<<"errorsym="<<errorsym<<endl;  
  136. cout<<"BER="<<BER<<endl;  
  137. cout<<"SER="<<SER<<endl;  
  138. }  
  139.   
  140. void main()  
  141. {  
  142.     for(snr=SNR_start;snr<=SNR_end;snr+=SNR_step)  
  143.           
  144.     {  
  145.         message();  
  146.           
  147.         modulate(source);  
  148.         channel(modulatesym,snr);  
  149.         demodulate();  
  150.         /*for(int i=0;i<source_length;i++) 
  151.                 {  
  152.                     cout<<resource[i]; 
  153.                 } 
  154.         cout<<endl;*/  
  155.         error();  
  156.     }     
  157. }  


========

C++ 实现QPSK


[cpp]  view plain  copy
  1. #include<iostream>  
  2. #include<time.h>  
  3. using namespace std;  
  4.   
  5. #define source_length 1000000   
  6. #define symbol_length source_length/2  
  7. #define SNR_start 1  
  8. #define SNR_end 10  
  9. #define SNR_step 1   
  10. #define PI 3.1415926  
  11. #define Coderate 1  
  12.   
  13. typedef struct {  
  14.     double Rpart;  
  15.     double Ipart;  
  16. }complex;  
  17.   
  18. int source[source_length];  
  19. int change[source_length];  
  20. int resource[source_length];    
  21. complex modulatesym[symbol_length];     
  22. int snr;  
  23. int errorbit, errorsym;  
  24. double BER, SER;  
  25.   
  26. //随机信号产生  
  27. void message()  
  28. {  
  29.     int i;  
  30.     //以当前时间作为时间种子  
  31.     srand((unsigned)time(NULL));  
  32.     //产生0,1随机信号  
  33.     for (i = 0; i<source_length; i++)  
  34.     {  
  35.         source[i] = rand() % 2;  
  36.         //cout<<source[i];  
  37.     }  
  38.     //cout<<endl;  
  39. }  
  40.   
  41. //调制  
  42. void modulate(int source[source_length])  
  43. {  
  44.     int i, j;  
  45.     //0->-1,1->1  
  46.     for (i = 0; i<source_length; i++)  
  47.     {  
  48.         change[i] = 1 - 2 * source[i];  
  49.     }  
  50.   
  51.     for (j = 0; j<symbol_length; j++)  
  52.     {  
  53.         modulatesym[j].Rpart = change[2 * j];//cout<<change[2*j];  
  54.         modulatesym[j].Ipart = change[2 * j + 1];//cout<<change[2*j+1];  
  55.     }  
  56.     // cout<<endl;  
  57. }  
  58.   
  59. //解调  
  60. void demodulate()  
  61. {  
  62.     for (int j = 0; j<symbol_length; j++)  
  63.     {  
  64.         if (modulatesym[j].Rpart>0)  
  65.             resource[2 * j] = 0;  
  66.         else //if(modulatesym[j].Rpart<=0)  
  67.             resource[2 * j] = 1;  
  68.     }  
  69.     for (int i = 0; i<symbol_length; i++)  
  70.     {  
  71.         if (modulatesym[i].Ipart>0)  
  72.             resource[2 * i + 1] = 0;  
  73.         else //if(modulatesym[j].Ipart<=0)  
  74.             resource[2 * i + 1] = 1;  
  75.     }  
  76. }  
  77.   
  78. //调制信号通过信道  
  79. void channel(complex modulatesym[], int snr)  
  80. {  
  81.     long int j;  
  82.     double r1, r2;  
  83.     double amp, phase;  
  84.     double sn, SNR, noise[2];  
  85.     SNR = snr + 10 * log10((double)Coderate);  
  86.     sn = pow(10.0, SNR / 10.0);  
  87.     for (j = 0; j<symbol_length; j++)  
  88.     {  
  89.         r1 = (double)rand() / RAND_MAX;  
  90.         r2 = (double)rand() / RAND_MAX;  
  91.         if (r1 <= 1.0e-8)    r1 = 1.0e-8; //防止出现log0的操作  
  92.         phase = 2.0*PI*r2;  
  93.         amp = sqrt(-log(r1) / sn);  
  94.         noise[0] = amp*cos(phase);  
  95.         noise[1] = amp*sin(phase);  
  96.         modulatesym[j].Rpart = modulatesym[j].Rpart + noise[0];//cout<<modulatesym[j].Rpart;  
  97.         modulatesym[j].Ipart = modulatesym[j].Ipart + noise[1];//cout<<modulatesym[j].Ipart;  
  98.     }  
  99.     //cout<<endl;  
  100. }  
  101.   
  102. void error()  
  103. {  
  104.     long int i, j;  
  105.     errorbit = 0;  
  106.     errorsym = 0;  
  107.   
  108.     for (i = 0; i<source_length; i++)  
  109.     {  
  110.         if (resource[i] != source[i])  
  111.             errorbit++;  
  112.     }  
  113.     for (j = 0; j <= symbol_length; j++)  
  114.     {  
  115.         if (resource[2 * j] != source[2 * j] || resource[2 * j + 1] != source[2 * j + 1])  
  116.             errorsym++;  
  117.     }  
  118.   
  119.     BER = (double)errorbit / source_length;  
  120.     SER = (double)errorsym / symbol_length;  
  121.     cout << "snr=" << snr << endl;  
  122.     cout << "source_length=" << source_length << endl;  
  123.     cout << "symbol_length=" << symbol_length << endl;  
  124.     cout << "errorbit=" << errorbit << endl;  
  125.     cout << "errorsym=" << errorsym << endl;  
  126.     cout << "BER=" << BER << endl;  
  127.     cout << "SER=" << SER << endl;  
  128. }  
  129.   
  130. int main()  
  131. {  
  132.     message();  
  133.     modulate(source);  
  134.     channel(modulatesym, snr);  
  135.     //cout << endl;  
  136.     demodulate();  
  137.     //for (int i = 0; i < source_length; i++)cout << resource[i];  
  138.     error();  
  139.     return 0;  
  140. }  

猜你喜欢

转载自blog.csdn.net/weixin_39878297/article/details/80233941
今日推荐