基于jupyter notebook的python编程-----通过python编程实现信号传输QPSK的调制与解调


在进行移动通信原理的学习中,必然会学习QPSK的调制与解调,对于QPSK的调制与解调,我们既要学习QPSK调制的实验的原理,也要学会通过代码进行QPSK实验原理的模拟,在教学中,大多数是通过matlab代码进行通信实验的仿真,但matlab能够实现的东西,python代码也一定能够解决,本次实验 ,林君学长将通过python代码,进行QPSK的调制与解调的实验模拟

一、QPSK调制解调原理

1、什么是QPSK?

1)、四相相移键控信号简称“QPSK”。它分为绝对相移和相对相移两种。由于绝对相移方式存在相位模糊问题,所以在实际中主要采用相对移相方式QDPSK。它具有一系列独特的优点,目前已经广泛应用于无线通信中,成为现代通信中一种十分重要的调制解调方式。

QPSK是英文Quadrature Phase Shift
Keying的缩略语简称,意为正交相移键控,是一种数字调制方式。在数字信号的调制方式中QPSK四相移键控是目前最常用的一种卫星数字信号调制方式,它具有较高的频谱利用率、较强的抗干扰性、在电路上实现也较为简单

2、QPSK调制原理

1)、QPSK调制原理
SK信号的正弦载波有4个可能的离散相位状态,每个载波相位携带2个二进制符号,其信号表示式为: s i ( t ) = A c o s ( w s t + θ ) s_i(t)=Acos(w_st+θ)
在0到 T s T_s 之间,i=1,2,3,4中取值。其中 T s T_s 为四进制符号间隔(i=1,2,3,4)为正弦载波的相位,有四种可能的状态
2)、QPSK调制原理框图
在这里插入图片描述

3、QPSK解调原理

1)、QPSK解调原理
QPSK数字解调包括:模数转换、抽取或插值、匹配滤波、时钟和载波恢复等。
在实际的调谐解调电路中,采用的是非相干载波解调,本振信号与发射端的载波信号存在频率偏差和相位抖动,因而解调出来的模拟I、Q基带信号是带有载波误差的信号。这样的模拟基带信号即使采用定时准确的时钟进行取样判决,得到的数字信号也不是原来发射端的调制信号,误差的积累将导致抽样判决后的误码率增大,因此数字QPSK解调电路要对载波误差进行补偿,减少非相干载波解调带来的影响。
2)、QPSK解调原理框图
在这里插入图片描述
对于QPSK的调制与解调,具体的实验原理,大家可以通过以下链接进行具体的了解学习,当然,小伙伴有兴趣的前提下,链接如下:https://baike.baidu.com/item/qpsk/1265737?fr=aladdin
通过对以上调制解调原理框图,设计对应的解调调制原理python代码,进而达到QPSK调制,解调的仿真目的,接下来,我们就进行python代码的设计吧!

二、QPSK的python代码设计

1、QPSK调制框图设计

1)、导入本次需要的python代码库

import numpy as np
import random
import matplotlib.pyplot as plt
  • numpy: 进行数学与数组的计算
  • random: 产生随机信号
  • matplotlib.pyplot: 绘制各种信号的图像

2)、信号随机产生函数设计

def information(N):#输入比特流的个数N,输出我们的信号,要么是1,要么是0
    signal=np.array([])
    for i in range(N):
        x=random.random()
        if x>=0.5:
            x=1
        else:
            x=0
        signal=np.insert(signal,len(signal),x)
    return signal

以上函数主要功能是产生个数为N的信号个数(N为我们需要设定的参数),每个信号要么是0,要么是1,从而进行信号的产生
3)、产生的信号进行串并转换,奇数进I路,偶数进Q路,并观察对应的信号波形
(1)、python代码如下所示:

N=20
T=1
fc=2
Fs=100
bitstream=information(N)
bitstream=2*bitstream-1
I=np.array([])
Q=np.array([])
for i in range(1,N+1):
    if np.mod(i,2)!=0:
        I=np.insert(I,len(I),bitstream[i-1])
    else:
        Q=np.insert(Q,len(Q),bitstream[i-1])
bit_data=np.array([])
for i in range(1,N+1):
     bit_data=np.insert(bit_data,len(bit_data),bitstream[i-1]*np.ones(T*Fs))
