信号调制与解调python

1.简介:

调制:把基带信号,也就是包含传输信息的有效信号加载到某个载波(通常为高频的正弦或余弦波)的过程称为调制,得到的信号称为已调信号调制是指载波信号在基带信号的作用下发生改变,包含信息的基带信号加载在载波上,即载波受基带信号的调制。

解调:调制的逆过程,就是通过某种信号处理手段从已调信号中得到原始包含传输信息的有效信号。

2.调制的优点:

  1. 调制能实现信号的频谱转移,从低频信号搬移到高频处,这样也就扩大了基带有效信号的频谱范围;

  2. 低频频带窄,都用低频传输,会造成堵塞,调制能够扩宽传输频带,提高了频率利用率;

  3. 调制能够将多路基带信号加载到频率不同的载波上,完成信号的频率分配,使多路信号互不干扰地在同一个信道上传输,实现频分复用;

  4. 调制还可以减弱噪声和降低干扰。

3.信号调制——调幅(AM)

3.1 双边带幅度调制(DSB-AM)与解调

1.假设基带信号为f=A\cdot cos\omega _{m}t,即幅度为A,初始相位为0,频率为\omega _{m};载波信号z=B\cdot cos\omega _{c}t为幅度B,初始相位为0,频率为\omega _{c}的余弦信号,其中\omega _{c}远大于\omega _{m}基带信号乘以载波信号进行调制,得到调制后的信号:F = A\cdot cos\omega _{m}t\cdot B\cdot cos\omega _{c}t=\frac{1}{2}\left ( A\cdot Bcos\left (\omega _{c}t+\omega _{m}t \right ) +A\cdot Bcos\left ( \omega _{c}t -\omega _{m}t\right )\right )

 2.信号做完调制后,基带信号就转到了频率为\omega _{c}附近对于基带信号与载波信号直接相乘的调制方式称为双边带幅度调制。然后继续将调制后的信号乘以载波信号进行解调,得到解调信号:P=F\cdot cos\omega _{c}t=\frac{1}{2}A\cdot B^{2} \left ( cos\omega _{m}t+cos\omega _{m}t\cdot cos2\omega _{c}t \right )。为了得到原来的基带信号,只需要用低通滤波过滤掉\omega _{c}的信号,再乘以\frac{2}{B^{2}},就得到原始信号了

3.2 单边带幅度调制(SSB-AM)与解调

从已调信号F中获得某一边带的信号,有两种方法分别是滤波法和相移法。

滤波法:调制后的信号频率在\omega _{c}附近,你需要哪一段就设置滤波器把另一半滤掉就好。

相移法:单边调制信号为:F_{SSB}=\frac{1}{2}AB\cdot cos\left (\omega _{m}t\pm \omega _{c}t \right )=\frac{1}{2}AB\cdot \left ( cos\omega _{m}t\cdot cos\omega _{c}t\mp sin\omega _{m}t\cdot sin\omega _{c}t \right )

单边解调信号为:P_{SSB}=\frac{1}{4}A\cdot B^{2}\cdot \left ( cos\omega _{m}t+cos\left ( \omega _{m}t\mp 2\omega _{c}t \right ) \right ),要想得到基带信号,需要做一个低通滤波,再乘以\frac{4}{B^{2}} ,得到基带信号。

注:A\cdot sin\left ( \omega _{m}t \right )为基带信号的希尔伯特变换

4.案例分析

1.画出一个周期的矩形波,周期为10,振幅为2的基带信号。

2. 令载波是一频率为100 Hz,振幅为1,初相为0的余弦波。

3.查看基带信号与已调信号的归一化频谱的对比。

 4.还原基带信号。

5. python程序。

import numpy as np
import scipy.fftpack as fftp
import matplotlib as mpl
import matplotlib.pyplot as plt
import scipy.signal as signalP
mpl.rcParams['font.sans-serif'] = ['KaiTi']   # 保证正常显示中文
mpl.rcParams['font.serif'] = ['KaiTi']        # 保证正常显示中文
mpl.rcParams['axes.unicode_minus'] = False    # 保证负号正常显示


def butter_lowpass_filtfilt(data, cutoff, fs, order=5):
    """
    对信号作低通滤波
    :param data:     输入信号
    :param cutoff:  通带截至频率
    :param fs:     采样频率
    :param order:  滤波器的阶数
    :return:       返回值为y,经低通滤波后的信号
    """
    b, a = signalP.butter(5, cutoff/fs*2, btype='low')
    shape = data.shape
    if shape[0] != 1:
        data = data.T
    y = signalP.filtfilt(b, a, data)
    y =y.T
    return y


dt = 0.001                                    # 时间域采样间隔
Fs = 1/dt                                     # 采样率
T = 10                                         # 矩形波的周期
nT = 10                                       # 总的周期数
nPT = int(T/dt+0.5)                           # 每个周期的样点数
n = nT*nPT                                    # 总样点数
alpha = 0.5                                   # 矩形波的占空比
t = np.arange(dt, n*dt+dt, dt)
f = np.zeros((n, 1), dtype=np.float64)
A = 2
for i in range(0, nT, 1):
    f[(i+1)*nPT-int(alpha*nPT):(i+1)*nPT] = A   # 得到矩形波


fc = 100  # 载波的频率
g1 = np.cos(2*np.pi*fc*t).reshape(n, 1)
g2 = np.sin(2*np.pi*fc*t).reshape(n, 1)
hf = fftp.hilbert(f.reshape(n, ))        # 矩形波的希尔伯特变换

s = 0.5*f*g1-0.5*hf.reshape(n, 1)*g2     # 已调信号
s_dm = s*g1                              # 解调
cutoff = 60                              # 截至频率
order = 6                                # 滤波器的阶数
s_dm = 4*butter_lowpass_filtfilt(s_dm, cutoff, Fs, order)  # 作低通滤波

