当前位置: 首页 > news >正文

_FYAW智能显示控制仪表的简单使用_串口通信

一、简介

        该仪表可以实时显示位移传感器的测量值,并可设定阈值等。先谈谈简单的使用方法,通过说明书,我们可以知道长按SET键可以进入参数选择状态,按“↑”“↓”可以选择该组参数的上一个或者下一个参数。

        从参数一览中可以看到有不同组的参数,当我们第一次进入参数选择状态时会进入第一组参数,可以设置不同的阈值。只不过由于是数码管,显示字母时会用一些比较奇怪的表达,比如“5”其实就是“S”,可以通过对照参数表,获取不同字母的显示。

        如果想进入其他组参数,可以在第一组参数中,通过“↑”或“↓”找到最后一个oA,然后按“←”开始设置参数,当把4位数码管都设为1,即输入密码1111后,再按下SET确定,就可以解锁密码了。此时可以通过长按SET键切换到其他组参数。

        更多功能可自行查看数据手册,不过要注意的是说明书中的参数并非全部与实际仪器一一对应,实际仪器有时会缺少一两个参数。

二、串口使用

        串口使用的是RS485电平或者RS232,千万要注意的就是A、B的接线,不要接错。这个一般需要按照说明书的来,说明书上说“7”对应的是“B”,“8”对应的是“A”,如果仪器上贴着的标签是相反的,那么可以先按照说明书上的接法,如果不行再按照仪器上的,不要忘记接地

        接下来说说具体的串口通信,仪器默认波特率是9600,通信协议是Modbus-RTU。这里推荐使用Modbus-RTU协议。

        这个通信过程并非是仪表主动不断地发送测量数据给上位机,而是需要你先发送相应命令给仪器,然后接收仪器数据。使用过程中倒是发现一些与说明书不同吻合的地方,比如读取测量值这一步,按理来说应答应如下,但实际过程中接收的是“01 04 04 42 47 3F 3F 3F 28”,即多了一个04

        不过当我们需要连续读取时就会发现单次发送实在是麻烦,现在可以有下面几种方法连续发下

1,使用llcom

        这个串口助手可以写lua脚本,以实现自动发送数据,并读取数据保存

chenxuuu/llcom: 🛠功能强大的串口工具。支持Lua自动化处理、串口调试、WinUSB、串口曲线、TCP测试、MQTT测试、编码转换、乱码恢复等功能 (github.com)

下面是可以发送命令并把读取数据保存起来的lua脚本。只不过lua脚本很难运行什么GUI,自然就无法显示图表

-- 发送数据中间间隔时间(单位ms)
local sendDelay = 100-- 生成16进制数据“01 04 0000 0002 71CB”
local usartData = "01040000000271CB"
usartData=usartData:fromHex()-- 获取当前日期和时间
local function get_current_datetime()local datetime = os.date("%Y%m%d_%H%M%S")return datetime
end-- 生成带有日期和时间的文件名
local function generate_filename()local datetime = get_current_datetime()return "D:/Script/python/expr_com/data_log/log_" .. datetime .. ".txt"
end-- 打开文件,如果文件不存在则创建,如果存在则覆盖
local filePath = generate_filename()
local file, err = io.open(filePath, "w")
if not file then-- 如果文件打开失败,输出错误信息print("无法打开文件: " .. err)
elseprint("文件成功打开: " .. filePath)
endlocal value_str = ""-- 发送数据的函数
apiSetCb("uart", function(data)-- 写入数据value_str = data:toHex():sub(7, 14)file:write(value_str .. "\n")  -- 添加换行符以便区分不同数据print(value_str)
end)-- 循环发送任务
sys.taskInit(function()while true do-- 发送数据apiSendUartData(usartData)sys.wait(sendDelay)end
end)-- 确保在脚本结束时关闭文件
--[[
atexit(function()if file thenfile:close()print("文件已关闭")end
end)
]]

