BPSK,QPSK的C语言仿真

本文首先给出BPSK的原理,再给出对应的C语言设计过程,并附代码。
当给出BPSK的过程后,QPSK即为分路问题,将直接给出代码。

一、什么是BPSK

BPSK可以被称为二进制相移键控,其利用载波的相位变化来传递数字信息,而振幅和频率保持不变。以初始相位0和π\piπ来表示二进制比特(符号)1和0。在传输时可以用以下波形函数表示:

s(t)=Asin⁡(ωt+φn)s\left( t \right) = A\sin \left( {\omega t + {\varphi _n}} \right)s(t)=Asin(ωt+φn​)

其中,φn\varphi _nφn​表示第nnn个符号的绝对相位,取值规则与之前所述相同。

二、BPSK仿真的问题处理

1. 流程确认

首先确定数据流的传递方式。其流程可以由以下过程表示:

由以上图片可知,仿真的难点在于信噪比和高斯噪声的加入。其他方式由低通等效原理可以省略高频调制步骤,至于其余步骤均为映射和判断的if else语句没有难度。

2. C语言随机信源的产生方式

首先应该了解C语言的随机数产生方式。
在标准C语言库stdlib.h内有rand()函数用于生成一个介于0与RAND_MAX之间的int型整数。其中RAND_MAX是一个整数,它与系统有关。
rand函数没有输入参数,由于rand函数在产生随机数前,需要系统提供的生成伪随机数序列的种子,rand根据这个种子的值产生一系列随机数。如果系统提供的种子没有变化,每次调用rand函数生成的伪随机数序列都是一样的,所以说C语言的随机是一种伪随机。
下面介绍srand函数。srand(unsigned seed)通过参数seed改变系统提供的种子值,从而可以使得每次调用rand函数生成的伪随机数序列不同,从而实现真正意义上的“随机”。通常利用系统时间来改变系统的种子值,即srand(time(NULL)),可以为rand函数提供不同的种子值,进而产生不同的随机数序列。注意,time函数包含在time.h头文件内,故声明时需要加入此文件。
具体使用时可以配合RAND_MAX得到想要范围内的随机值。
若要产生信源0,1,则使得生成的随机数除以2取余数即可。

// 信源生成函数
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define data_len XXX
void main()
{srand((unsigned int)time(NULL));int data_beforecoding[data_len];for (int i = 0; i < data_len; i++){data_beforecoding[i] = rand() % 2;}
}

3. 高斯噪声的加入

生成高斯噪声的方式我们采用Box-Muller方法,其描述如下:
如果在(0,1]\left( {0,1} \right](0,1]值域内有两个均匀分布随机变量XXX和YYY,则可以由以下运算得到正态分布随机变量ZZZ
Z=Rcos⁡θZ=R\cos\thetaZ=Rcosθ
(或Z=Rsin⁡θZ=R\sin\thetaZ=Rsinθ) 其中,R=−2ln⁡XR=\sqrt{-2\ln X}R=−2lnX​,θ=2πY\theta {\rm{ = 2}}\pi Yθ=2πY。

此时,正态随机变量Z∼N(0,1)Z \sim N\left( {0,1} \right)Z∼N(0,1)。

下面我们来证明一下:
假定随机变量X∼N(0,1)X \sim N\left( {0,1} \right)X∼N(0,1),Y∼N(0,1)Y \sim N\left( {0,1} \right)Y∼N(0,1),且相互独立,令p(X)p\left( X \right)p(X)和p(Y)p\left( Y \right)p(Y)分别为其概率密度函数,有:

p(X)=12πe−X22p\left( X \right) = \frac{1}{{\sqrt {2\pi } }}{e^{ - \frac{{{X^2}}}{2}}}p(X)=2π​1​e−2X2​
p(Y)=12πe−Y22p\left( Y \right) = \frac{1}{{\sqrt {2\pi } }}{e^{ - \frac{{{Y^2}}}{2}}}p(Y)=2π​1​e−2Y2​

联合概率密度由于独立,有

p(X,Y)=12πe−X2+Y22p\left( {X,Y} \right) = \frac{1}{{2\pi }}{e^{ - \frac{{{X^2} + {Y^2}}}{2}}}p(X,Y)=2π1​e−2X2+Y2​

对随机变量XXX和YYY作极坐标变换如下:

X=Rcos⁡θX=R\cos\thetaX=Rcosθ
Y=Rsin⁡θY=R\sin\thetaY=Rsinθ