I_data=np.array([])
Q_data=np.array([])
for i in range(1,int(N/2)+1):
    I_data=np.insert(I_data,len(I_data),I[i-1]*np.ones(T*Fs*2))
    Q_data=np.insert(Q_data,len(Q_data),Q[i-1]*np.ones(T*Fs*2))
t=np.array([])
for i in np.arange(0,N*T,1/Fs):
    t=np.insert(t,len(t),i)
plt.subplot(3,1,1)
plt.plot(t,bit_data)
plt.legend(["Bitstream"],loc='upper right')
plt.subplot(3,1,2)
plt.plot(t,I_data)
plt.legend(["I_Bitstream"],loc='upper right')
plt.subplot(3,1,3)
plt.plot(t,Q_data)
plt.legend(["Q_Bitstream"],loc='upper right')
plt.show()

(2)、产生的原始信号和I路及Q路信号波形如下所示:
在这里插入图片描述
由于信号是随机产生的,所以小伙伴运行的结果波形图与上图得到的结果图像会不一样的,属于正常现象
4)、QPSK调制设计,与想干载波进行相乘,进而得到原始信号调制信号、I路调制信号、Q路调制信号的波形图
(1)、python代码如下所示:

bit_t=np.array([])
for i in np.arange(0,2*T,1/Fs):
    bit_t=np.insert(bit_t,len(bit_t),i)
I_carrier=np.array([])
Q_carrier=np.array([])
for i in range(1,int(N/2)+1):
    I_carrier=np.insert(I_carrier,len(I_carrier),I[i-1]*np.cos(2*np.pi*fc*bit_t))
    Q_carrier=np.insert(Q_carrier,len(Q_carrier),Q[i-1]*np.cos(2*np.pi*fc*bit_t+np.pi/2))
QPSK_signal=I_carrier+Q_carrier
plt.subplot(3,1,1)
plt.plot(t,I_carrier)
plt.legend(["I_signal"],loc='upper right')
plt.subplot(3,1,2)
plt.plot(t,Q_carrier)
plt.legend(["Q_signal"],loc='upper right')
plt.subplot(3,1,3)
plt.plot(t,QPSK_signal)
plt.legend(["QPSK_signal"],loc='upper right')
plt.show()

QPSK信号调制,主要是将产生的I路信号、Q路信号与想干载波进行相乘,得到调制后的I路信号和Q路信号,然后通过相加器进行相加,得到原始信号的调制信号,并观察调制信号的波形。
(2)、原始信号调制信号、I路调制信号、Q路调制信号的波形图如下所示:
在这里插入图片描述
那么通过以上步骤,我们的QPSK的解调框图就设计完成了;接下来,我们需要的就是QPSK解调框图设计了,继续跟进林君学长吧!

2、高斯白噪声设计

1)、高斯白噪声的设计

def awgn(x, snr):
    snr = 10**(snr/10.0)
    xpower = np.sum(x**2)/len(x)
    npower = xpower/snr
    return np.random.randn(len(x)) * np.sqrt(npower)+x

2)、在进行信号的调制之后,在解调之前,信道肯定会融入噪声,所以我们需要加入高斯白噪声,模拟信道传输过程中的噪声

3、QPSK解调框图设计

1)、QPSK解调框图设计python代码如下所示:

snr=1
QPSK_receive=awgn(QPSK_signal,snr)
I_recover=np.array([])
Q_recover=np.array([])
for i in range(1,int(N/2)+1):
    I_output=QPSK_receive[(i-1)*len(bit_t):i*len(bit_t)]*np.cos(2*np.pi*fc*bit_t)
    if np.sum(I_output)>0:
        I_recover=np.insert(I_recover,len(I_recover),1)
    else:
        I_recover=np.insert(I_recover,len(I_recover),-1)
    Q_output=QPSK_receive[(i-1)*len(bit_t):i*len(bit_t)]*np.cos(2*np.pi*fc*bit_t+np.pi/2)
    if np.sum(Q_output)>0:
        Q_recover=np.insert(Q_recover,len(Q_recover),1)
    else:
        Q_recover=np.insert(Q_recover,len(Q_recover),-1)
bit_recover=np.array([])
for i in range(1,N+1):
    if np.mod(i,2)!=0:
        bit_recover=np.insert(bit_recover,len(bit_recover),I_recover[int((i-1)/2)])
    else:
        bit_recover=np.insert(bit_recover,len(bit_recover),Q_recover[int(i/2)-1])
