这个wifi解调安装起来很简单,没什么坑,就是老外按照gnuradio不同版本也分了几个版本,我下载的是3.7版本。

先安装3.7版本的gr-foo再安装gr-ieee802-11就行。

下面的安装脚本下载的是主分支的,如果要针对3.7或者3.8的,可以在网页里直接选择对应版本下载。

或者从这里下载:

链接:https://pan.baidu.com/s/1sBmPa1X2IInwJLV4qFDa3Q 
提取码:udhu

这是我下载的3.7版本的

git clone https://github.com/bastibl/gr-foo.git
cd gr-foo
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfiggit clone git://github.com/bastibl/gr-ieee802-11.git
cd gr-ieee802-11
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig

还有一个问题,老外本来是用uhd模块做的收发,limesdr虽然能支持,但是很麻烦,osmocom也能用,但是噪声很多,我最后用的是gr-limesdr,把中心频率和采样率填进去就行,采样率还要填到几个滤波器带宽里去。

演示视频:https://www.bilibili.com/video/av73714958

我只实现了wifi接收和解调,能够看到我的路由器发出的星座图,并且可以把抓取的数据用wireshark分析数据包,我对比了gnuradio命令行输出的一些设备mac和路由器配置页面里的设备mac是一样的。但是发射还不行,如果用它的流图发射,我接收到的星座图很奇怪。老外还提供了一个transceiver流图,理论上可以用这个实现虚拟网卡和其他wifi设备做udp通信,但是我现在发射还不行,改天搞个usrp试试。


USRP B210发射:

https://www.bilibili.com/video/BV1UA411Y7b8/

不要装libuhd003.010.003,他现在配套的下载程序已经无法下载合适的firmware和gateware了。
要用新版的libuhd3.15.0,但是要添加ppa。
sudo add-apt-repository -y ppa:ettusresearch/uhd

sudo apt update

不要apt安装gnuradio,否则会自动安装libuhd003.010.003
从github下载gnuradio-maint-3.7 (3.7.13)然后编译安装


USRP B210 wifi虚拟网卡:

https://www.bilibili.com/video/BV1Sp4y1v7kq

电脑1运行:

sudo ifconfig tap0 down
sudo ifconfig tap0 hw ether 30:14:4a:e6:46:e4
sudo ifconfig tap0 mtu 440
sudo ifconfig tap0 up
sudo ifconfig tap0 192.168.123.2sudo route del -net 192.168.123.0/24
sudo route add -net 192.168.123.0/24 mss 400 dev tap0sudo tc qdisc add dev tap0 root netem delay 10ms

