很多基于扩频通信的实现现在大多数仿真都是通过matlab进行实现仿真,但其实,python也完全可以进行仿真,只要理解原理,任何语言都可以实现对扩频通信系统的仿真,不过通过python和matlab比较简单实现一点,本次博客,林君学长主要带大家了解如何通过python编程,实现对扩频通信系统的BPSK调制解调,进而实现对多用户数据的传输仿真!
多用户扩频通信系统仿真的具体要求如下:
接下来,进行实验之前,我们需要先了解一下什么是BPSK调制?
1)、BPSK (Binary Phase Shift Keying)-------二进制相移键控。是把模拟信号转换成数据值的转换方式之一,利用偏离相位的复数波浪组合来表现信息键控移相方式。BPSK使用了基准的正弦波和相位反转的波浪,使一方为0,另一方为1,从而可以同时传送接受2值(1比特)的信息。
由于最单纯的键控移相方式虽抗噪音较强但传送效率差,所以常常使用利用4个相位的QPSK和利用8个相位的8PSK
1)、BPSK调制原理
BPSK 调制方式时,因为发送端以某一个相位作为基准,所以在接收端也一定有这样一个固定的基准相位作为参考。假如参考相位发生变化了,那么接收端恢复的信息也会出错,也就是存在“倒π”现象。因此需要在接收端使用载波同步,才能够正确恢复出基带的信号。
2)、BPSK解调原理
BPSK信号的幅度与基带信号无关,故不能用包络检波法而只能用相干解调法解调BPSK信号,在相干解调过程中需要用到与接收的BPSK信号同频同相的相干载波,相干接收机模型如下图所示:
因此、PBSK解调原理由上面可得出如下解调原理框图:
1)、BPSK调制过程,特别是移动通信原理学习之后,大致就分为如下六个过程:
信号发生器----->扩频----->调制----->解扩----->解调----->信号接收
当然,中间还有高斯白噪声的加入,这里主要在调制过程中加入,现实仿真模型中必须考虑噪声的影响!
说明: 发射端主要完成 m 序列的产生,随机 0,1 序列的产生。然后利用 m 序列对产生的随机序列进行扩频,然后再用 相干载波cos(wt) 对其进行调制。 信道主要模拟信号的多径传输,在这个信道中一共有三个用户的数据进行传输,并经过了多径衰落。
说明: 接收端接收到的信号是几路多径信号的加噪后的叠加,首先要完成信号的解扩,然后再解调,滤波,抽样判决最后分别与原始信号比较并统计误码率
准备阶段: 该项目需要导入的库如下:
import numpy as np
import random
import matplotlib.pyplot as plt
numpy用来做数组的运算、random用于随机数的产生、matplotlib用于作误比特率和信噪比的线性图
1)、随机产生信号的python代码如下所示:
#产生信息(1,-1)的信息流
def information(N):#输入比特流的个数N,输出我们的信号,要么是1,要么是0
signal=np.array([]) #定义信号数组
for i in range(N): #进行循环输出N个比特
x=random.randint(0,1) #随机产生0-1之间的一个随机数
if x>=0.5: #当产生的随机数大于0.5,我们设定为1,小于0.5,我们设定为0
x=1
else:
x=0
signal=np.insert(signal,len(signal),x*2-1)#向信号数组中插入处理后的比特,只有-1和1
return signal #返回信号
2)、函数说明:
以上函数为比特流的产生函数,给定我们需要产生的比特流的个数N,函数随机产生0-1之间的N个比特的数据流,并经过处理,最终发射出的只有-1和1的比特流
1)、定义产生M序列函数的python代码如下所示:
#扩频码的产生,只产生一个周期的M序列
def genMseq(b):#b为c0-cn的个数 b0对应Cn,bn对应C0
N=len(b)-1#N指寄存器个数
D=np.ones(N)#寄存器初始状态全1
A=b[N-1::-1]#c0--->cn的取值,分别对应b(n-1)--->b0
c=np.array([])#定义扩频后的序列数组(M序列)
for i in range((2**N)-1): #扩频的序列为2^N-1次循环
c1=(np.dot(D,A))%2#点乘求和,并与2求余数,最终得到的结果不是0就是1
c=np.insert(c,len(c),D[N-1])#为M序列插值,对应最后一个寄存区的状态
D=D[0:N-1]#每次操作之后,寄存区的数组D中的数据往后移一位
D=np.insert(D,0,c1)#将c1插入D的最前面!
for i in range(len(c)):
c[i]=int(c[i]*2-1)#处理M序列,返回-1和1
return c
2)、函数说明:
以上函数为扩频序列函数,给出一个周期的序列b,经过扩频函数产生M序列,达到扩频的效果,最终返回为2^N-1的M序列,最终的返回序列也为-1和1的序列比特
1)、扩频函数的python代码如下所示:
#扩频
def dsss(signal,c):
ssignal=np.array([])
for i in range(len(signal)):
ssignal=np.insert(ssignal,len(ssignal),signal[i]*c)#M序列与信号相乘,得到扩频序列
return ssignal
2)、函数说明
以上为模拟扩频过程函数,将上面的信号与产生的M序列进行扩频,最后返回的是一个N维度数组,数组中的每一个元素包含M序列周期个的元素,例如1000个维度,每个元素中的长度为31;[[,…,],[,…,]…[,…,],[,…,]]
1)、调制函数的python代码如下所示:
#调制 采用BPSK调制
def modu(signal,dataRate,fc,fs):#dataRate符号周期 fc载波频率 fs采样频率 Tb=1/dataRate
t=np.linspace(0,1/dataRate,int(fs/dataRate))#抽样采集,返回的(fs/dataRate)个的采集点的值
carrier=np.array([])#定义相干载波数组
carrier=np.insert(carrier,len(carrier),np.cos(2*(np.pi)*fc*t))#相干载波复制
modusignal=np.array([])#定义调制信号数组
for i in range(len(signal)):
modusignal=np.insert(modusignal,len(modusignal),signal[i]*carrier)#相干载波与扩频序列的乘积
#print(modusignal)
return modusignal #返回调制信号
2)、函数说明:
调制过程其实就是扩频序列与相干载波相乘,既然要乘以相干载波,那么我们必须要设计相干载波,框图中我们可以看出,相干载波为cos(2pifc*t),这也是我们设计相干载波的方法!而扩频序列乘以相干载波就得到了我们的调制信号!
1)、高斯白噪声函数的python代码如下所示:
#高斯白噪声产生
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)、函数说明
以上函数主要是模拟高斯白噪声的产生,X为我们的调制信号,snr为信噪比,经过处理之后,调制信号中会混合高斯白噪声,从而达到现实中的模拟!以上高斯白噪声的函数来自网络,大家可以百度查看该函数中的具体内容!
3)、多径衰落的python函数代码
#信道模拟多径衰落
def channels(modusignal,k):
L=len(modusignal)
x1=np.random.randn(1,L)
y1=np.random.randn(1,L)
h1=np.abs(x1+j*y1)
r1=np.array([])
r1=h1*modusignal
#print(r1)
r1=r1[0:len(modusignal)-6]
for i in range(6):
r1=np.insert(r1,0,0)
r1=r1[0:len(modusignal)]
x2=np.random.randn(1,L)
y2=np.random.randn(1,L)
h2=np.abs(x2+j*y2)
r2=np.array([])
r2=h2*modusignal
#print(r2)
r2=r2[0:len(modusignal)-7]
for i in range(7):
r2=np.insert(r2,0,0)
r2=r2[0:len(modusignal)]
x3=np.random.randn(1,L)
y3=np.random.randn(1,L)
h3=np.abs(x3+j*y3)
r3=np.array([])
r3=h3*modusignal
r3=r3[0:len(modusignal)-8]
for i in range(8):
r3=np.insert(r3,0,0)
r3=r3[0:len(modusignal)]
multiS=np.array([])
if k==2:
multiS=modusignal+r1
elif k==3:
multiS=modusignal+r1+r2
elif k==4:
multiS=modusignal+r3+r2+r1
return multiS
4)、函数说明
以上函数模拟多径衰落的函数,为了是解决用户1进行2径衰落、用户2进行3径衰落、用户3进行4径衰落;其中用户1延时6个采样点模拟衰落、用户2延时7个采样点模拟衰落、用户3延时8个采样点模拟衰落!
1)、解扩函数的python代码如下所示:
#解扩实现
def dedsss(receiveSignal,c,chipRate,fs):
L=int(fs/chipRate)#16
c1=np.array([])
a=np.ones(L)
for i in range(len(c)):
c1=np.insert(c1,len(c1),c[i]*a)
dessignal=np.array([])
for i in range(0,len(receiveSignal),len(c1)):
h=receiveSignal[i:i+len(c1)]
dessignal=np.insert(dessignal,len(dessignal),h*c1)
#print(h)
return dessignal
2)、函数说明:
解扩函数,是将上面的带着高斯白噪声的函数进行扩频序列的还原,输出解扩信号,传递的参数为带着高斯白噪声的扩频信号、 fs采样频率 Tb(chipRate)=1/dataRate,c1为M序列,也就是去掉M序列,还原为带着噪声的信号!
1)、解调函数的python代码如下所示:
#解调实现
def demodu(Resignal,datarate,fc,fs):
t=np.linspace(0,1/datarate,int(fs/datarate))
carrier=np.array([])
carrier=np.insert(carrier,len(carrier),np.cos(2*(np.pi)*fc*t))
Lc=len(carrier)
Ls=len(Resignal)
designal=np.array([])
for i in range(0,Ls,Lc):#从0到解扩信号长度,以载波信号长度为步长进行解扩信号的周期划分进而与载波信号相乘得到解调信号周期的抽样值
h=Resignal[i:i+Lc]
designal=np.insert(designal,len(designal),h*carrier)
demoSignal=np.array([])
sum=0
for i in range(0,Ls,Lc):
threshold=np.sum(designal[i:i + Lc - 1])
if threshold>0:
tt=1
else:
tt=-1
demoSignal=np.insert(demoSignal,len(demoSignal),tt)#输出解调信号
return demoSignal
2)、函数说明:
与想干载波相乘,去除高斯白噪声,得到解调信号,并与原始信号做对比,进而求得误比特率,解调函数的主要功能就是滤除带外噪声、回复原始信号,传递的参数为解扩信号、符号周期(dataRate)、载波频率(fc)、采样频率(fs)
1)、进行相关变量的赋值
dataRate=1000
chipRate=31*dataRate
fc=chipRate*2
fs=fc*8
N=300
c=31
b1=[1,0,0,1,0,1]
b2=[1,1,0,1,1,1]
b3=[1,1,1,1,0,1]
snr=np.array([])
for i in range(-20,-8,2):
snr=np.insert(snr,len(snr),i)
定义300个比特的数据流、符号周期、载波频率、采样频率
2)、调用函数,实现BPSK调制过程
err_bit1=np.array([])
err_bit2=np.array([])
err_bit3=np.array([])
for j in range(len(snr)):
signal1=information(N)
signal2=information(N)
signal3=information(N)
c1=genMseq(b1)
c2=genMseq(b2)
c3=genMseq(b3)
dssignal1=dsss(signal1,c1)
dssignal2=dsss(signal2,c2)
dssignal3=dsss(signal3,c3)
modusignal1=modu(dssignal1,chipRate,fc,fs)
modusignal11=channels(modusignal1,2)
modusignal2=modu(dssignal2,chipRate,fc,fs)
modusignal22=channels(modusignal2,3)
modusignal3=modu(dssignal3,chipRate,fc,fs)
modusignal33=channels(modusignal3,4)
mixsignal=modusignal11+modusignal22+modusignal33
receivesignal=awgn(mixsignal,snr[j])
dedssignal1=dedsss(receivesignal,c1,chipRate,fs)
demoSignal1=demodu(dedssignal1,dataRate,fc,fs)
dedssignal2=dedsss(receivesignal,c2,chipRate,fs)
demoSignal2=demodu(dedssignal2,dataRate,fc,fs)
dedssignal3=dedsss(receivesignal,c3,chipRate,fs)
demoSignal3=demodu(dedssignal3,dataRate,fc,fs)
q=0
for i in range(len(signal1)):
if demoSignal1[i]!=signal1[i]:
q=q+1
err_bit1=np.insert(err_bit1,j,q/N)
p=0
for i in range(len(signal2)):
if demoSignal2[i]!=signal2[i]:
p=p+1
err_bit2=np.insert(err_bit2,j,p/N)
s=0
for i in range(len(signal3)):
if demoSignal3[i]!=signal3[i]:
s=s+1
err_bit3=np.insert(err_bit3,j,s/N)
依次进行信号输入、产生M序列、序列扩频、调制、加入高斯白噪声、解扩、解调、输出
3)、输出结果,并作出误比特率与信噪比的线性图
print("用户1的误比特率:",err_bit1)
print("用户2的误比特率:",err_bit2)
print("用户3的误比特率:",err_bit3)
plt.plot(snr,err_bit1)
plt.plot(snr,err_bit2)
plt.plot(snr,err_bit3)
plt.grid()
plt.legend("123",loc='upper right')
plt.xlabel('SNR')
plt.ylabel('BER')
plt.title('SNR-BER')
plt.show()
作出信噪比与误比特率的线性图!
1)、扩频通信仿真运行结果
2)、运行结果分析
(1)、用户一通过2径衰落、用户二通过3径衰落,用户四通过4径衰落,的图像可以看出,从上之下为用户1,2,3!
(2)、随着信噪比的增加,用户的误比特率会降低,信噪比越大,误比特率越低。
由于信号是随机产生,故每次的运行结果都不一样,但是并不影响最后的误比特率与信噪比的线性关系哦!
import numpy as np
import random
import matplotlib.pyplot as plt
#产生信息(1,-1)的信息流
def information(N):#输入比特流的个数N,输出我们的信号,要么是1,要么是0
signal=np.array([])
for i in range(N):
x=random.randint(0,1)
if x>=0.5:
x=1
else:
x=0
signal=np.insert(signal,len(signal),x*2-1)
#print(signal)
return signal
#signal(15)
#扩频码的产生,只产生一个周期的M序列
def genMseq(b):#b为c0-cn的个数 b0对应Cn,bn对应C0
N=len(b)-1#N指寄存器个数
D=np.ones(N)#寄存器初始状态全1
A=b[N-1::-1]
#print(A)
c=np.array([])
for i in range((2**N)-1): #循环
c1=(np.dot(D,A))%2#点乘求和,并与2求余数
#print(c1)
c=np.insert(c,len(c),D[N-1])
D=D[0:N-1]
D=np.insert(D,0,c1)
#print(D)
for i in range(len(c)):
c[i]=int(c[i]*2-1)
#print(c)
return c
#genMseq([1,0,1,0])
#扩频
def dsss(signal,c):
ssignal=np.array([])
for i in range(len(signal)):
ssignal=np.insert(ssignal,len(ssignal),signal[i]*c)
#print(ssignal)
return ssignal
#dsss([1,-1,1],1)
#调制 采用BPSK调制
def modu(signal,dataRate,fc,fs):#dataRate符号周期 fc载波频率 fs采样频率 Tb=1/dataRate
t=np.linspace(0,1/dataRate,int(fs/dataRate))
carrier=np.array([])
carrier=np.insert(carrier,len(carrier),np.cos(2*(np.pi)*fc*t))
#print(carrier)
modusignal=np.array([])
for i in range(len(signal)):
modusignal=np.insert(modusignal,len(modusignal),signal[i]*carrier)
#print(modusignal)
return modusignal
#高斯白噪声产生
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 dedsss(receiveSignal,c,chipRate,fs):
L=int(fs/chipRate)#16
c1=np.array([])
a=np.ones(L)
for i in range(len(c)):
c1=np.insert(c1,len(c1),c[i]*a)
dessignal=np.array([])
for i in range(0,len(receiveSignal),len(c1)):
h=receiveSignal[i:i+len(c1)]
dessignal=np.insert(dessignal,len(dessignal),h*c1)
#print(h)
return dessignal
#解调实现
def demodu(Resignal,datarate,fc,fs):
t=np.linspace(0,1/datarate,int(fs/datarate))
carrier=np.array([])
carrier=np.insert(carrier,len(carrier),np.cos(2*(np.pi)*fc*t))
Lc=len(carrier)
Ls=len(Resignal)
designal=np.array([])
for i in range(0,Ls,Lc):
h=Resignal[i:i+Lc]
designal=np.insert(designal,len(designal),h*carrier)
demoSignal=np.array([])
sum=0
for i in range(0,Ls,Lc):
threshold=np.sum(designal[i:i + Lc - 1])
if threshold>0:
tt=1
else:
tt=-1
demoSignal=np.insert(demoSignal,len(demoSignal),tt)
return demoSignal
dataRate=1000
chipRate=31*dataRate
fc=chipRate*2
fs=fc*8
N=300
c=31
b1=[1,0,0,1,0,1]
b2=[1,1,0,1,1,1]
b3=[1,1,1,1,0,1]
snr=np.array([])
for i in range(-20,-8,2):
snr=np.insert(snr,len(snr),i)
#print(snr)
err_bit1=np.array([])
err_bit2=np.array([])
err_bit3=np.array([])
for j in range(len(snr)):
signal1=information(N)
signal2=information(N)
signal3=information(N)
c1=genMseq(b1)
c2=genMseq(b2)
c3=genMseq(b3)
dssignal1=dsss(signal1,c1)
dssignal2=dsss(signal2,c2)
dssignal3=dsss(signal3,c3)
modusignal1=modu(dssignal1,chipRate,fc,fs)
modusignal2=modu(dssignal2,chipRate,fc,fs)
modusignal3=modu(dssignal3,chipRate,fc,fs)
mixsignal=modusignal1+modusignal2+modusignal3
receivesignal=awgn(mixsignal,snr[j])
dedssignal1=dedsss(receivesignal,c1,chipRate,fs)
demoSignal1=demodu(dedssignal1,dataRate,fc,fs)
dedssignal2=dedsss(receivesignal,c2,chipRate,fs)
demoSignal2=demodu(dedssignal2,dataRate,fc,fs)
dedssignal3=dedsss(receivesignal,c3,chipRate,fs)
demoSignal3=demodu(dedssignal3,dataRate,fc,fs)
q=0
for i in range(len(signal1)):
if demoSignal1[i]!=signal1[i]:
q=q+1
err_bit1=np.insert(err_bit1,j,q/N)
p=0
for i in range(len(signal2)):
if demoSignal2[i]!=signal2[i]:
p=p+1
err_bit2=np.insert(err_bit2,j,p/N)
s=0
for i in range(len(signal3)):
if demoSignal3[i]!=signal3[i]:
s=s+1
err_bit3=np.insert(err_bit3,j,s/N)
print("用户1的误比特率:",err_bit1)
#print("发射信号:",signal1)
#print("解调信号:",demoSignal1)
print("用户2的误比特率:",err_bit2)
#print("发射信号:",signal2)
#print("解调信号:",demoSignal3)
print("用户3的误比特率:",err_bit3)
#print("发射信号:",signal3)
#print("解调信号:",demoSignal3)
plt.plot(snr,err_bit1)
plt.plot(snr,err_bit2)
plt.plot(snr,err_bit3)
plt.grid()
plt.legend("123",loc='upper right')
plt.xlabel('SNR')
plt.ylabel('BER')
plt.title('SNR-BER')
plt.show()
以上的所有代码建立在M序列周期为31的基础上哦,至于题目要求的M序列63或者127周期,需要小伙伴们自己修改哈,该的地方比较简单,你们需要锻炼一下啦!
以上就是本次博客的全部内容啦,通过本次博客,大家可以更好的了解到BPSK的的调制与解调原理,也能够对BPSK应用于生活中的调制解调问题有一定的了解,同时,林君学长也希望大家能够深入的了解代码的具体意思,理解原理;代码有错误的地方记得给林君学长留言改正。
同时、遇到问题的小伙伴也记得评论区留言,林君学长看到会给大家回复解答的,这个学长不太冷!
陈一月的又一天编程岁月^ _ ^