recover_data=np.array([])
for i in range(1,N+1):
    recover_data=np.insert(recover_data,len(recover_data),bit_recover[i-1]*np.ones(T*Fs))
I_recover_data=np.array([])
Q_recover_data=np.array([])
for i in range(1,int(N/2)+1):
    I_recover_data=np.insert(I_recover_data,len(I_recover_data),I_recover[i-1]*np.ones(T*Fs*2))
    Q_recover_data=np.insert(Q_recover_data,len(Q_recover_data),Q_recover[i-1]*np.ones(T*Fs*2))
plt.subplot(3,1,1)
plt.plot(t,recover_data)
plt.legend(["Bitstream"],loc='upper right')
plt.subplot(3,1,2)
plt.plot(t,I_recover_data)
plt.legend(["I_Bitstream"],loc='upper right')
plt.subplot(3,1,3)
plt.plot(t,Q_recover_data)
plt.legend(["Q_Bitstream"],loc='upper right')
plt.show()

将调制的I路信号和Q路信号进行叠加高斯白噪声之后,与想干载波相乘进行载波恢复,然后进行抽样判决之后,形成I路解调信号、Q路解调信号;最后对I路解调信号和Q路解调信号进行并/串转换,得到完整的解调信号,并观察三个信号的波形
2)、解调总信号、解调的I路信号、解调的Q路信号的波形图如下所示:
在这里插入图片描述

三、QPSK调制解调结论

1、QPSK调制结论

1)、QPSK的调制是将I路和Q路分别与想干载波相乘,然后通过相加器相加得到我们最终的调制信号,主要过程就是信号产生、信号分类(I路和Q路)、分类信号分别进行乘以相干载波调制、相加器相加得到最后的调制信号
2)、I路信号和Q路信号相加即可恢复为原始信号,上面的第一个图可以得到这个结论,下图所示:(原始信号)
在这里插入图片描述
3)、同理,解调信号的I路与Q路相加也可恢复为最终的解调信号,上面第二图可以得出,下图所示:
在这里插入图片描述

2、QPSK解调结论

1)、QPSK的解调是对I路和Q路分别进行解调,将解调后的I路和Q路进行最终的相加器相加得到我们的解调信号 ,主要过程就是调制信号->加入噪声->载波恢复->抽样判决->并/串变换->相加器相加
2)、通过原始信号与最终的解调信号我们可以得出,QPSK系统性能是非常不错的,原始信号波形图与解调信号波形图基本吻合,如下所示:
(1)原始信号波形图:
在这里插入图片描述
(2)、解调信号波形图
在这里插入图片描述
这就是python语言强大的功能之处,python在本世纪应该是人工智能和图像处理的主要设计代码,所以,多学习python,对自己以后的未来是有好处的!

四、QPSK调制解调整体代码

1、QPSK调制解调完整python代码如下所示

import numpy as np
import random
import matplotlib.pyplot as plt
def awgn(x, snr):
    snr = 10**(snr/10.0)
    xpower = np.sum(x**2)/len(x)
    npower = xpower/snr
    return np.random.randn(len(x)) * np.sqrt(npower)+x
def information(N):#输入比特流的个数N,输出我们的信号,要么是1,要么是0
    signal=np.array([])
    for i in range(N):
        x=random.random()
        if x>=0.5:
            x=1
        else:
            x=0
        signal=np.insert(signal,len(signal),x)
    return signal
#以下为信号分离
N=20
T=1
fc=2
Fs=100
bitstream=information(N)
bitstream=2*bitstream-1
I=np.array([])
Q=np.array([])
for i in range(1,N+1):
    if np.mod(i,2)!=0:
        I=np.insert(I,len(I),bitstream[i-1])
    else:
        Q=np.insert(Q,len(Q),bitstream[i-1])
bit_data=np.array([])
for i in range(1,N+1):
     bit_data=np.insert(bit_data,len(bit_data),bitstream[i-1]*np.ones(T*Fs))
I_data=np.array([])
Q_data=np.array([])
for i in range(1,int(N/2)+1):
    I_data=np.insert(I_data,len(I_data),I[i-1]*np.ones(T*Fs*2))
    Q_data=np.insert(Q_data,len(Q_data),Q[i-1]*np.ones(T*Fs*2))
t=np.array([])
for i in np.arange(0,N*T,1/Fs):
    t=np.insert(t,len(t),i)