有:
∫−∞∞∫−∞∞12πe−X2+Y22dXdY=∫02π∫0∞12πe−R22RdθdR=1\int_{ - \infty }^\infty {\int_{ - \infty }^\infty {\frac{1}{{2\pi }}{e^{ - \frac{{{X^2} + {Y^2}}}{2}}}dXdY} } = \int_0^{2\pi } {\int_0^\infty {\frac{1}{{2\pi }}{e^{ - \frac{{{R^2}}}{2}}}Rd\theta dR} } = 1∫−∞∞​∫−∞∞​2π1​e−2X2+Y2​dXdY=∫02π​∫0∞​2π1​e−2R2​RdθdR=1

由此可得随机变量RRR和θ\thetaθ的分布函数:

PR(R≤r)=∫02π∫0r12πe−R22RdθdR=1−e−r22{P_R}\left( {R \le r} \right) = \int_0^{2\pi } {\int_0^r {\frac{1}{{2\pi }}{e^{ - \frac{{{R^2}}}{2}}}Rd\theta dR} } = 1 - {e^{ - \frac{{{r^2}}}{2}}}PR​(R≤r)=∫02π​∫0r​2π1​e−2R2​RdθdR=1−e−2r2​

Pθ(θ≤ϕ)=∫0ϕ∫0∞12πe−R22RdθdR=ϕ2π{P_\theta }\left( {\theta \le \phi } \right) = \int_0^\phi {\int_0^\infty {\frac{1}{{2\pi }}{e^{ - \frac{{{R^2}}}{2}}}Rd\theta dR} } = \frac{\phi }{{2\pi }}Pθ​(θ≤ϕ)=∫0ϕ​∫0∞​2π1​e−2R2​RdθdR=2πϕ​

此时θ\thetaθ服从[0,2π]\left[ {0,2\pi } \right][0,2π]上的均匀分布,下面对RRR进行变换,使其符合均匀分布,构造

FR(r)=1−e−r22{F_R}\left( r \right) = 1 - {e^{ - \frac{{{r^2}}}{2}}}FR​(r)=1−e−2r2​

得到反函数:

R=FR−1(Z)=−2ln⁡(1−Z)R = F_R^{ - 1}\left( Z \right) = \sqrt{-2\ln \left( {1 - Z} \right)}R=FR−1​(Z)=−2ln(1−Z)​

当随机变量Z∼U[0,1]Z \sim U\left[ {0,1} \right]Z∼U[0,1],RRR的分布函数为FR{F_R}FR​,同样的,1−Z∼U[0,1]1-Z \sim U\left[ {0,1} \right]1−Z∼U[0,1],因此可以选择两个变量U1U_1U1​和U2U_2U2​,使得

θ=2πU1\theta = 2\pi {U_1}θ=2πU1​
1−Z=U21-Z =U_21−Z=U2​

R=−2ln⁡U2R= \sqrt{-2\ln U_2 }R=−2lnU2​​

由此带入X=Rcos⁡θX=R\cos\thetaX=Rcosθ,Y=Rsin⁡θY=R\sin\thetaY=Rsinθ,即可证明随机变量X∼N(0,1)X \sim N\left( {0,1} \right)X∼N(0,1),Y∼N(0,1)Y \sim N\left( {0,1} \right)Y∼N(0,1)。由此可知假设条件正确。

证明完毕后,我们可以根据此定理来构造高斯随机变量:先独立构造分布为U[0,1]U\left[ {0,1} \right]U[0,1]上的变量XXX和YYY;随后进行运算:

Z=−2ln⁡Xsin⁡(2πY)Z = \sqrt { - 2\ln X} \sin \left( {2\pi Y} \right)Z=−2lnX​sin(2πY)

则有Z∼N(0,1)Z \sim N\left( {0,1} \right)Z∼N(0,1)。

由此可得构造高斯随机变量的函数:

// Gauss型变量生成函数
double Gaussianrand()
{double U, V, Z;U = (double)(rand() + 1.0) / (double)(RAND_MAX + 1.0);V = (double)(rand() + 1.0) / (double)(RAND_MAX + 1.0);Z = sqrt(-2.0 * log(U)) * sin(2.0 * pi * V);return Z;
}

其中加一(+1.0)是为了防止产生0使得对数运算产生错误;使用墙砖是为了防止整型除以整形得到整形(如3/2=1,3.0/2.0=1.5),具体参见C语言数据类型运算。

4. 信噪比计算

