調制,就是將原始信號轉換為適合在信道中傳輸的形式的一種過程,在無線通信中,調制一般均指載波調制,而解調則是調制的逆過程,即將原始信號從已調信號中恢復出來。
進行載波調制,主要為實現以下目標:
1)在無線傳輸中,信號是以電磁波的形式通過天線輻射到空間的。為了獲得較高的輻射效率,天線的尺寸必須與發射信號波長相匹配。因此,需要通過調制將基帶信號的頻譜搬遷至較高的頻帶,使得已調信號的頻域與信道的帶通特性相匹配,這樣就可以以較小的發送功率和較短的天線來輻射電磁波。
2)將多個基帶信號的頻譜搬移至不同的頻點,從而實現頻分復用,提高頻譜利用效率。
3)擴展信號帶寬,提高系統抗干擾、抗衰落能力
在5G NR中,主要使用正交振幅調制(Quadrature Amplitude Modulation, QAM),包括BSPK,QPSK,16QAM, 64QAM, 256QAM等;它是一種振幅和相位聯合鍵控的調制方式,由於其矢量圖看似星座,故又稱為星座(Constellation)調制。在3GPP 38.211協議中,對物理層各信道的調制以及解調方式進行說明。
在π/2-BPSK中,二進制比特b(i)映射至復值調制符號d(i)

在BPSK中,二進制比特b(i)映射至復值調制符號d(i)
在QPSK中,二進制比特b(2i)和b(2i+1)映射至復值調制符號d(i)
在16QAM中,二進制比特b(4i), b(4i+1), b(4i+2), b(4i+3)映射至復值調制符號d(i)
在64QAM中,二進制比特b(6i), b(6i+1),b(6i+2),b(6i+3),b(6i+4),b(6i+5)映射至復值調制符號d(i)
在256QAM中,二進制比特b(8i), b(8i+1),b(8i+2),b(8i+3),b(8i+4),b(8i+5),b(8i+6),b(8i+7)映射至復值調制符號d(i)
下面是通過python實現的調制和硬解調的代碼:
1 # -*- coding: utf-8 -*- 2 # @Time : 2019/11/24 10:24 3 # @Author : Administrator 4 # @File : modulator.py 5 # @Software : PyCharm 6 7 import numpy as np 8 9 class ModulateTable(): 10 11 def __init__(self, **kwargs): 12 self._bpsk_cor = np.sqrt(1/2) 13 self._qpsk_cor = np.sqrt(1/2) 14 self._16qam_cor = np.sqrt(1/10) 15 self._64qam_cor = np.sqrt(1/42) 16 self._256qam_cor = np.sqrt(1/170) 17 18 self.const_bit = {'BPSK': 1, 'QPSK': 2, '16QAM': 4} 19 self.bit_table = {'BPSK': np.array( [0, 1] ), 20 'QPSK': np.array([[0, 0], [0, 1], [1, 0], [1, 1]]), 21 '16QAM': np.array([[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 0, 1, 1], 22 [0, 1, 0, 0], [0, 1, 0, 1], [0, 1, 1, 0], [0, 1, 1, 1], 23 [1, 0, 0, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 0, 1, 1], 24 [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 0], [1, 1, 1, 1]])} 25 26 def _bpsk_table(self): 27 return np.array([1+1j, 1-1j]) 28 29 def _qpsk_table(self): 30 return np.array([1+1j, 1-1j, -1+1j, -1-1j]) 31 32 def _16qam_table(self): 33 return np.array([ 3+3j, 1+3j, -1+3j, -3+3j, 34 -3+1j, -1+1j, 1+1j, 3+1j, 35 3-1j, 1-1j, -1-1j, -3-1j, 36 -3-3j, -1-3j, 1-3j, 3-3j]) 37 38 class Modulator(ModulateTable): 39 40 def __init__(self, **kwargs): 41 super().__init__(**kwargs) 42 self.mod_type = kwargs.get('mod_type', '') 43 44 def modulate(self, input): 45 46 self._get_symbol_table() 47 const_bit_num = self.const_bit[self.mod_type] 48 bit_table = self._get_bit_table(const_bit_num) 49 50 input = input.reshape((-1, const_bit_num)) 51 order = np.dot(input, bit_table) 52 ouput = self.symbol_table[order] 53 54 return ouput 55 56 def demodu_hard(self, input): 57 58 self._get_symbol_table() 59 bit_table = self.bit_table[self.mod_type] 60 min_loc = list(map(self.cal_distance, input)) 61 output = bit_table[min_loc].flatten() 62 63 return output 64 65 def demodu_soft(self, input): 66 pass 67 68 def cal_distance(self, rec_symbol): 69 return np.argmin(abs(rec_symbol - self.symbol_table)) 70 71 def _get_symbol_table(self): 72 73 if self.mod_type == 'BPSK': 74 self.symbol_table = self._bpsk_table() * self._bpsk_cor 75 elif self.mod_type == 'QPSK': 76 self.symbol_table = self._qpsk_table() * self._qpsk_cor 77 elif self.mod_type == '16QAM': 78 self.symbol_table = self._16qam_table() * self._16qam_cor 79 else: 80 raise ValueError("Only support BPSK, QPSK, 16QAM in modulate!") 81 82 def _get_bit_table(self, bit_num): 83 return np.logspace((bit_num - 1), 0, bit_num, endpoint=True, base=2).astype(np.int) 84 85 86 if __name__ == '__main__': 87 88 input = np.random.randint(0, 2, 1024) 89 90 modu = Modulator(mod_type='16QAM') 91 demodu_in = modu.modulate(input) 92 demodu_ou = modu.demodu_hard(demodu_in) 93 print(demodu_in) 94 print(demodu_ou) 95 96 if (input == demodu_ou).all(): 97 print("right") 98 else: 99 print("error")