plt.subplot(3,1,1)
plt.plot(t,bit_data)
plt.legend(["Bitstream"],loc='upper right')
plt.subplot(3,1,2)
plt.plot(t,I_data)
plt.legend(["I_Bitstream"],loc='upper right')
plt.subplot(3,1,3)
plt.plot(t,Q_data)
plt.legend(["Q_Bitstream"],loc='upper right')
plt.show()
#以下为信号调制,记得分开运行
bit_t=np.array([])
for i in np.arange(0,2*T,1/Fs):
    bit_t=np.insert(bit_t,len(bit_t),i)
I_carrier=np.array([])
Q_carrier=np.array([])
for i in range(1,int(N/2)+1):
    I_carrier=np.insert(I_carrier,len(I_carrier),I[i-1]*np.cos(2*np.pi*fc*bit_t))
    Q_carrier=np.insert(Q_carrier,len(Q_carrier),Q[i-1]*np.cos(2*np.pi*fc*bit_t+np.pi/2))
QPSK_signal=I_carrier+Q_carrier
plt.subplot(3,1,1)
plt.plot(t,I_carrier)
plt.legend(["I_signal"],loc='upper right')
plt.subplot(3,1,2)
plt.plot(t,Q_carrier)
plt.legend(["Q_signal"],loc='upper right')
plt.subplot(3,1,3)
plt.plot(t,QPSK_signal)
plt.legend(["QPSK_signal"],loc='upper right')
plt.show()
#以下为调制信号解调,记得分开运行
snr=1
QPSK_receive=awgn(QPSK_signal,snr)
I_recover=np.array([])
Q_recover=np.array([])
for i in range(1,int(N/2)+1):
    I_output=QPSK_receive[(i-1)*len(bit_t):i*len(bit_t)]*np.cos(2*np.pi*fc*bit_t)
    if np.sum(I_output)>0:
        I_recover=np.insert(I_recover,len(I_recover),1)
    else:
        I_recover=np.insert(I_recover,len(I_recover),-1)
    Q_output=QPSK_receive[(i-1)*len(bit_t):i*len(bit_t)]*np.cos(2*np.pi*fc*bit_t+np.pi/2)
    if np.sum(Q_output)>0:
        Q_recover=np.insert(Q_recover,len(Q_recover),1)
    else:
        Q_recover=np.insert(Q_recover,len(Q_recover),-1)
bit_recover=np.array([])
for i in range(1,N+1):
    if np.mod(i,2)!=0:
        bit_recover=np.insert(bit_recover,len(bit_recover),I_recover[int((i-1)/2)])
    else:
        bit_recover=np.insert(bit_recover,len(bit_recover),Q_recover[int(i/2)-1])
recover_data=np.array([])
for i in range(1,N+1):
    recover_data=np.insert(recover_data,len(recover_data),bit_recover[i-1]*np.ones(T*Fs))
I_recover_data=np.array([])
Q_recover_data=np.array([])
for i in range(1,int(N/2)+1):
    I_recover_data=np.insert(I_recover_data,len(I_recover_data),I_recover[i-1]*np.ones(T*Fs*2))
    Q_recover_data=np.insert(Q_recover_data,len(Q_recover_data),Q_recover[i-1]*np.ones(T*Fs*2))
plt.subplot(3,1,1)
plt.plot(t,recover_data)
plt.legend(["Bitstream"],loc='upper right')
plt.subplot(3,1,2)
plt.plot(t,I_recover_data)
plt.legend(["I_Bitstream"],loc='upper right')
plt.subplot(3,1,3)
plt.plot(t,Q_recover_data)
plt.legend(["Q_Bitstream"],loc='upper right')
plt.show()

对于以上代码模块的功能,林君学长已经给出,建议调制和解调分开运行,这样得到的波形图比较美观、知道每段代码对应的波形图,总共三个图,三段主要代码,在jupyter中分三格运行便好,VSCode中建议创建三个py文件然后调用运行就好!

以上就是本次博客的全部内容啦,通过本次博客,大家可以更好的了解到QPSK的的调制与解调原理,也能够对QPSK应用于生活中的调制解调问题有一定的了解,同时,林君学长也希望大家能够深入的了解代码的具体意思,理解原理;代码有错误的地方记得给林君学长留言改正。
同时、遇到问题的小伙伴也记得评论区留言,林君学长看到会给大家回复解答的,这个学长不太冷!

陈一月的又一天编程岁月^ _ ^

猜你喜欢

转载自blog.csdn.net/qq_42451251/article/details/106530700
今日推荐