多载波调制与OFDM原理讲解以及MATLAB实现GUI设计

news2024/10/6 16:19:00

前言

基于MATLAB设计并实现了一个OFDM调制的图形用户界面(GUI)系统。该系统旨在简化OFDM调制过程的仿真,提供友好的用户交互界面。设计目标是通过GUI实现参数化的OFDM仿真,包括子载波数、符号数、IFFT长度、循环前缀长度、循环后缀长度和信噪比等参数的动态调节。系统支持多种调制方式(如QPSK、16QAM、64QAM、256QAM)和单径、多径信道模型,并实时显示OFDM信号的时域图和星座图。用户可通过GUI调整各项参数,启动或暂停仿真,观察误码率的变化。

多载波调制思想

在信道不理想的条件下,若采用单一正弦波作为载波实现调制,已调信号频带上很难保持理想传输特性,容易造成信号的严重失真和码间串扰。

多载波调制就是把数据流分解为若干个载波,因此,在多载波调制信道中,数据传输速率相对较低,码元周期较长,克服了单载波调制方式码元持续时间Ts短,占用带宽B大,信号特性\left | C(f) \right |不理想,易产生码间串扰等缺点。只要时延扩展与码元周期相比小于一定的值,就不会产生码间串扰,因而多载波调制对于信道的时间弥散性不敏感,具有较强的抗多径传播和抗频率选择性衰落的能力以及较高的频谱利用率。

OFDM可以抵抗多径干扰,是当前研究的一个热点。在4G移动通信等高速无线通信系统中得到了广泛的应用。

OFDM原理

OFDM时域图绘制 

一个OFDM系统中有N个子信道,每个子信道采用的子载波为

x_{k}(t)= B_{k}cos(2\pi f_{k}t+\varphi_{k})

其中B_{k}是第k路子载波的振幅,它受基带码元的调制,f_{k}为第k路子载波的频率,\varphi_{k}为第k路子载波的初始相位,则在此系统中的N路自信号之和可以表示为

 e(t)=\sum_{k=0}^{N-1}x_{k}(t)= \sum_{k=0}^{N-1}B_{k}cos(2\pi f_{k}t+\varphi_{k})

复数形式为

e(t)= \sum_{k=0}^{N-1}B_{k} e^{j(2\pi f_{k}t+\varphi_{k})} 

代码在下面频域部分一起给出。 

这一步没什么难的,就是根据公式s(k) =\sum_{i=0}^{N-1} \exp(j2\pi \frac{ik}{N})实现。

OFDM频域图绘制

在我查过资料之后,大家基本上都是直接使用sinc绘制的。比如这下面的是来源于知乎的一篇代码生成的。

NoOfCarriers = 11;              % 设定载波的数量(需要保证是奇数)
iMin = -(NoOfCarriers-1)/2;     % 最小的子载波的索引
iMax = (NoOfCarriers-1)/2;      % 最大的子载波的索引
f = -10:0.01:10;                % 设定频率是从-10MHz到10MHz
fList = zeros(1,NoOfCarriers);  % 频率列表,用来存储各sinc函数的中心频率
cList = zeros(1,NoOfCarriers);  % 幅值列表,用来存储各sinc函数的幅值
%************************** 画出各OFDM子载波的频域图 **************************%
for i=iMin:1:iMax
    % 计算出每一个OFDM子载波的sinc函数
    fshift = i ;
    c = sinc(f - fshift);
    fList(i+NoOfCarriers) =  fshift;
    cList(i+NoOfCarriers) = max(c);
    plot(f,c,'linewidth',1.5);
    hold on;
    stem(i ,1,'r-','linewidth',1.5);
end
xlabel("频率 MHz");
grid();
hold off;

那么为什么是sinc呢?实际上OFDM信号不可能是无限长的,而有限长的OFDM信号实际可以看做与矩形窗函数的乘积,矩形窗函数可以定义如下:

