基于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+θ) si(t)=Acos(wst+θ)
在0到 T s T_s Ts之间,i=1,2,3,4中取值。其中 T s T_s Ts为四进制符号间隔(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应用于生活中的调制解调问题有一定的了解,同时,林君学长也希望大家能够深入的了解代码的具体意思,理解原理;代码有错误的地方记得给林君学长留言改正。
同时、遇到问题的小伙伴也记得评论区留言,林君学长看到会给大家回复解答的,这个学长不太冷!

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

  • 10
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
要在MATLAB中实现混合PPM-QPSK调制的误码率(Bit Error Rate,BER),您可以使用以下示例代码: ```matlab % 设置参数 M = 4; % QPSK调制中的符号数 Tb = 1; % 每个比特的持续时间 Tp = 4; % 每个PPM符号的持续时间 EbNo_dB = 0:10; % 信噪比范围(以dB为单位) EbNo = 10.^(EbNo_dB/10); % 转换为线性比特能量与噪声功率谱密度之比 % 生成随机比特序列 numBits = 1e6; % 比特序列长度 bitSeq = randi([0 1], 1, numBits); % PPM-QPSK调制 ppmSeq = zeros(1, numBits/Tb); for i = 1:numBits/Tb symbolIdx = bi2de(reshape(bitSeq((i-1)*Tb+1:i*Tb), 2, [])', 'left-msb') + 1; ppmSeq(i) = exp(1i * (2*pi/M) * (symbolIdx-1)); end % 添加高斯白噪声 ber = zeros(size(EbNo_dB)); for i = 1:length(EbNo_dB) N0 = Tb / (2 * log2(M) * EbNo(i)); % 噪声功率谱密度 noise = sqrt(N0/2) * (randn(size(ppmSeq)) + 1i * randn(size(ppmSeq))); % 复高斯白噪声 received = ppmSeq + noise; % 接收信号 % 解调 demodulated = angle(received) * M / (2*pi) + 1; demodulated = de2bi(demodulated-1, 'left-msb'); demodulated = reshape(demodulated', 1, []); % 计算误码率 numErrors = sum(bitSeq ~= demodulated); ber(i) = numErrors / numBits; end % 绘制误码率曲线 semilogy(EbNo_dB, ber, 'o-'); xlabel('Eb/No (dB)'); ylabel('Bit Error Rate (BER)'); title('BER Performance of Hybrid PPM-QPSK Modulation'); grid on; ``` 在上述代码中,我们首先设置了参数,包括QPSK调制中的符号数M、每个比特的持续时间Tb、每个PPM符号的持续时间Tp以及信噪比范围EbNo_dB。然后,我们生成了一个随机的比特序列bitSeq。 接下来,我们进行PPM-QPSK调制,将比特序列映射为复数形式的PPM符号ppmSeq。 随后,我们添加高斯白噪声,并对接收信号进行解调,得到解调后的比特序列demodulated。 最后,我们计算误码率,并绘制误码率曲线。 请根据您的具体需求调整参数并运行代码。希望对您有所帮助!如有更多问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈一月的编程岁月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值