电脑1运行wifi_transceiver.py脚本

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##################################################
# GNU Radio Python Flow Graph
# Title: Wifi Transceiver
# GNU Radio version: 3.7.13.5
##################################################if __name__ == '__main__':import ctypesimport sysif sys.platform.startswith('linux'):try:x11 = ctypes.cdll.LoadLibrary('libX11.so')x11.XInitThreads()except:print "Warning: failed to XInitThreads()"import os
import sys
sys.path.append(os.environ.get('GRC_HIER_PATH', os.path.expanduser('~/.grc_gnuradio')))from PyQt4 import Qt
from PyQt4.QtCore import QObject, pyqtSlot
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import qtgui
from gnuradio import uhd
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from gnuradio.qtgui import Range, RangeWidget
from optparse import OptionParser
from wifi_phy_hier import wifi_phy_hier  # grc-generated hier_block
import foo
import ieee802_11
import sip
import time
from gnuradio import qtguiclass wifi_transceiver(gr.top_block, Qt.QWidget):def __init__(self):gr.top_block.__init__(self, "Wifi Transceiver")Qt.QWidget.__init__(self)self.setWindowTitle("Wifi Transceiver")qtgui.util.check_set_qss()try:self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))except:passself.top_scroll_layout = Qt.QVBoxLayout()self.setLayout(self.top_scroll_layout)self.top_scroll = Qt.QScrollArea()self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)self.top_scroll_layout.addWidget(self.top_scroll)self.top_scroll.setWidgetResizable(True)self.top_widget = Qt.QWidget()self.top_scroll.setWidget(self.top_widget)self.top_layout = Qt.QVBoxLayout(self.top_widget)self.top_grid_layout = Qt.QGridLayout()self.top_layout.addLayout(self.top_grid_layout)self.settings = Qt.QSettings("GNU Radio", "wifi_transceiver")self.restoreGeometry(self.settings.value("geometry").toByteArray())################################################### Variables##################################################self.tx_gain = tx_gain = 0.75self.samp_rate = samp_rate = 5e6self.rx_gain = rx_gain = 0.75self.lo_offset = lo_offset = 0self.freq = freq = 5890000000self.encoding = encoding = 0self.chan_est = chan_est = 0################################################### Blocks##################################################self._tx_gain_range = Range(0, 1, 0.01, 0.75, 200)self._tx_gain_win = RangeWidget(self._tx_gain_range, self.set_tx_gain, "tx_gain", "counter_slider", float)self.top_grid_layout.addWidget(self._tx_gain_win)self._samp_rate_options = [5e6, 10e6, 20e6]self._samp_rate_labels = ["5 MHz", "10 MHz", "20 MHz"]self._samp_rate_tool_bar = Qt.QToolBar(self)self._samp_rate_tool_bar.addWidget(Qt.QLabel("samp_rate"+": "))self._samp_rate_combo_box = Qt.QComboBox()self._samp_rate_tool_bar.addWidget(self._samp_rate_combo_box)for label in self._samp_rate_labels: self._samp_rate_combo_box.addItem(label)self._samp_rate_callback = lambda i: Qt.QMetaObject.invokeMethod(self._samp_rate_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._samp_rate_options.index(i)))self._samp_rate_callback(self.samp_rate)self._samp_rate_combo_box.currentIndexChanged.connect(lambda i: self.set_samp_rate(self._samp_rate_options[i]))self.top_grid_layout.addWidget(self._samp_rate_tool_bar)self._rx_gain_range = Range(0, 1, 0.01, 0.75, 200)self._rx_gain_win = RangeWidget(self._rx_gain_range, self.set_rx_gain, "rx_gain", "counter_slider", float)self.top_grid_layout.addWidget(self._rx_gain_win)self._lo_offset_options = (0, 6e6, 11e6, )self._lo_offset_labels = (str(self._lo_offset_options[0]), str(self._lo_offset_options[1]), str(self._lo_offset_options[2]), )self._lo_offset_tool_bar = Qt.QToolBar(self)self._lo_offset_tool_bar.addWidget(Qt.QLabel("lo_offset"+": "))self._lo_offset_combo_box = Qt.QComboBox()self._lo_offset_tool_bar.addWidget(self._lo_offset_combo_box)for label in self._lo_offset_labels: self._lo_offset_combo_box.addItem(label)self._lo_offset_callback = lambda i: Qt.QMetaObject.invokeMethod(self._lo_offset_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._lo_offset_options.index(i)))self._lo_offset_callback(self.lo_offset)self._lo_offset_combo_box.currentIndexChanged.connect(lambda i: self.set_lo_offset(self._lo_offset_options[i]))self.top_grid_layout.addWidget(self._lo_offset_tool_bar)self._freq_options = [2412000000.0, 2417000000.0, 2422000000.0, 2427000000.0, 2432000000.0, 2437000000.0, 2442000000.0, 2447000000.0, 2452000000.0, 2457000000.0, 2462000000.0, 2467000000.0, 2472000000.0, 2484000000.0, 5170000000.0, 5180000000.0, 5190000000.0, 5200000000.0, 5210000000.0, 5220000000.0, 5230000000.0, 5240000000.0, 5250000000.0, 5260000000.0, 5270000000.0, 5280000000.0, 5290000000.0, 5300000000.0, 5310000000.0, 5320000000.0, 5500000000.0, 5510000000.0, 5520000000.0, 5530000000.0, 5540000000.0, 5550000000.0, 5560000000.0, 5570000000.0, 5580000000.0, 5590000000.0, 5600000000.0, 5610000000.0, 5620000000.0, 5630000000.0, 5640000000.0, 5660000000.0, 5670000000.0, 5680000000.0, 5690000000.0, 5700000000.0, 5710000000.0, 5720000000.0, 5745000000.0, 5755000000.0, 5765000000.0, 5775000000.0, 5785000000.0, 5795000000.0, 5805000000.0, 5825000000.0, 5860000000.0, 5870000000.0, 5880000000.0, 5890000000.0, 5900000000.0, 5910000000.0, 5920000000.0]self._freq_labels = ['  1 | 2412.0 | 11g', '  2 | 2417.0 | 11g', '  3 | 2422.0 | 11g', '  4 | 2427.0 | 11g', '  5 | 2432.0 | 11g', '  6 | 2437.0 | 11g', '  7 | 2442.0 | 11g', '  8 | 2447.0 | 11g', '  9 | 2452.0 | 11g', ' 10 | 2457.0 | 11g', ' 11 | 2462.0 | 11g', ' 12 | 2467.0 | 11g', ' 13 | 2472.0 | 11g', ' 14 | 2484.0 | 11g', ' 34 | 5170.0 | 11a', ' 36 | 5180.0 | 11a', ' 38 | 5190.0 | 11a', ' 40 | 5200.0 | 11a', ' 42 | 5210.0 | 11a', ' 44 | 5220.0 | 11a', ' 46 | 5230.0 | 11a', ' 48 | 5240.0 | 11a', ' 50 | 5250.0 | 11a', ' 52 | 5260.0 | 11a', ' 54 | 5270.0 | 11a', ' 56 | 5280.0 | 11a', ' 58 | 5290.0 | 11a', ' 60 | 5300.0 | 11a', ' 62 | 5310.0 | 11a', ' 64 | 5320.0 | 11a', '100 | 5500.0 | 11a', '102 | 5510.0 | 11a', '104 | 5520.0 | 11a', '106 | 5530.0 | 11a', '108 | 5540.0 | 11a', '110 | 5550.0 | 11a', '112 | 5560.0 | 11a', '114 | 5570.0 | 11a', '116 | 5580.0 | 11a', '118 | 5590.0 | 11a', '120 | 5600.0 | 11a', '122 | 5610.0 | 11a', '124 | 5620.0 | 11a', '126 | 5630.0 | 11a', '128 | 5640.0 | 11a', '132 | 5660.0 | 11a', '134 | 5670.0 | 11a', '136 | 5680.0 | 11a', '138 | 5690.0 | 11a', '140 | 5700.0 | 11a', '142 | 5710.0 | 11a', '144 | 5720.0 | 11a', '149 | 5745.0 | 11a (SRD)', '151 | 5755.0 | 11a (SRD)', '153 | 5765.0 | 11a (SRD)', '155 | 5775.0 | 11a (SRD)', '157 | 5785.0 | 11a (SRD)', '159 | 5795.0 | 11a (SRD)', '161 | 5805.0 | 11a (SRD)', '165 | 5825.0 | 11a (SRD)', '172 | 5860.0 | 11p', '174 | 5870.0 | 11p', '176 | 5880.0 | 11p', '178 | 5890.0 | 11p', '180 | 5900.0 | 11p', '182 | 5910.0 | 11p', '184 | 5920.0 | 11p']self._freq_tool_bar = Qt.QToolBar(self)self._freq_tool_bar.addWidget(Qt.QLabel("freq"+": "))self._freq_combo_box = Qt.QComboBox()self._freq_tool_bar.addWidget(self._freq_combo_box)for label in self._freq_labels: self._freq_combo_box.addItem(label)self._freq_callback = lambda i: Qt.QMetaObject.invokeMethod(self._freq_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._freq_options.index(i)))self._freq_callback(self.freq)self._freq_combo_box.currentIndexChanged.connect(lambda i: self.set_freq(self._freq_options[i]))self.top_grid_layout.addWidget(self._freq_tool_bar)self._encoding_options = [0, 1, 2, 3, 4, 5, 6, 7]self._encoding_labels = ["BPSK 1/2", "BPSK 3/4", "QPSK 1/2", "QPSK 3/4", "16QAM 1/2", "16QAM 3/4", "64QAM 2/3", "64QAM 3/4"]self._encoding_group_box = Qt.QGroupBox("encoding")self._encoding_box = Qt.QHBoxLayout()class variable_chooser_button_group(Qt.QButtonGroup):def __init__(self, parent=None):Qt.QButtonGroup.__init__(self, parent)@pyqtSlot(int)def updateButtonChecked(self, button_id):self.button(button_id).setChecked(True)self._encoding_button_group = variable_chooser_button_group()self._encoding_group_box.setLayout(self._encoding_box)for i, label in enumerate(self._encoding_labels):radio_button = Qt.QRadioButton(label)self._encoding_box.addWidget(radio_button)self._encoding_button_group.addButton(radio_button, i)self._encoding_callback = lambda i: Qt.QMetaObject.invokeMethod(self._encoding_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._encoding_options.index(i)))self._encoding_callback(self.encoding)self._encoding_button_group.buttonClicked[int].connect(lambda i: self.set_encoding(self._encoding_options[i]))self.top_grid_layout.addWidget(self._encoding_group_box)self._chan_est_options = [ieee802_11.LS, ieee802_11.LMS, ieee802_11.STA, ieee802_11.COMB]self._chan_est_labels = ["LS", "LMS", "STA", "Linear Comb"]self._chan_est_group_box = Qt.QGroupBox("chan_est")self._chan_est_box = Qt.QHBoxLayout()class variable_chooser_button_group(Qt.QButtonGroup):def __init__(self, parent=None):Qt.QButtonGroup.__init__(self, parent)@pyqtSlot(int)def updateButtonChecked(self, button_id):self.button(button_id).setChecked(True)self._chan_est_button_group = variable_chooser_button_group()self._chan_est_group_box.setLayout(self._chan_est_box)for i, label in enumerate(self._chan_est_labels):radio_button = Qt.QRadioButton(label)self._chan_est_box.addWidget(radio_button)self._chan_est_button_group.addButton(radio_button, i)self._chan_est_callback = lambda i: Qt.QMetaObject.invokeMethod(self._chan_est_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._chan_est_options.index(i)))self._chan_est_callback(self.chan_est)self._chan_est_button_group.buttonClicked[int].connect(lambda i: self.set_chan_est(self._chan_est_options[i]))self.top_grid_layout.addWidget(self._chan_est_group_box)self.wifi_phy_hier_0 = wifi_phy_hier(bandwidth=samp_rate,chan_est=chan_est,encoding=encoding,frequency=freq,sensitivity=0.56,)self.uhd_usrp_source_0 = uhd.usrp_source(",".join(('', "")),uhd.stream_args(cpu_format="fc32",channels=range(1),),)self.uhd_usrp_source_0.set_samp_rate(samp_rate)self.uhd_usrp_source_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(freq, rf_freq = freq - lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)self.uhd_usrp_source_0.set_normalized_gain(rx_gain, 0)#self.uhd_usrp_source_0.set_auto_dc_offset("", 0)#self.uhd_usrp_source_0.set_auto_iq_balance("", 0)self.uhd_usrp_sink_0 = uhd.usrp_sink(",".join(('', "")),uhd.stream_args(cpu_format="fc32",channels=range(1),),'packet_len',)self.uhd_usrp_sink_0.set_samp_rate(samp_rate)self.uhd_usrp_sink_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(freq, rf_freq = freq - lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)self.uhd_usrp_sink_0.set_normalized_gain(tx_gain, 0)self.qtgui_const_sink_x_0 = qtgui.const_sink_c(48*10, #size"", #name1 #number of inputs)self.qtgui_const_sink_x_0.set_update_time(0.10)self.qtgui_const_sink_x_0.set_y_axis(-2, 2)self.qtgui_const_sink_x_0.set_x_axis(-2, 2)self.qtgui_const_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "")self.qtgui_const_sink_x_0.enable_autoscale(False)self.qtgui_const_sink_x_0.enable_grid(False)self.qtgui_const_sink_x_0.enable_axis_labels(True)if not True:self.qtgui_const_sink_x_0.disable_legend()labels = ['', '', '', '', '','', '', '', '', '']widths = [1, 1, 1, 1, 1,1, 1, 1, 1, 1]colors = ["blue", "red", "red", "red", "red","red", "red", "red", "red", "red"]styles = [0, 0, 0, 0, 0,0, 0, 0, 0, 0]markers = [0, 0, 0, 0, 0,0, 0, 0, 0, 0]alphas = [1.0, 1.0, 1.0, 1.0, 1.0,1.0, 1.0, 1.0, 1.0, 1.0]for i in xrange(1):if len(labels[i]) == 0:self.qtgui_const_sink_x_0.set_line_label(i, "Data {0}".format(i))else:self.qtgui_const_sink_x_0.set_line_label(i, labels[i])self.qtgui_const_sink_x_0.set_line_width(i, widths[i])self.qtgui_const_sink_x_0.set_line_color(i, colors[i])self.qtgui_const_sink_x_0.set_line_style(i, styles[i])self.qtgui_const_sink_x_0.set_line_marker(i, markers[i])self.qtgui_const_sink_x_0.set_line_alpha(i, alphas[i])self._qtgui_const_sink_x_0_win = sip.wrapinstance(self.qtgui_const_sink_x_0.pyqwidget(), Qt.QWidget)self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_win)self.ieee802_11_parse_mac_0 = ieee802_11.parse_mac(False, True)self.ieee802_11_mac_0 = ieee802_11.mac(([0x30, 0x14, 0x4a, 0xe6, 0x46, 0xe4]), ([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]), ([0x42, 0x42, 0x42, 0x42, 0x42, 0x42]))self.ieee802_11_ether_encap_0 = ieee802_11.ether_encap(False)self.foo_packet_pad2_0 = foo.packet_pad2(False, False, 0.001, 10000, 10000)(self.foo_packet_pad2_0).set_min_output_buffer(100000)self.blocks_tuntap_pdu_0 = blocks.tuntap_pdu('tap0', 440, False)self.blocks_pdu_to_tagged_stream_0_0 = blocks.pdu_to_tagged_stream(blocks.complex_t, 'packet_len')self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vcc((0.6, ))(self.blocks_multiply_const_vxx_0).set_min_output_buffer(100000)################################################### Connections##################################################self.msg_connect((self.blocks_tuntap_pdu_0, 'pdus'), (self.ieee802_11_ether_encap_0, 'from tap'))self.msg_connect((self.ieee802_11_ether_encap_0, 'to tap'), (self.blocks_tuntap_pdu_0, 'pdus'))self.msg_connect((self.ieee802_11_ether_encap_0, 'to wifi'), (self.ieee802_11_mac_0, 'app in'))self.msg_connect((self.ieee802_11_mac_0, 'phy out'), (self.wifi_phy_hier_0, 'mac_in'))self.msg_connect((self.wifi_phy_hier_0, 'carrier'), (self.blocks_pdu_to_tagged_stream_0_0, 'pdus'))self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_ether_encap_0, 'from wifi'))self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_mac_0, 'phy in'))self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_parse_mac_0, 'in'))self.connect((self.blocks_multiply_const_vxx_0, 0), (self.foo_packet_pad2_0, 0))self.connect((self.blocks_pdu_to_tagged_stream_0_0, 0), (self.qtgui_const_sink_x_0, 0))self.connect((self.foo_packet_pad2_0, 0), (self.uhd_usrp_sink_0, 0))self.connect((self.uhd_usrp_source_0, 0), (self.wifi_phy_hier_0, 0))self.connect((self.wifi_phy_hier_0, 0), (self.blocks_multiply_const_vxx_0, 0))def closeEvent(self, event):self.settings = Qt.QSettings("GNU Radio", "wifi_transceiver")self.settings.setValue("geometry", self.saveGeometry())event.accept()def get_tx_gain(self):return self.tx_gaindef set_tx_gain(self, tx_gain):self.tx_gain = tx_gainself.uhd_usrp_sink_0.set_normalized_gain(self.tx_gain, 0)def get_samp_rate(self):return self.samp_ratedef set_samp_rate(self, samp_rate):self.samp_rate = samp_rateself._samp_rate_callback(self.samp_rate)self.wifi_phy_hier_0.set_bandwidth(self.samp_rate)self.uhd_usrp_source_0.set_samp_rate(self.samp_rate)self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate)def get_rx_gain(self):return self.rx_gaindef set_rx_gain(self, rx_gain):self.rx_gain = rx_gainself.uhd_usrp_source_0.set_normalized_gain(self.rx_gain, 0)def get_lo_offset(self):return self.lo_offsetdef set_lo_offset(self, lo_offset):self.lo_offset = lo_offsetself._lo_offset_callback(self.lo_offset)self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)def get_freq(self):return self.freqdef set_freq(self, freq):self.freq = freqself._freq_callback(self.freq)self.wifi_phy_hier_0.set_frequency(self.freq)self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)def get_encoding(self):return self.encodingdef set_encoding(self, encoding):self.encoding = encodingself._encoding_callback(self.encoding)self.wifi_phy_hier_0.set_encoding(self.encoding)def get_chan_est(self):return self.chan_estdef set_chan_est(self, chan_est):self.chan_est = chan_estself._chan_est_callback(self.chan_est)self.wifi_phy_hier_0.set_chan_est(self.chan_est)def main(top_block_cls=wifi_transceiver, options=None):from distutils.version import StrictVersionif StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):style = gr.prefs().get_string('qtgui', 'style', 'raster')Qt.QApplication.setGraphicsSystem(style)qapp = Qt.QApplication(sys.argv)tb = top_block_cls()tb.start()tb.show()def quitting():tb.stop()tb.wait()qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)qapp.exec_()if __name__ == '__main__':main()