2,使用Python脚本

        使用Python脚本直接打开串口,然后发送命令并读取数据,需要注意的是下面脚本里指定了一个串口,你需要打开设备管理器来找到实际串口并修改脚本里的串口为实际串口号。同时注意波特率设置。

        由于仪器发送的其实是浮点数据的实际表达,所以下面脚本就自动做了这个转换

        可惜的是,使用Python后,无法很好地实时更新数据到图表中,下面也就没有添加这个功能。

import serial
import struct
import time
import os
from datetime import datetime# 配置串口
ser = serial.Serial(port='COM7',  # 根据实际情况修改端口号baudrate=115200,  # 波特率timeout=1  # 超时设置
)# 要发送的16进制数据
send_data = bytes.fromhex('01040000000271CB')# 确保 data_log 目录存在
log_dir = 'data_log'
os.makedirs(log_dir, exist_ok=True)# 获取当前日期和时间
current_time = datetime.now().strftime('%Y%m%d_%H%M%S')
log_file_path = os.path.join(log_dir, f"log_{current_time}.csv")# 打开日志文件
with open(log_file_path, 'w') as log_file:log_file.write("Timestamp,Value\n")  # 写入表头try:while True:# 发送16进制数据ser.write(send_data)# 从串口读取9字节的数据,并提取中间的5-8位16进制数据data = ser.read(9)[3:7]# 将16进制数据转换为32位浮点数try:float_data = struct.unpack('>f', data)[0]  # '>f' 表示大端模式print(f"data: {float_data}")  # 打印浮点数# 获取当前时间戳timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')# 写入日志文件log_file.write(f"{timestamp},{float_data}\n")log_file.flush()  # 立即写入文件except struct.error as e:print(f"Error unpacking data: {e}")# 每100毫秒(即每秒10次)更新一次time.sleep(0.1)except KeyboardInterrupt:print("Program terminated by user")finally:# 关闭串口ser.close()

 CRC校验计算

        补充一点,为了可以使用其他命令,需要计算16位CRC校验值。比如下面可以数据手册上的读取测量值命令的CRC校验值“01 04 0000 0002 71CB”,其中71CB是16位校验值,在下面脚本中输入前面命令“01 04 0000 0002”即可

import crcmoddef calculate_crc16(data):# 创建一个CRC16校验对象crc16_func = crcmod.mkCrcFun(0x18005, initCrc=0xFFFF, rev=True, xorOut=0x0000)# 将16进制字符串转换为字节byte_data = bytes.fromhex(data)# 计算CRC16校验码crc_value = crc16_func(byte_data)# 交换高低字节crc_value = ((crc_value & 0xFF) << 8) | ((crc_value & 0xFF00) >> 8)return crc_value# 输入的16进制内容
hex_data = "01 04 0000 0002"# 去除空格并计算CRC16
hex_data_no_spaces = hex_data.replace(" ", "")
crc16_result = calculate_crc16(hex_data_no_spaces)# 打印结果
print(f"CRC16:{crc16_result:04X}")

 8位16进制字符串转为32位浮点数据

def hex_to_float(hex_str):# 将 16 进制字符串转换为 32 位无符号整数uint_value = int(hex_str, 16)# 将 32 位无符号整数转换为浮点数float_value = struct.unpack('!f', struct.pack('!I', uint_value))[0]return float_value

 3,使用WPF

        就功能而言,这个方法我是最满意的,可以自己定制化写一个专用的串口助手。不过它们各有缺陷,llcom虽然可以使用lua脚本做很多自动化处理,但无法显示图表。python虽然可以显示图表,但实时更新的效果并不好。使用WPF,虽然可以实现很多功能,但需要搭建Visual Studio环境,并且需要写不少代码。

        由于时间限制,目前我只实现了简单的定时发送,转为浮点数据的功能。后续,我会添加显示图表的功能,记录日志的功能还没有做好,使用会出问题。并且我暂时并不打算在这上面花太多时间,所以没怎么考虑界面设计。

        因此,界面很简单,使用起来也很简单。

XAML文件