首先应确定,高斯白噪声的功率谱密度,噪声功率与方差的关系为:
P(f)=N02=σ2P\left( f \right) = \frac{{{N_0}}}{2} = {\sigma ^2}P(f)=2N0​​=σ2
而高斯变量有:
X∼N(0,1)⇔μX+σ∼N(μ,σ2)X \sim N\left( {0,1} \right) \Leftrightarrow \mu X + \sigma \sim N\left( {\mu ,{\sigma ^2}} \right)X∼N(0,1)⇔μX+σ∼N(μ,σ2)
故设信噪比为EbN0_dB(以分贝为单位),首先确定Eb = 1,转化EbN0的单位,有EbN0 = 10 ^ (EbN0_dB / 10)。之后得到N0:
N0=Eb/EbN0=Eb/10EbN0(dB)10{N_0} = {E_b}/{E_b}{N_0} = {E_b}/{10^{\frac{{{E_b}{N_0}\left( {{\rm{dB}}} \right)}}{{10}}}}N0​=Eb​/Eb​N0​=Eb​/1010Eb​N0​(dB)​
之后有:
σ=N0/2\sigma {\rm{ = }}\sqrt {{N_0}/2}σ=N0​/2​
由此可构造符合信噪比要求的高斯白噪声。

三、BPSK仿真结果和理论值对比

显然,判决方式我们选择相干解调。理论误码率为:
Pe=0.5erfc(r){P_e} = 0.5{\mathop{\rm erfc}\nolimits} \left( {\sqrt r } \right)Pe​=0.5erfc(r​)
其推导参见通信原理内数字通信系统抗噪声性能有关章节。
其中rrr表示码元信噪比E/N0E/{N_0}E/N0​(单位不是dB),其与比特信噪比Eb/N0E_b/{N_0}Eb​/N0​的关系如下:
E/N0=r/kE/{N_0} = r/kE/N0​=r/k
其中kkk表示每个码元所包含的比特数,由于调制是BPSK,进制数M=1M=1M=1,故k=1k=1k=1。
经过仿真2000000次,得到的仿真结果和理论值对比如下:

比特信噪比 仿真结果 理论结果
0 0.078697 0.078693
1 0.056417 0.056264
2 0.037619 0.037483
3 0.023006 0.022876
4 0.012448 0.012549
5 0.005925 0.006007
6 0.002422 0.023953
7 0.000755 0.007775
8 0.000196 0.000191
9 0.000039 0.000038
10 0.000000 0.000007

对比可知仿真结果差距不大,当仿真次数增大,按中心极限定理差距将逐渐缩小。

五、BPSK仿真程序代码

代码封装部分省略,这里给出的代码会存在堆栈溢出问题,但解决办法可以通过设置全局变量和函数流程化封装解决。

//BPSK调制 —— C code
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define data_len 1000000   //比特长
#define pi 3.1415926535
#define EbN0_MAX 11     //信噪比 0 - 10double Gaussianrand();
double Erdproduce(double EbN0_dB);int main()
{srand((unsigned int)time(NULL));double EbN0_dB, Erd;for (int i = 0; i < EbN0_MAX; i++){EbN0_dB = (double)i;Erd = Erdproduce(EbN0_dB);printf("%lf \n", Erd);}return 0;
}double Erdproduce(double EbN0_dB)
{int data_beforecoding[data_len];       //信源for (int i = 0; i < data_len; i++){data_beforecoding[i] = rand() % 2;}int data_coding[data_len];             //调制for (int i = 0; i < data_len; i++){if (data_beforecoding[i] == 0)data_coding[i] = 1;elsedata_coding[i] = -1;}double Gaussnoice[data_len];for (int i = 0; i < data_len; i++){Gaussnoice[i] = Gaussianrand();}double Eb = 1;double EbN0;EbN0 = pow(10, EbN0_dB / 10.0);double N0 = Eb / EbN0;double sigma = sqrt(0.5 * N0);for (int i = 0; i < data_len; i++){Gaussnoice[i] = Gaussnoice[i] * sigma;}//加入高斯噪声double re_symbol[data_len];for (int i = 0; i < data_len; i++){re_symbol[i] = data_coding[i] + Gaussnoice[i];}//判决int re_data[data_len];for (int i = 0; i < data_len; i++){if (re_symbol[i] < 0)re_data[i] = 1;elsere_data[i] = 0;}//误比特统计double Erd = 0.0;int Nrd = 0;for (int i = 0; i < data_len; i++){if (re_data[i] != data_beforecoding[i])Nrd = Nrd + 1;}Erd = (double)Nrd / (double)data_len;return Erd;
}
//高斯白噪声子函数
double Gaussianrand()
{double U, V, Z;U = (double)(rand() + 1.0) / (double)(RAND_MAX + 1.0) ;V = (double)(rand() + 1.0) / (double)(RAND_MAX + 1.0) ;Z = sqrt(-2.0 * log(U)) * sin(2.0 * pi * V);return Z;
}