g(t) = \left\{\begin{matrix} 1 , 0<\left | t \right |<T\\ 0, \left | t \right |>T \end{matrix}\right.

对其进行傅里叶变换:

G(jw)=\frac{sin(\frac{wT}{2})}{\frac{w}{2}}

由于时域相乘等效于频域卷积,因此OFDM信号反映到频谱,就成为各个不同位置的冲击响应与sinc函数的卷积。

这里我们来看看怎么对时域波形做fft变换。

% ======================== 绘制时域波形图 =======================
Fs = 1000;                               % 总的采样率
N = 1024;                                % 总的子载波数
T = N / Fs;                              % 信号绘制为一个周期的长度
x = 0 : 1/Fs : T-1/Fs;                   % 生成时间向量,用于绘制波形
Numscr = 4;                              % 绘制的子载波数量
s_data = 1;                              % 初始相位
y = zeros(Numscr, numel(x));             % 初始化存储每个子载波的复数值的矩阵
ini_phase = ones(1, numel(x));           % 生成与时间长度相匹配的初始相位向量

% 生成所有子载波的时域波形
for k = 0 : Numscr-1                     % 循环遍历要绘制的子载波数量
    y(k+1, :) = ini_phase .* exp(1i * 2 * pi * k * (0:numel(x)-1) / N); % 计算每个时间点上每个子载波的复数值
end

% 绘制时域波形
figure(1);
plot(x, real(y));     
xlabel('时间/s');                
ylabel('幅度/V');               
title('多路子载波的时域波形');       
grid on; 


% ======================== 绘制频域波形图 =======================
a = 20;                                  % 扩展系数
total_length = (a + 1) * N;
delta_f = Fs / total_length;
f = (-Fs / 2) : delta_f : (Fs / 2 - delta_f);
y1 = zeros(Numscr, a * N);
y_combined = horzcat(y, y1); 
y_fft = zeros(Numscr, (a+1)*N);
for k = 1 : Numscr
    y_fft(k, :) = real(fftshift(fft(y_combined(k,:)))) / N;  % 计算每个子载波的频谱
end

figure(2);
plot(f, y_fft(1,:), f, y_fft(2,:), f, y_fft(3,:), f, y_fft(4,:));
grid on;
xlim([-10, 10]);
xlabel('频率/Hz');
ylabel('幅度/V');
title('多路子载波的频域波形'); 

a为扩展系数,设置为20,用于增加频谱的分辨率。扩展后的信号长度为 (a + 1) 倍的 N,这样就能扩展频谱分辨率,扩展后的频谱分辨率显著提高,频率间隔变得更小,频谱图更加细腻和平滑。

验证IDFT实现OFDM和模拟调制实现是否完全等效

假设OFDM系统包含了8个子载波,载波频率为1kHz,子载波频率间隔为1kHz,每个子载波采用4QAM调制,符号周期为1ms,试比较OFDM的模拟调制实现与IDFT/DFT实现。

% 参数设置
N = 8;                      % 子载波数
x = randi([0, 3], 1, N);    % 随机生成子载波上的数据
x1 = qammod(x, 4);          % 采用4-QAM调制
f = 1:N;                    % 子载波频率
t = 0:0.001:1-0.001;        % 符号持续时间

% 模拟调制实现
w = 2*pi*f.'*t;             % 子载波频率矩阵
y1 = x1 * exp(1i * w);      % 模拟调制实现

% IDFT实现
x2 = ifft(x1, N);           % 计算逆离散傅里叶变换
x2_time = (0:N-1)/N;        % IDFT时间轴

% 绘制波形比较
figure;
plot(t, abs(y1));           % 绘制模拟调制实现的时域波形
hold on;
stem(x2_time, abs(x2) * N, '-r'); % 绘制IDFT实现的时域波形
legend('模拟调制实现','IDFT实现');
title('模拟调制实现与IDFT比较');
xlabel('时间 (s)');
ylabel('幅度');

% 验证IDFT和FFT的关系
x3 = fft(x2, N);            % 计算快速傅里叶变换

disp(x1);
disp(x3);

升余弦窗处理

为了减少旁瓣干扰,提高系统的抗干扰性能,对添加了循环前缀和循环后缀的信号进行升余弦窗处理。升余弦窗处理通过调整信号的幅度,减少频域中的旁瓣,从而降低干扰。升余弦窗的系数计算使用了sin函数,目的是在窗函数的边界部分创建一个平滑的过渡。

窗口长度T由窗口的总长度bitLength和滚降系数\alpha决定:

T=\frac{bitLength}{2(1+\alpha )}

然后,计算窗口系数window(t)其中 t 是从 1 到 \frac{bitLength}{2}的向量:

window(t)=\frac{1}{2}(1-sin(\frac{\pi}{2\alpha T}\ast T))

这个公式通过sin函数在窗口的边界部分创建一个平滑的过渡,以减少频谱中的旁瓣干扰。注意这里的计算方式与标准升余弦窗的公式不同,更类似于汉宁窗(Hann window)的计算方式。对于(1-\alpha )范围内的T窗口系数设置为1,表示在窗口的平坦部分,信号保持不变:

window(1:(1-\alpha )\ast T)

最后,将窗口反转并拼接,生成完整的升余弦窗。通过升余弦窗处理,可以有效地减少频谱中的旁瓣干扰,从而提高信号的传输质量。使用sin函数是为了在窗口的边界部分创建一个平滑的过渡,以减少干扰。尽管这里与标准升余弦窗有所不同,但其基本思想是相同的,即通过平滑过渡减少频谱旁瓣干扰。

function window = rcoswindow(alpha, bit_length)
    warning off;
    window = zeros(1, bit_length / 2);
    t = 1:bit_length / 2;
    T = bit_length / (2 * (1 + alpha));
    window(t) = 0.5 * (1 - sin(pi / (2 * alpha * T) * (t - T)));
    window(1:(1 - alpha) * T) = 1;
    window = [fliplr(window) window]';
end

OFDM实现

clear all;
close all;

% OFDM仿真参数
carrier_count = 200;    % 子载波数
symbol_count = 100;     % 总符号数
ifft_length = 512;      % IFFT长度
CP_length = 128;        % 循环前缀长度
CS_length = 20;         % 循环后缀长度
alpha = 7/32;           % 升余弦窗系数
SNR = 20;               % 信噪比
rate = [];

% 选择调制方式:'QPSK'、'16QAM'、'64QAM'、'256QAM'
modulation_type = 'QPSK'; % 可以修改为 'QPSK', '64QAM', '256QAM'

switch modulation_type
    case 'QPSK'
        M = 4;
    case '16QAM'
        M = 16;
    case '64QAM'
        M = 64;
    case '256QAM'
        M = 256;
    otherwise
        error('Unsupported modulation type');
end

bit_per_symbol = log2(M);
bit_length = carrier_count * symbol_count * bit_per_symbol;

bit_sequence = randi([0, 1], bit_length, 1); 

% 绘制生成随机二进制序列
figure(1);
bar(bit_sequence(1:50), 'b');
xlabel('Bit Index');
ylabel('Bit Value');
title('Binary Source Code Distribution');
grid on;

% ================子载波调制方式========================
bit_moded = qammod(bit_sequence, M, 'InputType', 'bit', 'UnitAveragePower', true);
figure('position', [0 0 400 400]);
scatter(real(bit_moded), imag(bit_moded));
title(['调制后的散点图 - ', modulation_type]);
grid on;
% ===================IFFT===========================
% =================串并转换==========================
ifft_position = zeros(ifft_length, symbol_count);
bit_moded = reshape(bit_moded, carrier_count, []);
figure('position', [400 0 400 400]);
stem(abs(bit_moded(:, 1)));
grid on;

% 1-28置零 29-228有效 229-285置零 286-485共轭 486-512置零
carrier_position = 29:228;
conj_position = 485:-1:286;
ifft_position(carrier_position, :) = bit_moded;
ifft_position(conj_position, :) = conj(bit_moded);
signal_time = ifft(ifft_position, ifft_length);   % 512   100
figure('position', [0 400 400 400]);
subplot(3,1,1);
plot(signal_time(:, 1), 'b');
title('原始单个OFDM符号');
xlabel('Time');
ylabel('Amplitude');

% ==================加循环前缀和后缀==================
signal_time_C = [signal_time(end-CP_length+1:end, :); signal_time];
signal_time_C = [signal_time_C; signal_time_C(1:CS_length, :)];
subplot(3,1,2); % 单个完整符号为512+128+20=660
plot(signal_time_C(:, 1));
xlabel('Time');
ylabel('Amplitude');
title('加CP和CS的单个OFDM符号');

% =======================加窗========================
signal_window = signal_time_C .* repmat(rcoswindow(alpha, size(signal_time_C, 1)), 1, symbol_count);
subplot(3,1,3);
plot(signal_window(:, 1));
title('加窗后的单个OFDM符号');
xlabel('Time');
ylabel('Amplitude');
% ===================发送信号,多径信道====================
signal_Tx = reshape(signal_window, 1, []); % 时域完整信号
signal_origin = reshape(signal_time_C, 1, []); % 未加窗完整信号
mult_path_am = [1 0.2 0.1]; % 多径幅度
mutt_path_time = [0 20 50]; % 多径时延
path2 = 0.2 * [zeros(1, 20) signal_Tx(1:end-20)];
path3 = 0.1 * [zeros(1, 50) signal_Tx(1:end-50)];
signal_Tx_mult = signal_Tx + path2 + path3; % 多径信号

figure(5);
subplot(2,1,1);
plot(signal_Tx_mult);
title('多径下OFDM信号');
xlabel('Time/samples');
ylabel('Amplitude');
subplot(2,1,2);
plot(signal_Tx);
title('单径下OFDM信号');
xlabel('Time/samples');
ylabel('Amplitude');

% =====================发送信号频谱========================
% ====================未加窗信号频谱=======================
% 每个符号求频谱再平均,功率取对数
figure(6);
orgin_aver_power = 20 * log10(mean(abs(fft(signal_time_C'))));
subplot(2,1,1);
plot((1:length(orgin_aver_power)) / length(orgin_aver_power), orgin_aver_power);
hold on;
plot(0:1/length(orgin_aver_power):1, -35, 'rd');
hold off;
axis([0 1 -40 max(orgin_aver_power)]);
grid on;
title('未加窗信号频谱');
% ====================加窗信号频谱=========================
orgin_aver_power = 20 * log10(mean(abs(fft(signal_window'))));
subplot(2,1,2);
plot((1:length(orgin_aver_power)) / length(orgin_aver_power), orgin_aver_power);
hold on;
plot(0:1/length(orgin_aver_power):1, -35, 'rd');
hold off;
axis([0 1 -40 max(orgin_aver_power)]);
grid on;
title('加窗信号频谱');

% ========================加AWGN==========================
Rx_data_sig = awgn(signal_Tx, SNR, 'measured'); % 向单径信号添加噪声
Rx_data_mut = awgn(signal_Tx_mult, SNR, 'measured'); % 向多径信号添加噪声

% =======================串并转换==========================
Rx_data_mut = reshape(Rx_data_mut, ifft_length + CS_length + CP_length, []);
Rx_data_sig = reshape(Rx_data_sig, ifft_length + CS_length + CP_length, []);

% ====================去循环前缀和后缀======================
Rx_data_sig(1:CP_length, :) = [];
Rx_data_sig(end-CS_length+1:end, :) = [];
Rx_data_mut(1:CP_length, :) = [];
Rx_data_mut(end-CS_length+1:end, :) = [];

% FFT
fft_sig = fft(Rx_data_sig);
fft_mut = fft(Rx_data_mut);

% 降采样
data_sig = fft_sig(carrier_position, :);
data_mut = fft_mut(carrier_position, :);

figure;
scatter(real(reshape(data_sig, 1, [])), imag(reshape(data_sig, 1, [])), '.');
grid on;
title('单径下接收信号星座图');

figure;
scatter(real(reshape(data_mut, 1, [])), imag(reshape(data_mut, 1, [])), '.');
grid on;
title('多径下接收信号星座图');

% =========================逆映射===========================
bit_demod_sig = reshape(qamdemod(data_sig, M, 'OutputType', 'bit'), [], 1);
bit_demod_mut = reshape(qamdemod(data_mut, M, 'OutputType', 'bit'), [], 1);

% =========================误码率===========================
error_bit_sig = sum(bit_demod_sig ~= bit_sequence);
error_bit_mut = sum(bit_demod_mut ~= bit_sequence);
error_rate_sig = error_bit_sig / bit_length;
error_rate_mut = error_bit_mut / bit_length;
rate = [rate; error_rate_sig error_rate_mut];

% 打印误码率
fprintf('单径误码率: %f\n', error_rate_sig);
fprintf('多径误码率: %f\n', error_rate_mut);

生成的波形如下所示: 

图1 

图1上展示了一个原始单个OFDM符号的时域波形。该图像显示了OFDM符号在时域上的分布情况,未添加任何前缀或后缀。图1中展示了添加循环前缀(CP)和循环后缀(CS)后的单个OFDM符号。循环前缀和后缀有助于克服信道中的多径效应,并改善信号的接收性能。图1下展示了加窗后的单个OFDM符号。升余弦窗的应用使信号在边缘处更加平滑,从而减少频谱泄漏和旁瓣干扰。 

图2 单径与多径下OFDM信号

图2展示了单径和多径情况下的OFDM信号。多径效应引入了信号的时延和幅度变化,导致信号波形在多径情况下更加复杂。这部分仿真展示了信号在不同传输环境下的变化。

图3 加窗子与未加窗信号频谱图对比

图3展示了加窗和未加窗信号的频谱对比。通过比较可以看到,加窗后的信号频谱在边缘部分有显著的改善,表明升余弦窗在减少频谱泄漏方面的有效性。

图4 单径与多径下接受信号星座图

图4展示了单径和多径情况下的接收信号星座图。在单径情况下,接收的星座点较为集中,表示信号失真较小;而在多径情况下,由于多径效应的影响,星座点出现了明显的散布,显示出信号在复杂信道环境下的失真程度。

用户界面设计

界面整体设计采用两栏式设计,左侧为参数设置模块,右侧为结果显示模块。

左侧的参数设置模块提供了多个输入控件,用户可以在这里设置信噪比(SNR)、子载波数、符号数、IFFT长度、循环前缀长度、循环后缀长度以及调制方式等参数。这些控件包括文本框、下拉菜单和旋钮,用户可以通过这些控件输入或选择相应的数值和选项,以便精确地控制OFDM系统的仿真环境。在参数设置模块,还设计了开始仿真、暂停(恢复)仿真和结束仿真的按钮。用户点击“开始仿真”按钮后,系统会根据设置的参数启动仿真过程。在仿真进行中,用户可以通过“暂停”按钮暂时中止仿真,通过“恢复”按钮继续仿真,而点击“结束仿真”按钮则可以完全停止当前的仿真过程。

右侧的结果显示模块主要用于展示OFDM信号的时域波形和接收信号的星座图。在仿真过程中,系统会实时更新结果显示模块的内容,以便用户可以直观地观察OFDM信号的变化和传输效果。通过时域波形图,用户可以看到经过IFFT变换后的信号时域表现;通过星座图,用户可以分析接收信号的解调效果和误码情况。此外,结果显示模块还会实时显示系统的误码率,帮助用户评估不同参数设置下系统的性能。

动态演示

项目资源

你可以通过github下载整个项目资源。包括程序版本与独立桌面版本。

Auorui/Design-of-OFDM-GUI: 基于matlab的OFDM GUI设计 (github.com)

由于为了方便,误码率的计算是通过每次勾选复选框进行计算的。它并不是实时的,在多径上面误码率较大。 

参考文章

nayakanuj/playingWithOFDM(github.com)

OFDM基本原理_ofdm信号-CSDN博客

OFDM通信系统的MATLAB仿真(2) - 羽扇纶巾o0 - 博客园 (cnblogs.com)

OFDM调制matlab仿真详细代码_ofdm matlab-CSDN博客

如何画OFDM频谱图-CSDN博客

OFDM系统仿真【matlab代码】-CSDN博客

无线通信基础2:深入理解OFDM(含Matlab代码) - 知乎 (zhihu.com)

【现代数字传输】OFDM的原理讲解和MATLAB实现_ofdm matlab-CSDN博客

OFDM学习--第二节 用Matlab仿真基本的链路_哔哩哔哩_bilibili

给“小白”图示讲解OFDM的原理(受益匪浅,OFDM小白强推)_直观图解ofdm原理-CSDN博客

OFDM系统仿真【matlab源码】_ofdmmatlab仿真代码-CSDN博客

OFDM完整仿真过程及解释(MATLAB) - 简书 (jianshu.com)

OFDM原理及MATLAB仿真-CSDN博客

OFDM演示GUI_哔哩哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1891424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 换肤之插件换肤

文章目录 Android 换肤之插件换肤概述效果使用步骤代码结构原理 代码下载 Android 换肤之插件换肤 概述 Android 实现应用内换肤的常用方式&#xff08;两种&#xff09;&#xff1a; 通过Theme切换主题&#xff0c;即静态方法。通过AssetManager切换主题&#xff0c;可实现…

单元测试总结,一文全通

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、何为单测 测试有黑盒测试和白盒测试之分&#xff0c;黑盒测试顾名思义就是我们不了解盒子的…

数据泄露时代的安全之道:访问认证的重要性

引言 想象一下&#xff1a;你一觉醒来&#xff0c;收到一条通知——你的公司遭遇了数据泄露。你感到恐惧&#xff0c;因为这意味着客户数据被曝光&#xff0c;公司声誉受损&#xff0c;还有巨额罚款在等着你。在当今的数字化环境中&#xff0c;这种情况太常见了。全球各地的组…

ansible执行任务时,报错/usr/bin/env node没有文件或目录。

报错如图&#xff1a; 解决&#xff1a;添加软链即可 sudo ln -s /home/app/node-v18.20.3/bin/node /usr/bin/node

Qt开发 | qss简介与应用

文章目录 一、qss简介与应用二、QLineEdit qss介绍与使用三、QPushButton qss1.常用qss1.1 基本样式表1.2 背景图片1.3 图片在左文字在右 2.点击按钮弹出菜单以及右侧箭头样式设置3.鼠标悬浮按钮弹出对话框 四、QCheckBox qss妙用&#xff1a;实时打开关闭状态按钮五、QComboBo…

0-FreeCAD简介

这里写自定义目录标题 FreeCAD简介FreeCAD简介 FreeCAD是一款开源的三维计算机辅助设计(CAD)软件,它主要用于产品设计和工程制图。这款软件可以创建和修改3D模型,支持参数化设计,意味着你可以通过改变模型的参数来调整模型的大小、形状等属性。FreeCAD还支持多种3D文件格式…

【C语言】enum 关键字

在C语言中&#xff0c;enum关键字用于定义枚举类型。枚举是一种用户自定义的数据类型&#xff0c;由一组命名的整型常量构成。使用枚举可以提高代码的可读性和可维护性&#xff0c;特别是在表示一组相关的常量时。 定义和使用枚举类型 基本定义 要定义一个枚举类型&#xff…

党建科普3D数字化展馆支持实时更新迭代

3D虚拟策展逐渐成为新时代下的主流方式&#xff0c;深圳华锐视点作为专业的web3d开发公司&#xff0c;具有专业化的3D数字化空间还原能力&#xff0c;能根据企业/个人不同需求和预算&#xff0c;为您打造纯线上虚拟3D艺术展&#xff0c;让您彻底摆脱实体美术馆的限制&#xff0…

使用Ckman部署ClickHouse集群介绍

使用Ckman部署ClickHouse集群介绍 1. Ckman简介 ClickHouse Manager是一个为ClickHouse数据库量身定制的管理工具&#xff0c;它是由擎创科技数据库团队主导研发的一款用来管理和监控ClickHouse集群的可视化运维工具。目前该工具已在github上开源&#xff0c;开源地址为&…

【基于R语言群体遗传学】-4-统计建模与算法(statistical tests and algorithm)

之前的三篇博客&#xff0c;我们对于哈代温伯格遗传比例有了一个全面的认识&#xff0c;没有看的朋友可以先看一下前面的博客&#xff1a; 群体遗传学_tRNA做科研的博客-CSDN博客 1.一些新名词 &#xff08;1&#xff09;Algorithm: A series of operations executed in a s…

uni-app上传失败超出文件限制解决方法-分包处理-预加载

分包背景 当你的上传出现一下错误&#xff1a; Error: 系统错误&#xff0c;错误码&#xff1a;80051,source size 2089KB exceed max limit 2MB [20240703 10:53:06][wxbf93dfb6cb3eb8af] [1.06.2405010][win32-x64] 说明你主包太大需要处理了&#xff0c;一下两种方法可以…

51单片机嵌入式开发:STC89C52操作8八段式数码管原理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 STC89C52操作8八段式数码管原理 1 8位数码管介绍1.1 8位数码管概述1.2 8位数码管原理1.3 应用场景 2 原理图图解2.1 74HC573原理2.2 74HC138原理2.3 数码管原理 3 数码管程序…

QT_GUI

1、QT安装 一个跨平台的应用程序和用户界面框架&#xff0c;用于开发图形用户界面&#xff08;GUI&#xff09;应用程序以及命令行工具。QT有商业版额免费开源版&#xff0c;一般使用免费开源版即可&#xff0c;下面安装的是QT5&#xff0c;因为出来较早&#xff0c;使用较多&…

【前端CSS3】CSS引入方式总结(黑马程序员)

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、CSS引入方式&#xff1a;☀️☀️☀️2.1 内部样式表2.2 行内样式表 三、总结&#x1f680;&#x1f680;&#x1f680; 一、前言&#x1f680;&#x1f680;&#x1f680; ☀️ 回报不在行动之后&#xff0c;回报…

ETL数据集成丨使用ETLCloud实现MySQL与Greenplum数据同步

我们在进行数据集成时&#xff0c;MySQL和Greenplum是比较常见的两个数据库&#xff0c;我们可以通过ETLCloud数据集成平台&#xff0c;可以快速实现MySQL数据库与数仓数据库&#xff08;Greenplum&#xff09;的数据同步。 MySQL数据库&#xff1a; 优点&#xff1a; 轻量级…

Java实现电子围栏的小例子

主要需求是实现一个电子围栏判断的小例子其中包括前端和后端的demo代码 public class GeoFenceUtils {/** geometryFactory */private static final GeometryFactory geometryFactory new GeometryFactory();/*** 判断指定的GPS点是否在电子围栏内** param fencePointsList 包…

上海小程序开发需要进行定制开发吗?

随着互联网技术与移动设备的不断成熟&#xff0c;小程序也已普及到人们日常生活的方方面面。随着企业与互联网联结的愈发深入&#xff0c;小程序的开发可以为企业带来更高效的经营模式&#xff0c;降本增效。那么&#xff0c;上海小程序作为无需安装且开发门槛较低的应用&#…

udp发送数据如果超过1个mtu时,抓包所遇到的问题记录说明

最近在测试Syslog udp发送相关功能&#xff0c;测试环境是centos udp头部的数据长度是2个字节&#xff0c;最大传输长度理论上是65535&#xff0c;除去头部这些字节&#xff0c;可以大概的说是64k。 写了一个超过64k的数据(随便用了一个7w字节的buffer)发送demo&#xff0c;打…

Three.js机器人与星系动态场景(二):强化三维空间认识

在上篇博客中介绍了如何快速利用react搭建three.js平台&#xff0c;并实现3D模型的可视化。本文将在上一篇的基础上强化坐标系的概念。引入AxesHelper辅助工具&#xff0c;带你快速理解camer、坐标原点、可视区域。 Three.js机器人与星系动态场景&#xff1a;实现3D渲染与交互式…

AMEYA360代理:海凌科60G客流量统计雷达模块 4T4R出入口绊数计数

数字化时代&#xff0c;不管是大型商城还是各种连锁店&#xff0c;客流统计分析都可以帮助企业更加精准地了解顾客需求和消费行为。 海凌科推出一款专用于客流量统计的60G雷达模块&#xff0c;4T4R&#xff0c;可以实时进行固定范围内的人体运动轨迹检测&#xff0c;根据人体的…