<Window x:Class="expr_com.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="expr_com" Height="700" Width="1000"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto" /><!-- 可用串口 --><RowDefinition Height="Auto" /><!-- 波特率 --><RowDefinition Height="Auto" /><!-- 打开串口按钮 --><RowDefinition Height="Auto" /><!-- 发送数据 --><RowDefinition Height="Auto" /><!-- 16进制复选框 --><RowDefinition Height="Auto" /><!-- 16进制显示复选框 --><RowDefinition Height="Auto" /><!-- 单次发送和定时循环发送按钮 --><RowDefinition Height="Auto" /><!-- 周期(秒) --><RowDefinition Height="Auto" /><!-- 记录数据复选框 --><RowDefinition Height="Auto" /><!-- 处理数据复选框及参数 --><RowDefinition Height="*" /><!-- 接收数据框 --><RowDefinition Height="*" /><!-- 处理数据框 --></Grid.RowDefinitions><StackPanel Orientation="Horizontal" Grid.Row="0" Margin="10,10,10,0"><Label Content="可用串口:" Width="80" /><ComboBox Name="cmbPorts" SelectionChanged="cmbPorts_SelectionChanged" Width="150" /></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="1" Margin="10,0,10,0"><Label Content="波特率:" Width="80" /><TextBox Name="txtBaudRate" Text="115200" Width="100" /></StackPanel><Button Name="btnOpenPort" Content="打开串口" Click="btnOpenPort_Click" Width="120" Margin="10,0,10,10" Grid.Row="2" /><StackPanel Orientation="Horizontal" Grid.Row="3" Margin="10,0,10,0"><Label Content="发送数据:" Width="80" /><TextBox Name="txtSendData" Text="01040000000271CB" Width="200" /></StackPanel><CheckBox Name="chkHex" Content="16进制" Margin="10,0,10,10" Grid.Row="4" /><CheckBox Name="chkHexDisplay" Content="16进制显示" Margin="10,0,10,10" Grid.Row="5" /><StackPanel Orientation="Horizontal" Grid.Row="6" Margin="10,0,10,0"><Button Name="btnSendOnce" Content="单次发送" Click="btnSendOnce_Click" Width="120" /><Button Name="btnStartLoopSend" Content="定时循环发送" Click="btnStartLoopSend_Click" Width="120" Margin="10,0,0,0" /></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="7" Margin="10,0,10,0"><Label Content="周期(秒):" Width="80" /><TextBox Name="txtPeriod" Text="0.1" Width="50" /></StackPanel><CheckBox Name="chkLog" Content="记录数据" Margin="10,0,10,10" Grid.Row="8" /><StackPanel Orientation="Horizontal" Grid.Row="9" Margin="10,0,10,0"><CheckBox Name="chkProcessData" Content="处理数据" Margin="0,0,10,0" /><Label Content="起始位置:" Width="80" /><TextBox Name="txtStartIndex" Text="7" Width="50" Margin="0,0,10,0" /><Label Content="长度:" Width="50" /><TextBox Name="txtLength" Text="8" Width="50" /></StackPanel><TextBox Name="txtReceivedData" IsReadOnly="True" Margin="10,0,10,10" Grid.Row="10" VerticalScrollBarVisibility="Auto" /><Grid Grid.Row="11" Margin="10,0,10,10"><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBox Name="txtExtractedData" IsReadOnly="True" VerticalScrollBarVisibility="Auto" Grid.Column="0" /><TextBox Name="txtFloatData" IsReadOnly="True" VerticalScrollBarVisibility="Auto" Grid.Column="1" /></Grid></Grid>
</Window>

CS代码