六、QPSK仿真程序

QPSK是经过封装后的程序,避免了溢出问题。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#define pi 3.1415926535
#define data_len 1000000
#define EbN0_dB_MAX 11
#define k 2                 //符号比特数
#define M 2                 //进制数const int symbol_len = data_len / k;
int EbN0_dB;
const int Eb = 1;
int data_bfcoding[data_len], data_decoding[data_len];
int symbol_bfcoding[data_len];
int symbol_I[symbol_len], symbol_Q[symbol_len];
double symbol_I_AWGN[symbol_len], symbol_Q_AWGN[symbol_len];
int symbol_I_decoding[symbol_len], symbol_Q_decoding[symbol_len];
void Data_generate();
void Symbol_generate();
void Modulation();
double Gaussnoise();
void AWGN(int EbN0_dB);
void Demodulation();
double Erdsimulation();int main()
{int j = 0;double Erd; srand((unsigned int(time(NULL))));for (int j = 0; j < EbN0_dB_MAX; j++){EbN0_dB = j;Data_generate();Symbol_generate();Modulation();AWGN(EbN0_dB);Demodulation();Erd = Erdsimulation();printf("%f \n", Erd);}return 0;}void Data_generate()
{for (int i = 0; i < data_len; i++){data_bfcoding[i] = rand() % 2;}
}void Symbol_generate()
{for (int i = 0; i < data_len; i++){if (i % 2 == 0)symbol_I[i / 2] = data_bfcoding[i];elsesymbol_Q[i / 2] = data_bfcoding[i];}
}void Modulation()
{for (int i = 0; i < symbol_len; i++){symbol_I[i] = 1 - 2 * symbol_I[i];symbol_Q[i] = 1 - 2 * symbol_Q[i];}
}double Gaussnoise()
{double U, V, Z;U = (double)(rand() + 1.0) / (double)(RAND_MAX + 1.0);V = (double)(rand() + 1.0) / (double)(RAND_MAX + 1.0);Z = sqrt(-2 * log(U)) * sin(2 * pi * V);return Z;
}void AWGN(int EbN0_dB)
{double EbN0 = pow(10, (double)EbN0_dB / 10);double N0 = Eb / EbN0;double sigma = sqrt(0.5 * N0);for (int i = 0; i < symbol_len; i++){symbol_I_AWGN[i] = (double)symbol_I[i] + Gaussnoise() * sigma;symbol_Q_AWGN[i] = (double)symbol_Q[i] + Gaussnoise() * sigma;}
}void Demodulation()
{for (int i = 0; i < symbol_len; i++){if (symbol_I_AWGN[i] < 0.0){symbol_I_decoding[i] = 1;}else{symbol_I_decoding[i] = 0;}if (symbol_Q_AWGN[i] < 0.0){symbol_Q_decoding[i] = 1;}else{symbol_Q_decoding[i] = 0;}}for (int i = 0; i < data_len; i++){if (i % 2 == 0)data_decoding[i] = symbol_I_decoding[i / 2];elsedata_decoding[i] = symbol_Q_decoding[i / 2];}}double Erdsimulation()
{int Nrd = 0;double Erd_temp;for (int i = 0; i < data_len; i++){if (data_decoding[i] != data_bfcoding[i])Nrd++;}Erd_temp = (double)Nrd / (double)data_len;return Erd_temp;
}

七、参考资料

  1. BPSK调制与解调-MATLAB基带仿真
  2. C语言随机数:rand()和srand(time(NULL))的使用
  3. Box-Muller变换原理详解