最后,电脑1命令行再运行:

sudo arp -s 192.168.123.1 12:34:56:78:90:ab

电脑2命令行运行:

sudo ifconfig tap0 down
sudo ifconfig tap0 hw ether 12:34:56:78:90:ab
sudo ifconfig tap0 mtu 440
sudo ifconfig tap0 up
sudo ifconfig tap0 192.168.123.1sudo route del -net 192.168.123.0/24
sudo route add -net 192.168.123.0/24 mss 400 dev tap0sudo tc qdisc del dev tap0 root
sudo tc qdisc add dev tap0 root netem delay 10ms

电脑2运行wifi_transceiver.py脚本

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##################################################
# GNU Radio Python Flow Graph
# Title: Wifi Transceiver
# GNU Radio version: 3.7.13.5
##################################################if __name__ == '__main__':import ctypesimport sysif sys.platform.startswith('linux'):try:x11 = ctypes.cdll.LoadLibrary('libX11.so')x11.XInitThreads()except:print "Warning: failed to XInitThreads()"import os
import sys
sys.path.append(os.environ.get('GRC_HIER_PATH', os.path.expanduser('~/.grc_gnuradio')))from PyQt4 import Qt
from PyQt4.QtCore import QObject, pyqtSlot
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import qtgui
from gnuradio import uhd
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from gnuradio.qtgui import Range, RangeWidget
from optparse import OptionParser
from wifi_phy_hier import wifi_phy_hier  # grc-generated hier_block
import foo
import ieee802_11
import sip
import time
from gnuradio import qtguiclass wifi_transceiver(gr.top_block, Qt.QWidget):def __init__(self):gr.top_block.__init__(self, "Wifi Transceiver")Qt.QWidget.__init__(self)self.setWindowTitle("Wifi Transceiver")qtgui.util.check_set_qss()try:self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))except:passself.top_scroll_layout = Qt.QVBoxLayout()self.setLayout(self.top_scroll_layout)self.top_scroll = Qt.QScrollArea()self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)self.top_scroll_layout.addWidget(self.top_scroll)self.top_scroll.setWidgetResizable(True)self.top_widget = Qt.QWidget()self.top_scroll.setWidget(self.top_widget)self.top_layout = Qt.QVBoxLayout(self.top_widget)self.top_grid_layout = Qt.QGridLayout()self.top_layout.addLayout(self.top_grid_layout)self.settings = Qt.QSettings("GNU Radio", "wifi_transceiver")self.restoreGeometry(self.settings.value("geometry").toByteArray())################################################### Variables##################################################self.tx_gain = tx_gain = 0.75self.samp_rate = samp_rate = 5e6self.rx_gain = rx_gain = 0.75self.lo_offset = lo_offset = 0self.freq = freq = 5890000000self.encoding = encoding = 0self.chan_est = chan_est = 0################################################### Blocks##################################################self._tx_gain_range = Range(0, 1, 0.01, 0.75, 200)self._tx_gain_win = RangeWidget(self._tx_gain_range, self.set_tx_gain, "tx_gain", "counter_slider", float)self.top_grid_layout.addWidget(self._tx_gain_win)self._samp_rate_options = [5e6, 10e6, 20e6]self._samp_rate_labels = ["5 MHz", "10 MHz", "20 MHz"]self._samp_rate_tool_bar = Qt.QToolBar(self)self._samp_rate_tool_bar.addWidget(Qt.QLabel("samp_rate"+": "))self._samp_rate_combo_box = Qt.QComboBox()self._samp_rate_tool_bar.addWidget(self._samp_rate_combo_box)for label in self._samp_rate_labels: self._samp_rate_combo_box.addItem(label)self._samp_rate_callback = lambda i: Qt.QMetaObject.invokeMethod(self._samp_rate_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._samp_rate_options.index(i)))self._samp_rate_callback(self.samp_rate)self._samp_rate_combo_box.currentIndexChanged.connect(lambda i: self.set_samp_rate(self._samp_rate_options[i]))self.top_grid_layout.addWidget(self._samp_rate_tool_bar)self._rx_gain_range = Range(0, 1, 0.01, 0.75, 200)self._rx_gain_win = RangeWidget(self._rx_gain_range, self.set_rx_gain, "rx_gain", "counter_slider", float)self.top_grid_layout.addWidget(self._rx_gain_win)self._lo_offset_options = (0, 6e6, 11e6, )self._lo_offset_labels = (str(self._lo_offset_options[0]), str(self._lo_offset_options[1]), str(self._lo_offset_options[2]), )self._lo_offset_tool_bar = Qt.QToolBar(self)self._lo_offset_tool_bar.addWidget(Qt.QLabel("lo_offset"+": "))self._lo_offset_combo_box = Qt.QComboBox()self._lo_offset_tool_bar.addWidget(self._lo_offset_combo_box)for label in self._lo_offset_labels: self._lo_offset_combo_box.addItem(label)self._lo_offset_callback = lambda i: Qt.QMetaObject.invokeMethod(self._lo_offset_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._lo_offset_options.index(i)))self._lo_offset_callback(self.lo_offset)self._lo_offset_combo_box.currentIndexChanged.connect(lambda i: self.set_lo_offset(self._lo_offset_options[i]))self.top_grid_layout.addWidget(self._lo_offset_tool_bar)self._freq_options = [2412000000.0, 2417000000.0, 2422000000.0, 2427000000.0, 2432000000.0, 2437000000.0, 2442000000.0, 2447000000.0, 2452000000.0, 2457000000.0, 2462000000.0, 2467000000.0, 2472000000.0, 2484000000.0, 5170000000.0, 5180000000.0, 5190000000.0, 5200000000.0, 5210000000.0, 5220000000.0, 5230000000.0, 5240000000.0, 5250000000.0, 5260000000.0, 5270000000.0, 5280000000.0, 5290000000.0, 5300000000.0, 5310000000.0, 5320000000.0, 5500000000.0, 5510000000.0, 5520000000.0, 5530000000.0, 5540000000.0, 5550000000.0, 5560000000.0, 5570000000.0, 5580000000.0, 5590000000.0, 5600000000.0, 5610000000.0, 5620000000.0, 5630000000.0, 5640000000.0, 5660000000.0, 5670000000.0, 5680000000.0, 5690000000.0, 5700000000.0, 5710000000.0, 5720000000.0, 5745000000.0, 5755000000.0, 5765000000.0, 5775000000.0, 5785000000.0, 5795000000.0, 5805000000.0, 5825000000.0, 5860000000.0, 5870000000.0, 5880000000.0, 5890000000.0, 5900000000.0, 5910000000.0, 5920000000.0]self._freq_labels = ['  1 | 2412.0 | 11g', '  2 | 2417.0 | 11g', '  3 | 2422.0 | 11g', '  4 | 2427.0 | 11g', '  5 | 2432.0 | 11g', '  6 | 2437.0 | 11g', '  7 | 2442.0 | 11g', '  8 | 2447.0 | 11g', '  9 | 2452.0 | 11g', ' 10 | 2457.0 | 11g', ' 11 | 2462.0 | 11g', ' 12 | 2467.0 | 11g', ' 13 | 2472.0 | 11g', ' 14 | 2484.0 | 11g', ' 34 | 5170.0 | 11a', ' 36 | 5180.0 | 11a', ' 38 | 5190.0 | 11a', ' 40 | 5200.0 | 11a', ' 42 | 5210.0 | 11a', ' 44 | 5220.0 | 11a', ' 46 | 5230.0 | 11a', ' 48 | 5240.0 | 11a', ' 50 | 5250.0 | 11a', ' 52 | 5260.0 | 11a', ' 54 | 5270.0 | 11a', ' 56 | 5280.0 | 11a', ' 58 | 5290.0 | 11a', ' 60 | 5300.0 | 11a', ' 62 | 5310.0 | 11a', ' 64 | 5320.0 | 11a', '100 | 5500.0 | 11a', '102 | 5510.0 | 11a', '104 | 5520.0 | 11a', '106 | 5530.0 | 11a', '108 | 5540.0 | 11a', '110 | 5550.0 | 11a', '112 | 5560.0 | 11a', '114 | 5570.0 | 11a', '116 | 5580.0 | 11a', '118 | 5590.0 | 11a', '120 | 5600.0 | 11a', '122 | 5610.0 | 11a', '124 | 5620.0 | 11a', '126 | 5630.0 | 11a', '128 | 5640.0 | 11a', '132 | 5660.0 | 11a', '134 | 5670.0 | 11a', '136 | 5680.0 | 11a', '138 | 5690.0 | 11a', '140 | 5700.0 | 11a', '142 | 5710.0 | 11a', '144 | 5720.0 | 11a', '149 | 5745.0 | 11a (SRD)', '151 | 5755.0 | 11a (SRD)', '153 | 5765.0 | 11a (SRD)', '155 | 5775.0 | 11a (SRD)', '157 | 5785.0 | 11a (SRD)', '159 | 5795.0 | 11a (SRD)', '161 | 5805.0 | 11a (SRD)', '165 | 5825.0 | 11a (SRD)', '172 | 5860.0 | 11p', '174 | 5870.0 | 11p', '176 | 5880.0 | 11p', '178 | 5890.0 | 11p', '180 | 5900.0 | 11p', '182 | 5910.0 | 11p', '184 | 5920.0 | 11p']self._freq_tool_bar = Qt.QToolBar(self)self._freq_tool_bar.addWidget(Qt.QLabel("freq"+": "))self._freq_combo_box = Qt.QComboBox()self._freq_tool_bar.addWidget(self._freq_combo_box)for label in self._freq_labels: self._freq_combo_box.addItem(label)self._freq_callback = lambda i: Qt.QMetaObject.invokeMethod(self._freq_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._freq_options.index(i)))self._freq_callback(self.freq)self._freq_combo_box.currentIndexChanged.connect(lambda i: self.set_freq(self._freq_options[i]))self.top_grid_layout.addWidget(self._freq_tool_bar)self._encoding_options = [0, 1, 2, 3, 4, 5, 6, 7]self._encoding_labels = ["BPSK 1/2", "BPSK 3/4", "QPSK 1/2", "QPSK 3/4", "16QAM 1/2", "16QAM 3/4", "64QAM 2/3", "64QAM 3/4"]self._encoding_group_box = Qt.QGroupBox("encoding")self._encoding_box = Qt.QHBoxLayout()class variable_chooser_button_group(Qt.QButtonGroup):def __init__(self, parent=None):Qt.QButtonGroup.__init__(self, parent)@pyqtSlot(int)def updateButtonChecked(self, button_id):self.button(button_id).setChecked(True)self._encoding_button_group = variable_chooser_button_group()self._encoding_group_box.setLayout(self._encoding_box)for i, label in enumerate(self._encoding_labels):radio_button = Qt.QRadioButton(label)self._encoding_box.addWidget(radio_button)self._encoding_button_group.addButton(radio_button, i)self._encoding_callback = lambda i: Qt.QMetaObject.invokeMethod(self._encoding_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._encoding_options.index(i)))self._encoding_callback(self.encoding)self._encoding_button_group.buttonClicked[int].connect(lambda i: self.set_encoding(self._encoding_options[i]))self.top_grid_layout.addWidget(self._encoding_group_box)self._chan_est_options = [ieee802_11.LS, ieee802_11.LMS, ieee802_11.STA, ieee802_11.COMB]self._chan_est_labels = ["LS", "LMS", "STA", "Linear Comb"]self._chan_est_group_box = Qt.QGroupBox("chan_est")self._chan_est_box = Qt.QHBoxLayout()class variable_chooser_button_group(Qt.QButtonGroup):def __init__(self, parent=None):Qt.QButtonGroup.__init__(self, parent)@pyqtSlot(int)def updateButtonChecked(self, button_id):self.button(button_id).setChecked(True)self._chan_est_button_group = variable_chooser_button_group()self._chan_est_group_box.setLayout(self._chan_est_box)for i, label in enumerate(self._chan_est_labels):radio_button = Qt.QRadioButton(label)self._chan_est_box.addWidget(radio_button)self._chan_est_button_group.addButton(radio_button, i)self._chan_est_callback = lambda i: Qt.QMetaObject.invokeMethod(self._chan_est_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._chan_est_options.index(i)))self._chan_est_callback(self.chan_est)self._chan_est_button_group.buttonClicked[int].connect(lambda i: self.set_chan_est(self._chan_est_options[i]))self.top_grid_layout.addWidget(self._chan_est_group_box)self.wifi_phy_hier_0 = wifi_phy_hier(bandwidth=samp_rate,chan_est=chan_est,encoding=encoding,frequency=freq,sensitivity=0.56,)self.uhd_usrp_source_0 = uhd.usrp_source(",".join(('', "")),uhd.stream_args(cpu_format="fc32",channels=range(1),),)self.uhd_usrp_source_0.set_samp_rate(samp_rate)self.uhd_usrp_source_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(freq, rf_freq = freq - lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)self.uhd_usrp_source_0.set_normalized_gain(rx_gain, 0)#self.uhd_usrp_source_0.set_auto_dc_offset("", 0)#self.uhd_usrp_source_0.set_auto_iq_balance("", 0)self.uhd_usrp_sink_0 = uhd.usrp_sink(",".join(('', "")),uhd.stream_args(cpu_format="fc32",channels=range(1),),'packet_len',)self.uhd_usrp_sink_0.set_samp_rate(samp_rate)self.uhd_usrp_sink_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(freq, rf_freq = freq - lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)self.uhd_usrp_sink_0.set_normalized_gain(tx_gain, 0)self.qtgui_const_sink_x_0 = qtgui.const_sink_c(48*10, #size"", #name1 #number of inputs)self.qtgui_const_sink_x_0.set_update_time(0.10)self.qtgui_const_sink_x_0.set_y_axis(-2, 2)self.qtgui_const_sink_x_0.set_x_axis(-2, 2)self.qtgui_const_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "")self.qtgui_const_sink_x_0.enable_autoscale(False)self.qtgui_const_sink_x_0.enable_grid(False)self.qtgui_const_sink_x_0.enable_axis_labels(True)if not True:self.qtgui_const_sink_x_0.disable_legend()labels = ['', '', '', '', '','', '', '', '', '']widths = [1, 1, 1, 1, 1,1, 1, 1, 1, 1]colors = ["blue", "red", "red", "red", "red","red", "red", "red", "red", "red"]styles = [0, 0, 0, 0, 0,0, 0, 0, 0, 0]markers = [0, 0, 0, 0, 0,0, 0, 0, 0, 0]alphas = [1.0, 1.0, 1.0, 1.0, 1.0,1.0, 1.0, 1.0, 1.0, 1.0]for i in xrange(1):if len(labels[i]) == 0:self.qtgui_const_sink_x_0.set_line_label(i, "Data {0}".format(i))else:self.qtgui_const_sink_x_0.set_line_label(i, labels[i])self.qtgui_const_sink_x_0.set_line_width(i, widths[i])self.qtgui_const_sink_x_0.set_line_color(i, colors[i])self.qtgui_const_sink_x_0.set_line_style(i, styles[i])self.qtgui_const_sink_x_0.set_line_marker(i, markers[i])self.qtgui_const_sink_x_0.set_line_alpha(i, alphas[i])self._qtgui_const_sink_x_0_win = sip.wrapinstance(self.qtgui_const_sink_x_0.pyqwidget(), Qt.QWidget)self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_win)self.ieee802_11_parse_mac_0 = ieee802_11.parse_mac(False, True)self.ieee802_11_mac_0 = ieee802_11.mac(([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]), ([0x30, 0x14, 0x4a, 0xe6, 0x46, 0xe4]), ([0x42, 0x42, 0x42, 0x42, 0x42, 0x42]))self.ieee802_11_ether_encap_0 = ieee802_11.ether_encap(False)self.foo_wireshark_connector_0 = foo.wireshark_connector(127, False)self.foo_packet_pad2_0 = foo.packet_pad2(False, False, 0.001, 10000, 10000)(self.foo_packet_pad2_0).set_min_output_buffer(100000)self.blocks_tuntap_pdu_0 = blocks.tuntap_pdu('tap0', 440, False)self.blocks_pdu_to_tagged_stream_0_0 = blocks.pdu_to_tagged_stream(blocks.complex_t, 'packet_len')self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vcc((0.6, ))(self.blocks_multiply_const_vxx_0).set_min_output_buffer(100000)self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_char*1, '/tmp/wifi.pcap', True)self.blocks_file_sink_0.set_unbuffered(True)################################################### Connections##################################################self.msg_connect((self.blocks_tuntap_pdu_0, 'pdus'), (self.ieee802_11_ether_encap_0, 'from tap'))self.msg_connect((self.ieee802_11_ether_encap_0, 'to tap'), (self.blocks_tuntap_pdu_0, 'pdus'))self.msg_connect((self.ieee802_11_ether_encap_0, 'to wifi'), (self.ieee802_11_mac_0, 'app in'))self.msg_connect((self.ieee802_11_mac_0, 'phy out'), (self.wifi_phy_hier_0, 'mac_in'))self.msg_connect((self.wifi_phy_hier_0, 'carrier'), (self.blocks_pdu_to_tagged_stream_0_0, 'pdus'))self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.foo_wireshark_connector_0, 'in'))self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_ether_encap_0, 'from wifi'))self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_mac_0, 'phy in'))self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_parse_mac_0, 'in'))self.connect((self.blocks_multiply_const_vxx_0, 0), (self.foo_packet_pad2_0, 0))self.connect((self.blocks_pdu_to_tagged_stream_0_0, 0), (self.qtgui_const_sink_x_0, 0))self.connect((self.foo_packet_pad2_0, 0), (self.uhd_usrp_sink_0, 0))self.connect((self.foo_wireshark_connector_0, 0), (self.blocks_file_sink_0, 0))self.connect((self.uhd_usrp_source_0, 0), (self.wifi_phy_hier_0, 0))self.connect((self.wifi_phy_hier_0, 0), (self.blocks_multiply_const_vxx_0, 0))def closeEvent(self, event):self.settings = Qt.QSettings("GNU Radio", "wifi_transceiver")self.settings.setValue("geometry", self.saveGeometry())event.accept()def get_tx_gain(self):return self.tx_gaindef set_tx_gain(self, tx_gain):self.tx_gain = tx_gainself.uhd_usrp_sink_0.set_normalized_gain(self.tx_gain, 0)def get_samp_rate(self):return self.samp_ratedef set_samp_rate(self, samp_rate):self.samp_rate = samp_rateself._samp_rate_callback(self.samp_rate)self.wifi_phy_hier_0.set_bandwidth(self.samp_rate)self.uhd_usrp_source_0.set_samp_rate(self.samp_rate)self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate)def get_rx_gain(self):return self.rx_gaindef set_rx_gain(self, rx_gain):self.rx_gain = rx_gainself.uhd_usrp_source_0.set_normalized_gain(self.rx_gain, 0)def get_lo_offset(self):return self.lo_offsetdef set_lo_offset(self, lo_offset):self.lo_offset = lo_offsetself._lo_offset_callback(self.lo_offset)self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)def get_freq(self):return self.freqdef set_freq(self, freq):self.freq = freqself._freq_callback(self.freq)self.wifi_phy_hier_0.set_frequency(self.freq)self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)def get_encoding(self):return self.encodingdef set_encoding(self, encoding):self.encoding = encodingself._encoding_callback(self.encoding)self.wifi_phy_hier_0.set_encoding(self.encoding)def get_chan_est(self):return self.chan_estdef set_chan_est(self, chan_est):self.chan_est = chan_estself._chan_est_callback(self.chan_est)self.wifi_phy_hier_0.set_chan_est(self.chan_est)def main(top_block_cls=wifi_transceiver, options=None):from distutils.version import StrictVersionif StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):style = gr.prefs().get_string('qtgui', 'style', 'raster')Qt.QApplication.setGraphicsSystem(style)qapp = Qt.QApplication(sys.argv)tb = top_block_cls()tb.start()tb.show()def quitting():tb.stop()tb.wait()qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)qapp.exec_()if __name__ == '__main__':main()