using System;
using System.IO.Ports;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using System.Timers;namespace expr_com
{public partial class MainWindow : Window{private SerialPort? _serialPort; // 声明为可为 null 的类型private System.Timers.Timer? _timer; // 声告为可为 null 的类型public MainWindow(){InitializeComponent();LoadAvailablePorts();_serialPort = null; // 初始化为 null_timer = null; // 初始化为 null}private void LoadAvailablePorts(){cmbPorts.ItemsSource = SerialPort.GetPortNames();}private void cmbPorts_SelectionChanged(object sender, SelectionChangedEventArgs e){if (cmbPorts.SelectedItem != null){txtBaudRate.Focus();}}private void btnOpenPort_Click(object sender, RoutedEventArgs e){if (cmbPorts.SelectedItem == null){MessageBox.Show("请选择一个串口。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);return;}if (_serialPort == null || !_serialPort.IsOpen){try{_serialPort = new SerialPort(cmbPorts.SelectedItem.ToString(), int.Parse(txtBaudRate.Text)){ReadTimeout = 1000, // 增加读取超时时间WriteTimeout = 500,DataBits = 8,StopBits = StopBits.One,Parity = Parity.None};// 注册 DataReceived 事件_serialPort.DataReceived += SerialPort_DataReceived;_serialPort.Open();btnOpenPort.Content = "关闭串口";// 显示成功消息txtReceivedData.AppendText("← 串口已打开。" + Environment.NewLine);}catch (Exception ex){MessageBox.Show($"打开串口失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);txtReceivedData.AppendText($"← 打开串口失败: {ex.Message}" + Environment.NewLine);}}else{_serialPort.DataReceived -= SerialPort_DataReceived; // 取消注册 DataReceived 事件_serialPort.Close();btnOpenPort.Content = "打开串口";// 显示成功消息txtReceivedData.AppendText("← 串口已关闭。" + Environment.NewLine);}}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){try{string data = _serialPort.ReadExisting();if (!string.IsNullOrEmpty(data)){Dispatcher.Invoke(() =>{if (chkHexDisplay.IsChecked == true){// 将接收到的数据转换为16进制字符串byte[] bytes = Encoding.ASCII.GetBytes(data);string hexData = BitConverter.ToString(bytes).Replace("-", " ");txtReceivedData.AppendText($"→ {hexData}" + Environment.NewLine);if (chkProcessData.IsChecked == true){ProcessData(hexData);}}else{txtReceivedData.AppendText($"→ {data}" + Environment.NewLine);}// 立即滚动到底部txtReceivedData.ScrollToEnd();});}}catch (Exception ex){// 处理其他异常Dispatcher.Invoke(() =>{txtReceivedData.AppendText($"→ 读取错误: {ex.Message}" + Environment.NewLine);});}}private void LogData(string data){string logFilePath = Path.Combine("data_log", $"log_{DateTime.Now:yyyyMMdd_HHmmss}.csv");File.AppendAllText(logFilePath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss},{data}{Environment.NewLine}");}private async void btnSendOnce_Click(object sender, RoutedEventArgs e){await SendDataAsync(false);}private async void btnStartLoopSend_Click(object sender, RoutedEventArgs e){if (_timer == null || !_timer.Enabled){try{double period = double.Parse(txtPeriod.Text);_timer = new System.Timers.Timer(period * 1000); // 转换为毫秒_timer.Elapsed += OnTimedEvent;_timer.AutoReset = true;_timer.Enabled = true;btnStartLoopSend.Content = "停止循环发送";// 显示启动消息txtReceivedData.AppendText($"← 定时循环发送已启动,周期: {period} 秒。" + Environment.NewLine);}catch (Exception ex){MessageBox.Show($"设置定时发送失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);txtReceivedData.AppendText($"← 设置定时发送失败: {ex.Message}" + Environment.NewLine);}}else{_timer.Enabled = false;_timer.Dispose();_timer = null;btnStartLoopSend.Content = "定时循环发送";// 显示停止消息txtReceivedData.AppendText("← 定时循环发送已停止。" + Environment.NewLine);}}private async void OnTimedEvent(object source, ElapsedEventArgs e){try{await Dispatcher.InvokeAsync(async () =>{await SendDataAsync(true);});}catch (Exception ex){// 处理其他异常await Dispatcher.InvokeAsync(() =>{txtReceivedData.AppendText($"← 发送错误: {ex.Message}" + Environment.NewLine);});}}private async Task SendDataAsync(bool isLoop){try{if (_serialPort != null && _serialPort.IsOpen){string sendData = txtSendData.Text.Trim();if (string.IsNullOrEmpty(sendData)){throw new InvalidOperationException("发送数据不能为空。");}if (chkHex.IsChecked == true){byte[] hexData = Convert.FromHexString(sendData);_serialPort.Write(hexData, 0, hexData.Length);}else{_serialPort.WriteLine(sendData);}// 显示发送数据txtReceivedData.AppendText($"← {sendData}" + Environment.NewLine);if (chkLog.IsChecked == true){LogData(sendData);}}else{// 串口未打开,显示错误信息txtReceivedData.AppendText("← 串口未打开,无法发送数据。" + Environment.NewLine);}}catch (Exception ex){// 处理其他异常txtReceivedData.AppendText($"← 发送错误: {ex.Message}" + Environment.NewLine);}}private void ProcessData(string hexData){try{// 从文本框中获取用户输入的起始位置和长度int startIndex = int.Parse(txtStartIndex.Text) - 1; // 减1是为了适应索引从0开始int length = int.Parse(txtLength.Text);// 去除空格string hexDataWithoutSpaces = hexData.Replace(" ", "");// 检查数据长度是否足够if (hexDataWithoutSpaces.Length >= startIndex + length){// 截取指定位置和长度的数据string hexDataToProcess = hexDataWithoutSpaces.Substring(startIndex, length);// 将16进制字符串转换为字节数组byte[] bytes = Convert.FromHexString(hexDataToProcess);// 检查字节顺序if (BitConverter.IsLittleEndian){// 如果系统是小端序,而数据是大端序,则需要反转字节顺序Array.Reverse(bytes);}// 将字节数组转换为浮点数float floatValue = BitConverter.ToSingle(bytes, 0);// 追加结果txtExtractedData.AppendText($"{hexDataToProcess}" + Environment.NewLine);txtFloatData.AppendText($"{floatValue}" + Environment.NewLine);// 立即滚动到底部txtExtractedData.ScrollToEnd();txtFloatData.ScrollToEnd();}else{txtExtractedData.AppendText("数据长度不足,无法处理。" + Environment.NewLine);}}catch (FormatException ex){txtExtractedData.AppendText($"格式错误: {ex.Message}" + Environment.NewLine);}}}
}

实际效果:

单次发送

循环发送

相关文章:

_FYAW智能显示控制仪表的简单使用_串口通信

一、简介 该仪表可以实时显示位移传感器的测量值&#xff0c;并可设定阈值等。先谈谈简单的使用方法&#xff0c;通过说明书&#xff0c;我们可以知道长按SET键可以进入参数选择状态&#xff0c;按“↑”“↓”可以选择该组参数的上一个或者下一个参数。 从参数一览中可以看到有…...

激光雷达定位初始化的另外一个方案 通过键盘按键移动当前位姿 (附python代码)

通常使用的是通过在 rviz 中点选指定初始化位置和方向来完成点云的初始化匹配。 但是这种粗略的初始化方法有时候可能不成功,因此需要使用准确的初始化方法,以更好的初始值进行无损检测配准。 为了提供更好的匹配初始值,我使用 Python 脚本获取键盘输入,并不断调整这个匹配…...

从0-1逐步搭建一个前端脚手架工具并发布到npm

前言 vue-cli 和 create-react-app 等 cli 脚手架工具用于快速搭建应用&#xff0c;无需手动配置复杂的构建环境。本文介绍如何使用 rollup 搭建一个脚手架工具。 脚手架工具的工作流程简言为&#xff1a;提供远端仓库各种模版 > 用户通过命令选择模版 > 拉取仓库代码 …...

河道水位流量一体化自动监测系统:航运安全的护航使者

在广袤的水域世界中&#xff0c;航运安全始终是至关重要的课题。而河道水位流量一体化自动监测系统的出现&#xff0c;如同一位强大的护航使者&#xff0c;为航运事业的稳定发展提供了坚实的保障。 水位传感器&#xff1a;负责实时监测河道的水位变化。这些传感器通常采用先进的…...

维护在线重做日志

学习目标 解释在线重做日志文件的目的概述在线重做日志文件的结构控制日志开关和检查点多路复用和维护在线重做日志文件使用OMF管理在线重做日志文件获取在线重做日志文件信息 在线重做日志文件提供了在数据库发生故障时重做事务的方法。 每个事务都同步写入重做日志缓冲区&a…...

ASCB1系列APP操控末端回路智能微断 物联网断路器 远程控制开关 学校、工厂、农场、商业大楼等可用

安科瑞戴婷 Acrel-Fanny ASCB1系列智能微型断路器是安科瑞电气股份有限公司全新推出的智慧用电产品&#xff0c;产品由智能微型断路器与智能网关两部分组成&#xff0c;可用于对用电线路的关键电气因素&#xff0c;如电压、电流、功率、温度、漏电、能耗等进行实时监测&#x…...

Python入门(10)--面向对象进阶

Python面向对象进阶 &#x1f680; 1. 继承与多态 &#x1f504; 1.1 继承基础 class Animal:def __init__(self, name, age):self.name nameself.age agedef speak(self):passdef describe(self):return f"{self.name} is {self.age} years old"class Dog(Anim…...

Makefile 之 自动化变量

作用范围只在这条规则以及连带规则中&#xff0c;所以其值也只在作用范围内有效。而不会影响规则链以外的全局变量的值。 "$" 表示目标的集合&#xff0c;就像一个数组&#xff0c;"$"依次取出目标&#xff0c;并执于命令。 "$<"和"$&qu…...

鸿蒙开发:ForEach中为什么键值生成函数很重要

前言 在列表组件使用的时候&#xff0c;如List、Grid、WaterFlow等&#xff0c;循环渲染时都会使用到ForEach或者LazyForEach&#xff0c;当然了&#xff0c;也有单独使用的场景&#xff0c;如下&#xff0c;一个很简单的列表组件使用&#xff0c;这种使用方式&#xff0c;在官…...

沃丰科技智能外呼机器人:超越人工,重塑外呼体验

随着科技的不断发展&#xff0c;人工智能已经逐渐渗透到各行各业&#xff0c;其中智能外呼机器人的出现&#xff0c;更是给企业带来了全新的客户体验。与传统的人工外呼相比&#xff0c;智能外呼机器人具有更高的效率、更低的成本以及更好的用户体验等优势。 优势一&#xff1…...

百度飞浆:paddle 线性回归模型

学习引用 参考视频&#xff1a; https://www.bilibili.com/video/BV1oRtkeVEVx?spm_id_from333.788.player.switch&vd_sourcec7739de98d044e74cdc74d6e772bed5f&p2 这段代码使用PaddlePaddle深度学习框架来实现一个简单的线性回归模型&#xff0c;旨在从给定的出租车…...

【JavaSE】【网络编程】UDP数据报套接字编程

目录 一、网络编程简介二、Socket套接字三、TCP/UDP简介3.1 有连接 vs 无连接3.2 可靠传输 vs 不可靠传输3.3 面向字节流 vs 面向数据报3.4 双向工 vs 单行工 四、UDP数据报套接字编程4.1 API介绍4.1.1 DatagramSocket类4.1.1.1 构造方法4.1.1.2 主要方法 4.1.2 DatagramPocket…...

45.坑王驾到第九期:Mac安装typescript后tsc命令无效的问题

点赞收藏加关注&#xff0c;你也能主打别墅&#xff01; 一、问题描述 Mac上终端运行如下命令&#xff1a; sudo npm install typescript -g //全局安装ts提示成功安装后&#xff0c;我测试tsc -v这个命令时出现如下错误&#xff1a; 也就是说找不到 tsc 命令。 二、解决方…...

20241120-Milvus向量数据库快速体验

目录 20241120-Milvus向量数据库快速体验Milvus 向量数据库pymilvus内嵌向量数据库模式设置向量数据库创建 Collections准备数据用向量表示文本插入数据 语义搜索向量搜索带元数据过滤的向量搜索查询通过主键搜索 删除实体加载现有数据删除 Collections了解更多 个人主页: 【⭐…...

【Golang】——Gin 框架中间件详解:从基础到实战

中间件是 Web 应用开发中常见的功能模块&#xff0c;Gin 框架支持自定义和使用内置的中间件&#xff0c;让你在请求到达路由处理函数前进行一系列预处理操作。这篇博客将涵盖中间件的概念、内置中间件的用法、如何编写自定义中间件&#xff0c;以及在实际应用中的一些最佳实践。…...

量子计算来袭:如何保护未来的数字世界

目录 前言 一、量子计算安全的学习方向 1. 量子物理学基础 2. 量子计算原理与技术 3. 传统网络安全知识 4. 量子密码学 5. 量子计算安全政策与法规 二、量子计算的漏洞风险 1. 加密算法被破解风险 2. 区块链安全风险 3. 量子密钥分发风险 4. 量子计算系统自身风险 …...

VMware虚拟机(Ubuntu或centOS)共享宿主机网络资源

VMware虚拟机(Ubuntu或centOS)共享宿主机网络资源 由于需要在 Linux 环境下进行一些测试工作&#xff0c;于是决定使用 VMware 虚拟化软件来安装 Ubuntu 24.04 .1操作系统。考虑到测试过程中需要访问 Github &#xff0c;要使用Docker拉去镜像等外部网络资源&#xff0c;因此产…...

光伏电站仿真系统的作用

光伏仿真系统有多方面的重要作用&#xff0c;不仅对前期的项目设计评估还是后期的运维效验都有非常重要的作用。 1、优化系统设计 通过输入不同的光伏组件参数、布局方案以及气象条件等&#xff0c;模拟各种设计场景下光伏电站的性能表现。例如&#xff0c;可以比较不同类型光…...

Golang文件操作

写文件 &emsp&#xff1b; os模块可以创建文件&#xff0c;使用fmt可以写入文件。如以下例子&#xff1a; package mainimport ("fmt""os" )func main() {// 学习 golang的文件操作file, err : os.Create("test.txt")if err ! nil {fmt.P…...

爬虫开发工具与环境搭建——使用Postman和浏览器开发者工具

第三节&#xff1a;使用Postman和浏览器开发者工具 在网络爬虫开发过程中&#xff0c;我们经常需要对HTTP请求进行测试、分析和调试。Postman和浏览器开发者工具&#xff08;特别是Network面板和Console面板&#xff09;是两种最常用的工具&#xff0c;能够帮助开发者有效地捕…...

React(二)

文章目录 项目地址七、数据流7.1 子组件传递数据给父组件7.1.1 方式一:給父设置回调函数,传递给子7.1.2 方式二:直接将父的setState传递给子7.2 给props传递jsx7.2.1 方式一:直接传递组件给子类7.2.2 方式二:传递函数给子组件7.3 props类型验证7.4 props的多层传递7.5 cla…...

同步原语(Synchronization Primitives)

同步原语&#xff08;Synchronization Primitives&#xff09;是用于控制并发编程中多个线程或进程之间的访问顺序&#xff0c;确保共享资源的安全访问的一组机制或工具。它们解决了竞争条件&#xff08;Race Condition&#xff09;、死锁&#xff08;Deadlock&#xff09;等并…...

SpringBoot服务多环境配置

一个项目的的环境一般有三个&#xff1a;开发(dev)、测试(test)、生产(proc)&#xff0c;一般对应三套环境&#xff0c;三套配置文件。 像下面这样直接写两个配置文件是不行的。 application.ymlserver:port: 8080application-dev.ymlspring:datasource:driver-class-name: co…...

STM32单片机CAN总线汽车线路通断检测-分享

目录 目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 1.电路图采用Altium Designer进行设计&#xff1a; 2.实物展示图片 三、程序源代码设计 四、获取资料内容 前言 随着汽车电子技术的不断发展&#xff0c;车辆通信接口在汽车电子控…...

【环境搭建】使用IDEA远程调试Docker中的Java Web

有时候要对Docker的Java Web远程调试其功能&#xff0c;于是就需要使用IDEA的远程调试功能&#xff0c;记录一下简单配置方法。 以Kylin4.0.0为例&#xff0c;首先拉取镜像并启动容器&#xff1a; $ docker pull apachekylin/apache-kylin-standalone:4.0.0$ docker run -d \-…...

贴代码框架PasteForm特性介绍之select,selects,lselect和reload

简介 PasteForm是贴代码推出的 “新一代CRUD” &#xff0c;基于ABPvNext&#xff0c;目的是通过对Dto的特性的标注&#xff0c;从而实现管理端的统一UI&#xff0c;借助于配套的PasteBuilder代码生成器&#xff0c;你可以快速的为自己的项目构建后台管理端&#xff01;目前管…...

STM32G4的数模转换器(DAC)的应用

目录 概述 1 DAC模块介绍 2 STM32Cube配置参数 2.1 参数配置 2.2 项目架构 3 代码实现 3.1 接口函数 3.2 功能函数 3.3 波形源代码 4 DAC功能测试 4.1 测试方法介绍 4.2 波形测试 概述 本文主要介绍如何使用STM32G4的DAC模块功能&#xff0c;笔者使用STM32Cube工具…...

SpringMVC跨线程获取requests请求对象(子线程共享servletRequestAttributes)和跨线程获取token信息

文章目录 引言I 跨线程共享数据跨线程获取requests请求对象基于org.slf4j.MDC存储共享数据InheritableThreadLocal解决异步线程,无法获取token信息问题II Feign 传递请求属性feign 模块处理被调用方处理请求头III 异步调用的方式CompletableFutureAsync注解Executors引言 本文…...

提取repo的仓库和工作树(无效)

问题 从供应商处获取的.repo的git仓库裸(project-object)仓库和工作树(projects)是分开的。 解决方案 根据工作树的软链接路劲&#xff0c;将工作树合并到project-object下。 import os import shutil import argparse import logging# 设置日志配置 logging.basicConfig(l…...

力扣整理版七:二叉树(待更新)

满二叉树&#xff1a;如果一棵二叉树只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。深度为k&#xff0c;有2^k-1个节点的二叉树。 完全二叉树&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&am…...

丰台网站建设公司/短视频排名seo

单词&#xff1a;efficient computation(高效运算) DECIMATION-IN-TIME FFT ALGORITHMS(按时间抽取的傅里叶算法) In-Place Computations(同址运算) Alternative Forms(其他形式) 知识点&#xff1a; 1、改善DFT计算效率的大多数方法均利用了Wn kn的对称性和周期性...

帝国网站7.2 pc wap 跳转/百度指数大数据分享平台

你是否想知道企业大规模系统是如何设计的? 在软件开发开始之前&#xff0c;我们必须选择一个合适的架构&#xff0c;能提供所需的功能和质量特性。因此&#xff0c;在将架构应用到我们的设计之前&#xff0c;我们应该了解各种不同架构的特点。 01、什么是架构模式 根据维基百…...

如何建立个人网站/新闻类软文营销案例

想了一会儿还是不知道怎么处理顺序这个情况。。。于是看了题解&#xff08;太弱啦qwq。。&#xff09; 膜hzwer大大 N辆车&#xff0c;M个工人。 把每个工人拆成N个点。记为A[i,j]表示第i个工人修倒数第j辆车。 每个车跟所有N*M个工人拆出的点连边。流量为1&#xff0c;费用为…...

东丽做网站/免费发广告网站

1.采用简化的分批法计算产品成本时&#xff0c;在基本生产成本二级账计算得到的各项间接计入费用累计分配率&#xff0c;既是在各批完工产品之间分配各该费用的依据&#xff0c;也是在完工批别与月末在产品批别之间以及某批产品的完工产品与月末在产品之间分配各该费用的依据。…...

iis发布网站无法访问/电商网站建设方案

第一部分&#xff1a;预备知识 原文&#xff1a;Part I: Initial Knowledge 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 自豪地采用谷歌翻译 你需要学习的第一件事就是一切事情。我知道这是吓人的&#xff0c;但我在介绍中提到&#xff0c;你在整本书中只会练习三个…...

实用网站设计步骤/谷歌推广费用多少

此方法撰写于 2019 年 05 月 30 日&#xff0c;能有效阻止 WIN10各版本更新&#xff0c;亲测有效&#xff0c;操作方便。&#xff08;请将这几步都做完&#xff0c;如果只做单项或几项&#xff0c;不确保它会反复&#xff0c;所以请都做完。注&#xff1a;本文以WIN10 1511企业…...