BPSK,QPSK的C语言仿真相关推荐

  1. BPSK,QPSK,2FSK,16QAM,64QAM信号在高斯信道与瑞利信道下的误码率性能仿真

    BPSK,QPSK,2FSK,16QAM,64QAM信号在高斯信道与瑞利信道下的误码率性能仿真_南大小王-CSDN博客 16QAM调制解调仿真(matlab,详细介绍仿真方案的设计.结果及结论.完整代 ...

  2. 通过matlab对比不同调制方式下的球形译码误码率仿真,包括BPSK,QPSK,8PSK,4QAM以及16QAM

    目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 在BLAST检测中,目前采用的ZF(迫零) 算法,MMSE(最小均方误差) 算法, OSIC(排序连 ...

  3. 基于Simulink对调制-解调系统的仿真(BASK+BFSK+BPSK+QPSK)

    目录 目 录 1 一 .调制-解调系统的基本原理 3 1.1 BASK 3 1.1.1 调制原理 3 1.1.2 解调原理 3 1.2 BFSK 3 1.2.1 调制原理 3 1.2.2 解调原理 4 ...

  4. 基于MATLAB的自适应调制解调通信系统的误码率仿真,对比BPSK,QPSK,16QAM,64QAM

    目录 1.算法仿真效果 2.MATLAB核心程序 3.算法涉及理论知识概要 4.完整MATLAB 1.算法仿真效果 matlab2022a仿真结果如下: 2.MATLAB核心程序 .......... ...

  5. 简陋版C语言仿真通讯录之动态内存开辟版本

    简陋版C语言仿真通讯录 https://blog.csdn.net/csdn_kou/article/details/80287640 简陋版C语言仿真通讯录之动态内存开辟版本 给Contact结构体 ...

  6. 数字调制BPSK/QPSK/QAM/ASK/FSK/PSK

    文章目录 BPSK QPSK BPSK&QPSK比较 QAM 16-QAM vs 64-QAM vs 256-QAM 512 QAM vs 1024 QAM vs 2048 QAM vs 40 ...

  7. matlab 通讯系统设计与仿真,基于BPSK通信系统的设计与仿真

    基于BPSK通信系统的设计与仿真 一.BPSK信号调制原理 1.1  系统原理 file:///C:\Users\ADMINI~1.KGH\AppData\Local\Temp\ksohtml\wps ...

  8. 开源RISC-V处理器(蜂鸟E203)学习(五)A100T-FPGA 移植蜂鸟Hbirdv2,实现Centos下调试器USB识别以及程序编译烧写,并进行C语言仿真

    1.简述 最近购买了一块适合做原型验证FPGA板卡,板卡接口和外设比较丰富,十分适合跑一些小型的SOC工程,比如蜂鸟E203:板卡自带FPGA烧写器和软核CPU的JATG调试器,还有USB接口的UAR ...

  9. DSP定点运算之数字信号处理算法的定点化及其C语言仿真(转)

    DSP广义上指数字信号处理理论(Digital Signal Processing),狭义上指数字 信号处理器(Digital Signal Processor).数字信号处理理论广泛应用于语音.图象 ...

最新文章

  1. Microbiome:南土所梁玉婷组-稻田土壤产甲烷菌的共存模式
  2. 量子信息技术研究现状与未来
  3. 为什么要用hadoop
  4. 利用构造函数进行简化类初始化
  5. ipsec ***概念(一)
  6. python如何读取数据保存为新格式_python,初学者应用实例:读取文件中的数据,将将北京时间转换成世界时间,再保存成新的CSV格式文件...
  7. node 存储过程_用Node.js操作跨平台数据库Firebird
  8. IOT(34)---物连网体系结构
  9. 生成.o linux,JaxoDraw下载 费曼图生成工具JaxoDraw for linux v2.1.0 官方安装版 下载-脚本之家...
  10. java计算机二级内容总结
  11. 在条码打印软件中如何绘制圆形
  12. 三菱plc pwm指令_三菱PLC高速处理指令编程(新手教学)
  13. L298N和TB6612FNG模块控制直流电机
  14. Angular SSR 探究
  15. 为什么你读专业技术书逐渐焦虑,读不下去书怎么办?
  16. easyui01人门基础
  17. 不懂技术自己也可以轻松制作App
  18. Android基础——多媒体编程
  19. Discriminative Correlation Filters (DCF)
  20. 力扣 2212. 射箭比赛中的最大得分

热门文章

  1. 装机员Ghost Win8.1 64位装机8月版
  2. python数字排序_python数字排序
  3. css3 cheatsheet,Complete CSS Cheat Sheet
  4. 史上最全SD-WAN供应方大盘点(下)
  5. 迷你世界api 系统事件
  6. 国产 工程机械控制器SPC-SFMC-X2424A
  7. S3C6410移植linux4.17内核(一)
  8. 存储fc交换机配置小结
  9. VSG中的虚拟调速器和无功-电压调节
  10. 软件质量管理的方法、工具和保证