基于jupyter notebook的python编程-----通过python编程实现信号传输MSK的调制与解调目录
- 一、MSK调制解调原理
- 1、什么是MSK?
- 2、MSK调制原理
- 3、MSK解调原理
- 二、MSK调制解调的python代码设计
- 1、信号发射器设计
- 2、高斯白噪声设计
- 3、低通滤波器设计
- 4、MSK调制原理框图设计
- 5、MSK解调原理框图设计
- 三、MSK调制解调结论
- 1、MSK调制结论
- 2、MSK解调结论
- 四、MSK调制解调整体代码
- 1、MPSK调制解调完整python代码如下所示
移动通信原理学习过程中,有太多的调制原理了,BPSK、QPSK、MSK等等,前面林君学长分别进行了对应的BPKS和QPSK调制与解调的博客讲解,本次博客,林君学长主要讲解MSK的调制解调原理,并通过调制解调原理,进行对应的调制解调python代码的设计,一起学习吧
一、MSK调制解调原理
1、什么是MSK?
1)、最小频移键控MSK (Minimum Shift Keying)是一种改变波载频率来传输信息的调制技术,即特殊的连续相位的频移键控 (CPFSK)。其最大频移为比特速率的1/4,即MSK是调制系数为0.5的连续相位的FSK。
2)、在数字调制中,最小频移键控(Minimum-Shift Keying,缩写:MSK)是一种连续相位的频移键控方式,在1950年代末和1960年代产生。与偏移四相相移键控(OQPSK)类似,MSK同样将正交路基带信号相对于同相路基带信号延时符号间隔的一半,从而消除了已调信号中180°相位突变的现象。与OQPSK不同的是, MSK采用正弦型脉冲代替了OQPSK基带信号的矩形波形,因此得到恒定包络的调制信号,这有助于减少非线性失真带来的解调问题
MSK又称快速移频键控(FFSK)。这里“最小”指的是能以最小的调制指数(即0.5)获得正交信号;而“快速”指的是对于给定的频带,它能比PSK传送更高的比特速率。
MSK是一种在无线移动通信中很有吸引力的数字调制方式,它具有以下两种主要的特点:
1.信号能量的99.5%被限制在数据传输速率的1.5倍的带宽内。谱密度随频率(远离信号带宽中心)倒数的四次幂而下降,而通常的离散相位FSK信号的谱密度却随频率倒数的平方下降。因此,MSK信号在带外产生的干扰非常小。这正是限带工作情况下所希望有的宝贵特点。
2.信号包络是恒定的,系统可以使用廉价高效的非线性器件。
更多有关MSK的介绍,小伙伴可以参考以下链接进行相关了解,链接如下:https://baike.baidu.com/item/MSK/5475817?fr=aladdin
2、MSK调制原理
1)、MSK调制原理
(1)、MSK信号是一种相位连续、包络恒定并且占用带宽最小的二进制正交FSK信号。它的第k个码元可以表示为:
式中,为视在角载频;=±1;T为第k个码元确定的初始相位。
(2)、由上式可以看出,当=+1时,码元频率等于;当=-1时,码元频率等于。故和的距离等于。这是2FSK信号最小频率间隔。
(3)、式(2-1)可以用频率为的两个正交分量表示。将式(2-1)进行三角公式变换,得到:
式(3-1)表示,此MSK信号可以分解为同相分量(I)和正交分量(Q)两部分。
2)、MSK调制原理框图
由式(3-1)可知,MSK信号可以用两个正交的分量表示。根据该式构成 的MSK信号的产生MSK原理框图如下所示:
3、MSK解调原理
1)、MSK解调原理
由于MSK信号是最小二进制FSK信号,所以它可以采用解调FSK信号的相干法和非相干法解调。
2)、MSK解调原理框图
通过解调原理,可得到MSK信号的解调原理框图,如下所示:
二、MSK调制解调的python代码设计
1、信号发射器设计
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 ,然后该函数产生0、1的比特流
2、高斯白噪声设计
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
模拟信号在信道传输的过程中掺杂的噪声,x为我们调制后的信号,snr为信噪比,然后输出掺杂高斯白噪声后的调制信号
3、低通滤波器设计
def butter_lowpass(cutoff, fs, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = butter(order, normal_cutoff, btype='low', analog=False)
return b, a
def myfilter(data, cutoff, fs, order=5):
b, a = butter_lowpass(cutoff, fs,order=order)
y = lfilter(b, a, data)
return y
调制信号需要经过低通滤波器,所以以上函数只是为了模拟低通滤波器的作用,其中:
- cutoff:截止频率
- fs:信号采样频率
- order:滤波器的阶数
- data:滤波之前的调制信号
4、MSK调制原理框图设计
1)、导入需要的python库
import numpy as np
import random
import matplotlib.pyplot as plt
- numpy: 进行数学与数组的计算
- random: 产生随机信号
- matplotlib.pyplot: 绘制各种信号的图像
2)、MSK调制原理框图python设计
N=20
T=1
fc=10
Fs=100
bitstream=information(N)
bitstream1=2*bitstream-1
b0=1
encode_output=np.array([])
for i in range(1,N+1):
encode_output=np.insert(encode_output,len(encode_output),b0*bitstream1[i-1])
b0=encode_output[i-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),encode_output[i-1])
else:
Q=np.insert(Q,len(Q),encode_output[i-1])
bit_data=np.array([])
for i in range(1,N+1):
bit_data=np.insert(bit_data,len(bit_data),encode_output[i-1]*np.ones(T*Fs))
I_data=np.array([])
Q_data=np.array([])
base_wave=np.array([])
for i in np.arange(-T,T,1/Fs):
base_wave=np.insert(base_wave,len(base_wave),i)
for i in range(1,int(N/2)+1):
I_data=np.insert(I_data,len(I_data),I[i-1]*np.cos(np.pi*base_wave/(2*T)))
Q_data=np.insert(Q_data,len(Q_data),Q[i-1]*np.cos(np.pi*base_wave/(2*T)))
number_delay=int(len(base_wave)/2)
a=np.zeros(number_delay)
b=Q_data[0:len(Q_data)-number_delay]
Q_data1=np.hstack((a,b))
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_data1)
plt.legend(["Q_Bitstream"],loc='upper right')
plt.show()
以上python代码功能为MSK的调制过程,将信号进行串/并变换,分为I路和Q路,然后进行对应的信号调制
3)、调制信号波形图如下所示:
5、MSK解调原理框图设计
1)、MSK解调原理框图python设计
bit_t=np.array([])
for i in np.arange(0,N*T,1/Fs):
bit_t=np.insert(bit_t,len(bit_t),i)
I_carrier=np.cos(2*np.pi*fc*bit_t)
Q_carrier=np.cos(2*np.pi*fc*bit_t+np.pi/2)
MSK_signal=I_data*I_carrier+Q_data1*Q_carrier
snr=1
MSK_receive=awgn(MSK_signal,snr)
I_output=MSK_receive*I_carrier
I_filter_output=myfilter(I_output, fc, Fs, order=5)
Q_output=MSK_receive*Q_carrier
Q_filter_output=myfilter(Q_output, fc, Fs, order=5)
I_recover=np.array([])
Q_recover=np.array([])
for i in range(1,int(N/2)+1):
if I_filter_output[(2*i-2)*number_delay]>0:
I_recover=np.insert(I_recover,len(I_recover),1)
else:
I_recover=np.insert(I_recover,len(I_recover),-1)
if Q_filter_output[(2*i-1)*number_delay]>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])
bit_recover1=np.array([])
for i in range(1,N+1):
if i==1:
bit_recover1=np.insert(bit_recover1,len(bit_recover1),bit_recover[i-1])
else:
bit_recover1=np.insert(bit_recover1,len(bit_recover1),bit_recover[i-1]*bit_recover[i-2])
recover_data=np.array([])
for i in range(1,N+1):
recover_data=np.insert(recover_data,len(recover_data),bit_recover1[i-1]*np.ones(T*Fs))
bit_stream=np.array([])
for i in range(1,N+1):
bit_stream=np.insert(bit_stream,len(bit_stream),bitstream1[i-1]*np.ones(T*Fs))
plt.subplot(2,1,2)
plt.plot(t,bit_stream)
plt.legend(["original Bitstream"],loc='upper right')
plt.subplot(2,1,1)
plt.plot(t,recover_data)
plt.legend(["recover Bitstream"],loc='upper right')
plt.show()
以上python代码功能为MSK解调过程模拟,对调制信号进行解调,然后得到解调信号的波形图!
2)、MSK解调信号波形图如下所示:
三、MSK调制解调结论
1、MSK调制结论
1)、MSK调制信号波形如下所示:
2)、上图调制仿真的结果为原始信号的波形,和串/并变换后I路和Q路的解调信号的波形
3)、从上图可以看出,I路的调制信号和Q路的调制信号的波形不同的原因主要是因为载波相位不同导致的,当然,这也是MSK调制独特的特点
2、MSK解调结论
1)、MSK解调信号波形如下所示:
2)、上图解调的波形为解调信号与原始信号的波形图
3)、可以看出,解调后的信号波形图与原始信号是非常吻合的,这个结果对于这个实验来说是很重要的结果,这暗示这我们的MSK的python代码是模拟的非常好的!同时决定的MSK的调制、解调性能的优异
四、MSK调制解调整体代码
1、MPSK调制解调完整python代码如下所示
import numpy as np
import random
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter
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
def butter_lowpass(cutoff, fs, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = butter(order, normal_cutoff, btype='low', analog=False)
return b, a
def myfilter(data, cutoff, fs, order=5):
b, a = butter_lowpass(cutoff, fs,order=order)
y = lfilter(b, a, data)
return y
N=20
T=1
fc=10
Fs=100
bitstream=information(N)
bitstream1=2*bitstream-1
b0=1
encode_output=np.array([])
for i in range(1,N+1):
encode_output=np.insert(encode_output,len(encode_output),b0*bitstream1[i-1])
b0=encode_output[i-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),encode_output[i-1])
else:
Q=np.insert(Q,len(Q),encode_output[i-1])
bit_data=np.array([])
for i in range(1,N+1):
bit_data=np.insert(bit_data,len(bit_data),encode_output[i-1]*np.ones(T*Fs))
I_data=np.array([])
Q_data=np.array([])
base_wave=np.array([])
for i in np.arange(-T,T,1/Fs):
base_wave=np.insert(base_wave,len(base_wave),i)
for i in range(1,int(N/2)+1):
I_data=np.insert(I_data,len(I_data),I[i-1]*np.cos(np.pi*base_wave/(2*T)))
Q_data=np.insert(Q_data,len(Q_data),Q[i-1]*np.cos(np.pi*base_wave/(2*T)))
number_delay=int(len(base_wave)/2)
a=np.zeros(number_delay)
b=Q_data[0:len(Q_data)-number_delay]
Q_data1=np.hstack((a,b))
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_data1)
plt.legend(["Q_Bitstream"],loc='upper right')
plt.show()
bit_t=np.array([])
for i in np.arange(0,N*T,1/Fs):
bit_t=np.insert(bit_t,len(bit_t),i)
I_carrier=np.cos(2*np.pi*fc*bit_t)
Q_carrier=np.cos(2*np.pi*fc*bit_t+np.pi/2)
MSK_signal=I_data*I_carrier+Q_data1*Q_carrier
snr=1
MSK_receive=awgn(MSK_signal,snr)
I_output=MSK_receive*I_carrier
I_filter_output=myfilter(I_output, fc, Fs, order=5)
Q_output=MSK_receive*Q_carrier
Q_filter_output=myfilter(Q_output, fc, Fs, order=5)
I_recover=np.array([])
Q_recover=np.array([])
for i in range(1,int(N/2)+1):
if I_filter_output[(2*i-2)*number_delay]>0:
I_recover=np.insert(I_recover,len(I_recover),1)
else:
I_recover=np.insert(I_recover,len(I_recover),-1)
if Q_filter_output[(2*i-1)*number_delay]>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])
bit_recover1=np.array([])
for i in range(1,N+1):
if i==1:
bit_recover1=np.insert(bit_recover1,len(bit_recover1),bit_recover[i-1])
else:
bit_recover1=np.insert(bit_recover1,len(bit_recover1),bit_recover[i-1]*bit_recover[i-2])
recover_data=np.array([])
for i in range(1,N+1):
recover_data=np.insert(recover_data,len(recover_data),bit_recover1[i-1]*np.ones(T*Fs))
bit_stream=np.array([])
for i in range(1,N+1):
bit_stream=np.insert(bit_stream,len(bit_stream),bitstream1[i-1]*np.ones(T*Fs))
plt.subplot(2,1,2)
plt.plot(t,bit_stream)
plt.legend(["original Bitstream"],loc='upper right')
plt.subplot(2,1,1)
plt.plot(t,recover_data)
plt.legend(["recover Bitstream"],loc='upper right')
plt.show()
以上就是本次博客的全部内容啦,通过本次博客,大家可以更好的了解到MSK的的调制与解调原理,也能够对MSK应用于生活中的调制解调问题有一定的了解,同时,林君学长也希望大家能够深入的了解代码的具体意思,理解原理;代码有错误的地方记得给林君学长留言改正。
同时、遇到问题的小伙伴也记得评论区留言,林君学长看到会给大家回复解答的,这个学长不太冷!
陈一月的又一天编程岁月^ _ ^