f_spec = np.fft.fft(f, n, 0)                # 作傅立叶变换
freq = np.fft.fftfreq(n, dt).reshape(n, 1)  # 得到每点的频率
f_spec_amp = abs(f_spec)/(n/2)              # 对频谱的振幅作归一化
f_spec_amp[0] = f_spec_amp[0]/2
f_spec_amp[int(n/2)+1] = f_spec_amp[int(n/2)+1]/2

s_spec = np.fft.fft(s, n, 0)
s_spec_amp = abs(s_spec)/(n/2)
s_spec_amp[0] = s_spec_amp[0]/2
s_spec_amp[int(n/2)+1] = s_spec_amp[int(n/2)+1]/2

# 绘制一个周期内的矩形波
plt.figure(num=1)
plt.plot(t[0:nPT], f[0:nPT], 'b-')
plt.xlim(0, T)
plt.ylim(-3, 3)
plt.xlabel('时间/(s)')
plt.ylabel('振幅')
plt.title('一个周期内的矩形波信号')
plt.savefig('图1.jpg', dpi=600)
plt.show()

# 绘制已调信号
plt.figure(num=2)
plt.plot(t[0:int(10/fc/dt+0.5)], s[0:int(10/fc/dt+0.5)], 'b-')
plt.xlim(0, 10/fc)
plt.ylim(-3, 3)
plt.xlabel('时间/(s)')
plt.ylabel('振幅')
plt.title('已调信号')
plt.savefig('图2.jpg')
plt.show()

# 绘制基带信号与已调信号的频谱
plt.figure(num=3)
plt.plot(freq, f_spec_amp, 'b-', freq, s_spec_amp, 'r-')
plt.xlim(min(freq), max(freq))
plt.legend(('基带信号的频谱', '已调信号的频谱'), loc='upper right')
plt.xlabel('频率/(Hz)')
plt.ylabel('振幅')
plt.title('基带信号和已调信号的归一化频谱')
plt.savefig('图3.jpg')
plt.show()

# 绘制基带信号与解调信号
plt.figure(num=4)
plt.plot(t[0:nPT], f[0:nPT], 'k-', t[0:nPT], s_dm[0:nPT], 'r-')
plt.legend(('基带信号', '解调信号'), loc='upper right')
plt.xlim(0, T)
plt.ylim(-3, 3)
plt.xlabel('时间/(s)')
plt.ylabel('振幅')
plt.title('基带信号和解调信号')
plt.savefig('图4.jpg')
plt.show()

 

引用\[1\]:在Python中,可以使用commpy库来实现16QAM调制解调。首先,需要导入commpy库和numpy库。然后,可以使用commpy库中的QAMModem类来实现16QAM调制调制的过程是将输入的比特流转换为对应的16QAM符号。具体的实现代码如下所示: ```python import commpy as cpy import numpy as np def modulate_16qam(bits): qam16 = cpy.QAMModem(16) symbol = qam16.modulate(bits) return symbol ``` 对于解调,可以使用commpy库中的QAMModem类的demodulate方法来实现。解调的过程是将接收到的信号转换为对应的比特流。具体的实现代码如下所示: ```python def demodulate_16qam(signal): qam16 = cpy.QAMModem(16) bits = qam16.demodulate(signal, 'hard') return bits ``` 引用\[3\]:另外,还可以使用字典来实现16QAM调制解调。首先,需要定义一个字典来保存16QAM中比特与振幅的对应关系。然后,通过遍历比特流,将每个比特组合转换为对应的复数,从而实现16QAM调制。具体的实现代码如下所示: ```python import numpy as np def modulate_16qam(bits): diagram = { '00': complex(-3, 3), '01': complex(-3, 1), '11': complex(-1, 1), '10': complex(-1, 3), '110': complex(-3, -3), '111': complex(-3, -1), '101': complex(-1, -1), '100': complex(-1, -3), '010': complex(3, 3), '011': complex(3, 1), '001': complex(1, 1), '000': complex(1, 3), '101': complex(3, -3), '111': complex(3, -1), '110': complex(1, -1), '100': complex(1, -3) } symbol = \[\] for i in range(0, len(bits), 4): bit_group = bits\[i:i+4\] symbol.append(diagram\[bit_group\]) return np.array(symbol) ``` 对于解调,可以通过查询字典来将接收到的复数转换为对应的比特组合。具体的实现代码如下所示: ```python def demodulate_16qam(signal): diagram = { complex(-3, 3): '00', complex(-3, 1): '01', complex(-1, 1): '11', complex(-1, 3): '10', complex(-3, -3): '110', complex(-3, -1): '111', complex(-1, -1): '101', complex(-1, -3): '100', complex(3, 3): '010', complex(3, 1): '011', complex(1, 1): '001', complex(1, 3): '000', complex(3, -3): '101', complex(3, -1): '111', complex(1, -1): '110', complex(1, -3): '100' } bits = \[\] for s in signal: bit_group = diagram\[s\] bits.extend(list(bit_group)) return np.array(bits) ``` 以上是两种实现16QAM调制解调的方法,你可以根据自己的需求选择其中一种来使用。 #### 引用[.reference_title] - *1* *2* [【信号处理】Python实现BPSK、QPSK、8PSK、8QAM、16QAM、64QAM的调制解调](https://blog.csdn.net/weixin_43935696/article/details/120596442)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [16QAM调制的仿真及其Python实现的代码(超级详细)](https://blog.csdn.net/m0_46303328/article/details/121092456)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

似水不惧

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

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

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

打赏作者

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

抵扣说明:

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

余额充值