最后电脑2运行:

sudo arp -s 192.168.123.2 30:14:4a:e6:46:e4

两个电脑运行的东西都差不多,主要是ip和mac不一样,另外wifi_transceiver里的dst和src的mac地址也要调换一下。


HackRF接收

如果你没有LimeSDR或者USRP这些昂贵的设备,你也可以用HackRF来接收WiFi数据包。

它的DC offset比较大,所以不能直接用wifi_rx.grc流图,而是要在osmocom source后面接一个FFT Filter实现的高通滤波器。如下图:

然后你保持采样率20MHz不变,耐心地切换各个中心频点,直到观察到类似上面的QAM图形或者2PSK图像就说明能解出数据包了。

这时回到gnuradio界面,左下角会有数据包里对应的Mac地址信息。

流图下载:

https://github.com/bastibl/gr-ieee802-11/files/6813359/wifi_rx_hackrf.zip

LimeSDR实验教程(5) WiFi解调相关推荐

  1. LimeSDR实验教程(15) Lattepanda + LimeSDR Mini转接板

    最近做portapack教程,感觉反响不错,Portapack的优点是可以脱离电脑使用,具有很高的便携性.同样的功能在portapack上运行比在电脑上运行感觉实用了不少,我早期也是被portapac ...

  2. LimeSDR实验教程(13) LTE基站、终端、核心网 (srsLTE nextepc)

    接下来我会讲一个大型应用,实现LTE基站和LTE终端.其实这个应用之前国内就有很多人做,但是一般都是使用OAI实现的,这个软件包虽然很全,但是安装很麻烦,而且很不稳定.我使用的是srsLTE实现的,它 ...

  3. LimeSDR实验教程(10) DVB-S发射和接收

    我在windows下实现了dvb-s的发射和接收. 发射使用的是limesdr-mini,接收使用的是hackrf/limesdr-usb. 这次和以前的dvb-t发射不同,这次的发射和接收都是用软件 ...

  4. LimeSDR实验教程(11) GFSK音频发射和接收

    gnuradio 3.7.13 下面的流图可以实现本地回环,可以听一下声音是不是录音文件里的,其中采样率必须等于wav文件实际采样率,要不然声音会有问题,可以查看wav的详细信息,观察采样率和通道数, ...

  5. 【嵌入式开发教程9】手把手教你做平板电脑-WIFI 驱动实验教程

    WIFI 驱动实验教程 --疯壳·嵌入式平板开发 第一节 电路原理图介绍 下图来源于文档 3128_sdk_a02_20170325.pdf 中第 16 页.   CMD 信号(用于传送命令和反应): ...

  6. 【CC3200AI 实验教程6】疯壳·AI语音人脸识别(会议记录仪/人脸打卡机)-串口

    CC3200AI实验教程 --疯壳·开发板系列 串口 串行接口分为异步串行接口和同步串行接口两种.异步串行接口统称为通用异步收发器(UART)接口,同步串行接口有SPI和I2C等,同步串行接口除了包含 ...

  7. 计算机控制实验教程,新)《计算机控制技术》实验教程.doc

    肇庆学院光机电一体化综合性实验教学示范中心实验教材之二十六 计算机控制技术 实 验 教 程 肇庆学院电子信息与机电工程学院 编 二00八年九月 内容简介 本书主要是基于清华大学出版社出版的由于海生先生 ...

  8. 数学实验matlab课后习题答案,matlab数学实验教程答案

    摘要: 数学实验如按工程组成来分单价分部分项,答案形式工程价的有(量清单报,在工中计价清单程量.项目题了质量问出现,数学实验造成了一定的损失,业主取的包括对此措施可噪.... 数学实验 教程工程价的量 ...

  9. ArcGIS实验教程——实验三十九:ArcGIS多元分类(ISO聚类分析、最大似然分类、主成分分析)案例教程

    ArcGIS实验视频教程合集:<ArcGIS实验教程从入门到精通>(附配套实验数据)> 文章目录 一.ISO聚类 1. ISO聚类简介 2. ISO聚类进行非监督分类实验操作 二.最 ...

  10. ArcGIS实验教程——实验三十八:基于ArcGIS的等高线、山体阴影、山顶点提取案例教程

    ArcGIS实验视频教程合集:<ArcGIS实验教程从入门到精通>(附配套实验数据)> 文章目录 1. 加载DEM 2. 提取等高距为15m的等高线 3. 提取等高距为75m的等高线 ...

最新文章

  1. 实战:CNN+BLSTM+CTC的验证码识别从训练到部署 | 技术头条
  2. 服务器性能优化的正确姿势
  3. linux下配置tomcat、resin
  4. js调用python脚本_javascript – 如何从NodeJs调用python脚本
  5. ArcGIS for Android 中MapView截图实现方法
  6. 好久没有写什么东西了。。。。
  7. 机器学习-分类算法-模型选择与调优09
  8. python汉诺塔_汉诺塔递归算法/搬金盘的婆罗门 - Python实现
  9. js日期函数表达天,时,分,秒
  10. 语音自训练平台技术详解,快速训练专属语音识别模型
  11. 微信公众号php从0开发,包括功能(自定义菜单,分享)
  12. java操作ElasticSearch(包含增删改查及基础语法操作)
  13. 汽车底盘线控与动力学域控制技术
  14. Debian安装和配置CA证书
  15. mysql 参照完整性规则_mysql数据的完整性约束(完整)
  16. 协成zookeeper
  17. Youtube字幕下载转SRT字幕
  18. No matter what,just do not give up。
  19. 【OpenCV】- 图像修复
  20. 合规性对区块链项目的重要性

热门文章

  1. html转word设置一二三级标题,word怎么设置一二三级标题
  2. w10怎样关闭对计算机更改,w10电脑定时关机怎么设置 让w10系统自动关闭的设置方法...
  3. 高中生物神经系统的组成,初中生物神经系统考题
  4. Android Switch禁止手动切换状态
  5. jquery实现登录成功界面_【jQuery实例】Ajax登录页面
  6. ps怎么抠地图线路_怎样在PS里画地图的边界线?
  7. 微信公众号主体如何变更:账号迁移全攻略
  8. android js 回调函数,Javascript回调函数传递给Android
  9. 物联网是什么,和互联网之间主要有什么区别
  10. AV1代码学习:av1_encode_strategy、denoise_and_encode、av1_encode函数