首页
关于
标签
友链
更多
统计
图片
Search
1
A测-气压测控仿真系统
78 阅读
2
自建博客的图床问题-PicGo+github+obsidian
20 阅读
3
拨号上网无法使用clash verge代理的问题
16 阅读
4
高数强化梳理
12 阅读
5
CF Round1043 Div.3
9 阅读
算法竞赛
杂项
技术
考研
专业课
登录
Search
标签搜索
专业课
课程实验
Python
算法竞赛
分布式计算
数学
技术
Codeforces
Java
微服务
考研
Blog
代理
Atcoder
网络编程
Jmeter
gRPC
RPC
ActiveMQ
消息队列
HoshiuZ
累计撰写
12
篇文章
累计收到
13
条评论
首页
栏目
算法竞赛
杂项
技术
考研
专业课
页面
关于
标签
友链
统计
图片
搜索到
12
篇与
的结果
2025-09-20
A测-气压测控仿真系统
测试内容是去年的补测题目。区别在于,去年的上位机软件直接用的是 XCOM,而今年的正测需要自行编写上位机软件。关于软件的安装以及初步的使用,参考了 西电A测:串口通信仿真-CSDN博客 与 2024春季 西电A测-气压测控仿真系统-CSDN博客。过程虽然今年让自己写一个上位机软件,但打算还是先用 XCOM 进行测试,一切正常后打算用 Python Tkinter 来写个 GUI。电路图已经提供了,只需分析电路图然后用 arduino IDE 写代码即可。这是 LCD,发现接了引脚 12,11,5,4,3,2,所以初始化 LCD 时对这几个引脚初始化。这是直流电机驱动电路,发现接了引脚 7,所以控制直流电机的操作可以通过将引脚 7 写高/低电平来实现。Arduino IDE 代码通过上述分析写出如下代码。选用的是串口 COM3.#include <Wire.h> #include <Adafruit_BMP085.h> #include <LiquidCrystal.h> Adafruit_BMP085 bmp; LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setup() { Serial.begin(9600); lcd.begin(16, 2); pinMode(7, OUTPUT); bmp.begin(); } int setATM = 860; void loop() { int realATM = (bmp.readPressure() + 50) / 100; String str = ""; lcd.print("ID:"); if(Serial.available() > 0) { while(Serial.available() > 0) { str += (char)Serial.read(); delay(10); } str.trim(); lcd.println(str); int len = str.length(); int last = str[len - 1] - '0'; setATM = 860 + last; str = ""; } Serial.print("ATM: "); Serial.print(realATM); Serial.println("hPa"); lcd.setCursor(0, 1); lcd.print("ATM: "); lcd.print(realATM); lcd.print("hPa"); lcd.home(); if(realATM >= setATM) { digitalWrite(7, HIGH); } else { digitalWrite(7, LOW); } delay(1000); }将代码用 arduino IDE 编译后,proteus 选中 arduino UNO 元件,并将 program file 选中生成的 .hex 文件。我所使用的串口是 COM3 和 COM4,用 VSPD 配置一下就行。然后打开 XCOM,设为 COM4,接着用 proteus 开启仿真。如图所示,正常运行。接下来就只剩下 GUI 的编写。GUI编写采用的是 Python 语言的 Tkinter 库,并用 pyserial 来实现串口通信。代码如下:import tkinter as tk from tkinter import ttk, scrolledtext import serial import serial.tools.list_ports from threading import Thread, Event import time class MyCOM: def __init__(self, window): # 初始化主窗口 self.window = window self.window.title("114514 田所浩二 - 气压测控仿真系统") self.window.geometry("800x600") # 串口相关变量 self.serial_port = None self.is_serial_open = False self.receive_thread = None self.stop_event = Event() self.create_widgets() # 创建界面控件 self.update_com_list() # 初始化时更新可用串口列表 def create_widgets(self): """创建并布局所有GUI控件""" # 顶部框架 - 串口控制区域 top_frame = ttk.LabelFrame(self.window, text="串口配置", padding="5") top_frame.grid(row=0, column=0, columnspan=2, padx=5, pady=5, sticky="ew") # 串口选择标签和下拉框 ttk.Label(top_frame, text="选择串口:").grid(row=0, column=0, padx=5, pady=5, sticky="w") self.com_combo = ttk.Combobox(top_frame, width=15, state="readonly") self.com_combo.grid(row=0, column=1, padx=5, pady=5) # 波特率选择标签和下拉框 ttk.Label(top_frame, text="波特率:").grid(row=0, column=2, padx=5, pady=5, sticky="w") self.baud_combo = ttk.Combobox(top_frame, width=10, values=['9600', '19200', '38400', '57600', '115200'], state="readonly") self.baud_combo.set('9600') # 默认波特率 self.baud_combo.grid(row=0, column=3, padx=5, pady=5) # 刷新串口按钮 self.refresh_btn = ttk.Button(top_frame, text="刷新串口", command=self.update_com_list) self.refresh_btn.grid(row=0, column=4, padx=5, pady=5) # 打开/关闭串口按钮 self.open_close_btn = ttk.Button(top_frame, text="打开串口", command=self.toggle_serial) self.open_close_btn.grid(row=0, column=5, padx=5, pady=5) # 状态标签 self.status_label = ttk.Label(top_frame, text="当前状态: 串口未打开", foreground="red") self.status_label.grid(row=0, column=6, padx=10, pady=5, sticky="w") # 中部框架 - 数据发送区域 send_frame = ttk.LabelFrame(self.window, text="发送数据", padding="5") send_frame.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="ew") # 发送数据输入框 ttk.Label(send_frame, text="发送指令:").grid(row=0, column=0, padx=5, pady=5, sticky="w") self.send_entry = ttk.Entry(send_frame, width=50) self.send_entry.insert(0, "114514") # 默认填入学号 self.send_entry.grid(row=0, column=1, padx=5, pady=5, sticky="ew") # 发送按钮 self.send_btn = ttk.Button(send_frame, text="发送", command=self.send_data, state="disabled") self.send_btn.grid(row=0, column=2, padx=5, pady=5) # 底部框架 - 数据接收区域 receive_frame = ttk.LabelFrame(self.window, text="接收数据", padding="5") receive_frame.grid(row=2, column=0, columnspan=2, padx=5, pady=5, sticky="nsew") # 接收数据显示区域 self.receive_text = scrolledtext.ScrolledText(receive_frame, width=70, height=20, state="disabled") self.receive_text.grid(row=0, column=0, columnspan=3, padx=5, pady=5, sticky="nsew") self.receive_text.tag_config("send_color", foreground="blue") self.receive_text.tag_config("receive_color", foreground="green") self.receive_text.tag_config("error_color", foreground="red") # 清空接收区按钮 clear_btn = ttk.Button(receive_frame, text="清空接收区", command=self.clear_receive_area) clear_btn.grid(row=1, column=0, padx=5, pady=5, sticky="w") # 配置网格权重,使界面随窗口调整大小 self.window.columnconfigure(0, weight=1) self.window.rowconfigure(2, weight=1) receive_frame.columnconfigure(0, weight=1) receive_frame.rowconfigure(0, weight=1) def update_com_list(self): """获取可用串口列表并更新下拉框""" com_list = [port.device for port in serial.tools.list_ports.comports()] self.com_combo['values'] = com_list if com_list: self.com_combo.set(com_list[0]) def toggle_serial(self): """打开或关闭串口""" if not self.is_serial_open: self.open_serial() else: self.close_serial() def open_serial(self): """打开串口""" try: selected_port = self.com_combo.get() baud_rate = int(self.baud_combo.get()) if not selected_port: self.update_status("请选择有效的串口", "red") return # 创建串口连接 self.serial_port = serial.Serial( port=selected_port, baudrate=baud_rate, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1 ) self.is_serial_open = True self.update_ui_for_serial_state() self.update_status(f"已打开 {selected_port} ({baud_rate}bps)", "green") # 启动接收线程 self.stop_event.clear() self.receive_thread = Thread(target=self.receive_data, daemon=True) self.receive_thread.start() except Exception as e: self.update_status(f"打开串口失败: {str(e)}", "red") def close_serial(self): """关闭串口""" try: self.is_serial_open = False self.stop_event.set() if self.serial_port and self.serial_port.is_open: self.serial_port.close() self.update_ui_for_serial_state() self.update_status("串口已关闭", "red") except Exception as e: self.update_status(f"关闭串口时出错: {str(e)}", "red") def update_ui_for_serial_state(self): """根据串口状态更新UI控件状态""" if self.is_serial_open: self.open_close_btn.config(text="关闭串口") self.com_combo.config(state="disabled") self.baud_combo.config(state="disabled") self.refresh_btn.config(state="disabled") self.send_btn.config(state="normal") else: self.open_close_btn.config(text="打开串口") self.com_combo.config(state="readonly") self.baud_combo.config(state="readonly") self.refresh_btn.config(state="normal") self.send_btn.config(state="disabled") def update_status(self, message, color="black"): """更新状态标签""" self.status_label.config(text=f"当前状态: {message}", foreground=color) def send_data(self): """发送数据到串口""" try: data = self.send_entry.get() if data and self.serial_port and self.serial_port.is_open: self.serial_port.write(data.encode()) self.display_data(f"发送: {data}", "send_color") except Exception as e: self.update_status(f"发送数据失败: {str(e)}", "red") def receive_data(self): """在后台线程中接收串口数据""" while not self.stop_event.is_set() and self.is_serial_open: try: if self.serial_port and self.serial_port.in_waiting > 0: data = self.serial_port.readline().decode('utf-8', errors='ignore').strip() if data: self.display_data(f"接收: {data}", "receive_color") except Exception as e: if self.is_serial_open: # 只在串口打开时报告错误 self.window.after(0, lambda: self.update_status(f"接收错误: {str(e)}", "error_color")) break time.sleep(0.01) def display_data(self, data, tag_type="receive_color"): """在接收文本框中显示数据""" def update_display(): self.receive_text.config(state="normal") self.receive_text.insert(tk.END, data + "\n", (tag_type,)) self.receive_text.see(tk.END) # 自动滚动到底部 self.receive_text.config(state="disabled") # 确保UI更新在主线程中执行 self.window.after(0, update_display) def clear_receive_area(self): """清空接收数据显示区域""" self.receive_text.config(state="normal") self.receive_text.delete(1.0, tk.END) self.receive_text.config(state="disabled") def on_closing(self): """窗口关闭时的清理工作""" if self.is_serial_open: self.close_serial() self.window.destroy() if __name__ == "__main__": root = tk.Tk() app = MyCOM(root) root.protocol("WM_DELETE_WINDOW", app.on_closing) root.mainloop()界面如下:
2025年09月20日
78 阅读
2 评论
0 点赞
2025-08-27
CF Round1045 Div.2
A当 $n, a, b$ 同奇偶,显然成立。由于按顺序的,所以只能由 $b$ 覆盖 $a$,所以当三者奇偶性不相同但是 $n$ 与 $b$ 同奇偶时,也成立。除了这两种情况以外都不成立。#include<bits/stdc++.h> #define ll long long int T; void solve() { int n, a, b; std::cin >> n >> a >> b; if(n % 2 == a % 2 && a % 2 == b % 2) std::cout << "YES\n"; else if(n % 2 == b % 2 && a < b) std::cout << "YES\n"; else std::cout << "NO\n"; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cin>>T; while(T--) { solve(); } return 0; }B当 $k$ 为奇数时,只需把每个数都加成偶数即可。当 $k$ 为偶数时,需要找到一个奇数 $b$ 使得 $b$ 不是 $k$ 的因数,然后将所有的数都加成 $b$ 的倍数,可以证明每个数加的次数一定都小于 $k$ 。$b$ 的求法,可以将 $k$ 一直除以 $2$ 直至为奇数,然后再加上 $2$ ,这样一个值即为一个符合条件的 $b$ ,时间复杂度 $O(\log k)$.知道了 $b$ 后,如何将 $a[i]$ 加成一个 $b$ 的倍数?有 $a[i] + kx = by$ ,所以即为同余方程 $kx + by = a[i]$,由上述 $b$ 的求法,显然 $b$ 与 $k$ 互质,所以这个同余方程一定有解,用扩展欧几里得算法求解即可,得到 $x_0, y_0$.题目中要求加的次数不超过 $k$ ,所以有 $-k \le x \le 0$,而有 $x = x_0 + tb$,代入解得 $\dfrac{-k-x_0}{b} \le t \le \dfrac{-x_0}{b}$,取 $t = \Big\lceil\dfrac{-k-x_0}{b}\Big\rceil$ 再进行调整即可得出 $x$.$a[i]$ 最终的值即为 $a[i] - kx$.#include<bits/stdc++.h> #define ll long long int T; void Exgcd(ll a,ll b, ll& x, ll& y) { if(!b) x = 1, y = 0; else { Exgcd(b, a % b, x, y); int t = x; x = y, y = t - a / b * y; } } void solve() { ll n, k; std::cin >> n >> k; std::vector<ll> a(n + 1); for(int i = 1; i <= n; i++) { std::cin >> a[i]; } if(n == 1) { std::cout << a[1] + k << "\n"; } else { if(k & 1) { for(int i = 1; i <= n; i++) { if(a[i] & 1) a[i] += k; } for(int i = 1; i <= n; i++) { std::cout << a[i] << " "; } std::cout << "\n"; } else { ll b = k; while(b % 2 == 0) b /= 2; b += 2; ll x, y; Exgcd(k, b, x, y); for(int i = 1; i <= n; i++) { ll X, Y; X = x * a[i], Y = y * a[i]; ll t = ceil((double)(-k - X) / b); if(X + b * t < -k) t++; if(X + b * t > 0) t--; X += b * t; a[i] -= X * k; } for(int i = 1; i <= n; i++) { std::cout << a[i] << " "; } std::cout << "\n"; } } } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cin>>T; while(T--) { solve(); } return 0; }C先考虑奇数项,把其变成左右两个偶数项中的较小值。再考虑偶数项,经过了上一步操作,每次一个子区间往后/往前扩展两个位置时,偶数项增量一定比奇数项增量大,所以只需考虑偶数项与其左右两个奇数项构成的子区间。从前往后考虑每个子区间 $[a, b, c]$,其中 $b$ 为偶数项,如果 $b \ge a + c$ 则不用操作,否则令 $sub = a + c - b$,贪心地把这个 $sub$ 尽可能全用在 $c$ 上即可。#include<bits/stdc++.h> #define ll long long int T; void solve() { int n; std::cin >> n; std::vector<ll> a(n + 1); for(int i = 1; i <= n; i++) { std::cin >> a[i]; } ll ans = 0; for(int i = 1; i <= n; i += 2) { ll minn; if(i == 1) minn = a[i + 1]; else if(i == n) minn = a[i - 1]; else minn = std::min(a[i - 1], a[i + 1]); if(minn > a[i]) continue; ans += a[i] - minn; a[i] = minn; } for(int i = 2; i <= n; i += 2) { if(i == n) continue; ll sum = a[i - 1] + a[i + 1]; if(sum <= a[i]) continue; ll sub = sum - a[i]; ans += sub; if(sub > a[i + 1]) a[i + 1] = 0; else a[i + 1] -= sub; } std::cout << ans << "\n"; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cin>>T; while(T--) { solve(); } return 0; }
2025年08月27日
2 阅读
0 评论
0 点赞
2025-08-24
ABC420
赛时 5/7,中途有点事,G 没打完。
2025年08月24日
6 阅读
0 评论
0 点赞
2025-08-24
高数强化梳理
高数强化梳理
2025年08月24日
12 阅读
1 评论
0 点赞
2025-08-24
自建博客的图床问题-PicGo+github+obsidian
解决了博客的图片存储问题。
2025年08月24日
20 阅读
3 评论
0 点赞
1
2
3