分享一个基于Qt的Ymodem的上位机(GitHub开源)

文章目录

  • 1.项目地址
  • 2.Ymodem 协议介绍
  • 3.文件传输过程
  • 4.使用
  • 5.SecureCRT 软件也支持Ymodem
  • 6.基于PyQt5的Ymodem界面实现案例

1.项目地址

https://github.com/XinLiGH/SerialPortYmodem
基于VS2019 Qt5.15.2 编译,Linux下编译也可以,这里不做说明。
在这里插入图片描述

2.Ymodem 协议介绍

YModem 协议是由 XModem 协议演变而来的,每包数据可以达到 1024 字节,是一个非常高效的文件传输协议。我们平常所说的 Ymodem 协议是指的 Ymodem-1K,除此还有 Ymodem-g(没有 CRC 校验,不常用)。YModem-1K 协议用 1024 字节数据帧传输取代了标准的 128 字节数据帧传输,发送的数据会使用 CRC 校验,保证数据传输的正确性。它每传输一个信息块时,就会等待接收端返回 ACK 信号,接收到响应信号后,才会继续传输下一个信息块,从而保证能够接收到全部数据。

3.文件传输过程

通常单片机程序是运行在主程序下的(单片机主程序不支持YModem),我这里由Qt上位机通过串口发送一条自定义的协议告诉单片机,进入升级模式。接着就是下图的流程:
在这里插入图片描述
在这里插入图片描述

4.使用

在这里插入图片描述

5.SecureCRT 软件也支持Ymodem

在这里插入图片描述

6.基于PyQt5的Ymodem界面实现案例

基于PyQt5做一些小工具真的很方便,大家感兴趣可以尝试下!

#coding=utf-8from tkinter import *
from tkinter.ttk import Combobox
from tkinter import filedialog
from tkinter import messagebox
from ctypes import *
import serial.tools.list_ports
import threading
from ymodem import YMODEM
import os
from time import sleepapp = Tk()
comportbox=Combobox(app,width = 7, height = 10)
baudratebox=Combobox(app,width = 8, height = 10)
red_canvas = Canvas(app, width=50, height=50,bg="red")
green_canvas = Canvas(app, width=50, height=50,bg="green")
progress_bar = Canvas(app, width = 350,height = 26,bg = "white")
fill_line = progress_bar.create_rectangle(2,2,0,27,width = 0,fill = "green") 
ser = serial.Serial(bytesize=8, parity='N', stopbits=1, timeout=1, write_timeout=3)
linsten_lock = threading.Lock()
need_listen = 0
exit_listen = Falsedef upgrade_callback(total_packets,file_size,file_name):if len(progress_bar.gettags("text")) == 0:progress_bar.create_text(175, 15, text=file_name, tags="text")progress = total_packets*350/(file_size/1024)progress_bar.coords(fill_line, (0, 0, progress, 30))def set_connect_logo(is_connected = True):if is_connected:red_canvas.place_forget()green_canvas.place(x=100,y=60)comportbox.configure(state='disabled')baudratebox.configure(state='disabled')else:green_canvas.place_forget()red_canvas.place(x=100,y=60)comportbox.configure(state='enabled')baudratebox.configure(state='enabled')def listen_connect_thread():global serglobal need_listenglobal exit_listenglobal linsten_lockwhile exit_listen == False:linsten_lock.acquire()if need_listen == 0:linsten_lock.release()sleep(1)continueelse:com_number = comportbox.get()port_found = 0plist = list(serial.tools.list_ports.comports())if len(plist) <= 0:if ser.is_open == True:ser.close()set_connect_logo(False)else:for item in plist:if com_number == item[0]:port_found = 1breakif port_found == 0:if ser.is_open == True:ser.close()set_connect_logo(False)else:if ser.is_open == False:try:ser.port = com_numberser.open()set_connect_logo(True)except Exception as e:print(e)passlinsten_lock.release()sleep(0.3)continuedef connect():global need_listenglobal sercom_number = comportbox.get()port_found = 0plist = list(serial.tools.list_ports.comports())if ser.is_open == True:messagebox.showinfo(title="Error", message="Already connected!")returnif len(plist) <= 0:messagebox.showinfo(title="Error", message="No available serial!")need_listen = 0set_connect_logo(False)returnelse:for item in plist:if com_number == item[0]:port_found = 1breakif port_found == 0:need_listen = 0set_connect_logo(False)messagebox.showinfo(title="Error", message="Cannot find serial "+com_number)returntry:ser.port = com_numberser.baudrate = 115200 #int(baud_rate)if ser.is_open == False:ser.open()except Exception as e:if ser.is_open == False:need_listen = 0set_connect_logo(False)messagebox.showinfo(title="Error", message=e)returnset_connect_logo(True)need_listen = 1global listen_connectif listen_connect.is_alive() == False:listen_connect.start()def disconnect():global serglobal need_listenglobal linsten_locklinsten_lock.acquire()need_listen = 0linsten_lock.release()#sleep(0.1)if ser.is_open == False:messagebox.showinfo(title="Error", message="Serial not connected!")else:try:ser.close()except Exception as e:messagebox.showinfo(title="Error", message=e)returnneed_listen = 0set_connect_logo(False)def cancel():global ymodem_senderif upgrade_button['state'] == 'disabled':ymodem_sender.abort()def upgrade():global upgrade_buttonif ser.is_open == False:messagebox.showinfo(title="Error", message="Please connect the serial first!")upgrade_button.configure(state='active')returnfile_list = filedialog.askopenfilenames(filetypes=[("bin file", "*.bin"),("all","*.*")])if len(file_list) <= 0:upgrade_button.configure(state='active')returnelse:ret_val = prepare_upgrade()if ret_val < 0:upgrade_button.configure(state='active')returnupgrade_button.configure(state='disabled')disconnect_button.configure(state='disabled')upgrade_thread = threading.Thread(target=do_upgrade,args = (file_list,))upgrade_thread.start()def show_progress_bar(show=True):if show:progress_bar.place(x=10,y=150)else:progress_bar.place_forget()progress_bar.coords(fill_line, (0, 0, 0, 30))progress_bar.delete('text')def serial_reconnect(baud_rate = 115200, timeout = 1):need_sleep = 1if  ser.baudrate == baud_rate:need_sleep = 0try:ser.timeout = timeoutser.baudrate = baud_rateser.close()ser.open()except Exception as e:raise Exception("Reconnect Fail")if need_sleep:sleep(1)def do_upgrade(file_list):global upgrade_buttonneed_listen = 0 sleep(1)baud_rate = baudratebox.get()try:serial_reconnect()except Exception as e:print(e)ser.write("\r".encode("utf-8"))ch_str = "upgrade -t 0 " + str(int(baud_rate)) + "\r"ser.write(ch_str.encode("utf-8"))sleep(1)for file in file_list:file_size = os.path.getsize(file)if file_size > 2*1024*1024:continuetry:serial_reconnect(baud_rate = int(baud_rate), timeout = 5)except Exception as e:print(e)show_progress_bar(True)if len(progress_bar.gettags("text")) == 0:progress_bar.create_text(175, 15, text=os.path.basename(file), tags="text")ser.read_all()ser.write("\r".encode("utf-8"))ser.write("upgrade -u\r".encode("utf-8"))while True:ch_str = ser.read(4).decode("utf-8")if ch_str == "CCCC":breakymodem_send(file)while True:if ser.read(1).decode("utf-8") == 'I':if ser.read(1).decode("utf-8") == 'E':if ser.read(1).decode("utf-8") == 'T':ymodem_sender.log.info("Receive IET")show_progress_bar(False)sleep(1)breakelse:continueelse:continueshow_progress_bar(False)try:ser.write("\r".encode("utf-8"))ser.write("upgrade -t 0 115200\r".encode("utf-8"))sleep(1)serial_reconnect()except Exception as e:print(e)upgrade_button.configure(state='active')disconnect_button.configure(state='active')need_listen = 1def ymodem_send(file):global ymodem_sendertry:file_stream = open(file, 'rb')except IOError as e:raise Exception("Open file fail!")file_name = os.path.basename(file)file_size = os.path.getsize(file)rate = baudratebox.get()try:serial_reconnect(baud_rate = int(rate), timeout=5)except Exception as e:messagebox.showinfo(title="Error", message="Connection error!")returntry:ymodem_sender.send(file_stream, file_name,file_size,callback=upgrade_callback)except Exception as e:file_stream.close()raisefile_stream.close()def prepare_upgrade():global serser.flushOutput()ser.flushInput()ser.write("\r".encode("utf-8"))ret_str = ser.read(1024).decode("utf-8")b_reset= Falseif ret_str.find("IET") == -1:try:serial_reconnect(baud_rate = 9600)b_reset = Trueexcept Exception as e:messagebox.showinfo(title="Error", message=e)return -1ser.read_all()ser.write("flash -u\r".encode("utf-8"))sleep(0.5)read_byte = ser.read_all()if len(read_byte) <= 3:b_reset = Trueelse:ret_str = read_byte[0:min(20,len(read_byte))].decode("utf-8")if ret_str.find("IET") != -1:b_reset = Trueelse:b_reset = Falseif b_reset:messagebox.showinfo(title="Tips", message="Please reset/reconnect board first, then press [OK]")sleep(0.5)serial_reconnect()return 0def sender_getc(size):return ser.read(size) or Nonedef sender_putc(data):send_data_mutex.acquire()ser.write(data)send_data_mutex.release()connect_button = Button(app, text="连接",width = 8,height = 1,command=connect)
disconnect_button = Button(app, text="断开",width = 8,height = 1,command=disconnect)
upgrade_button = Button(app, text="升级",width = 8,height = 1,command=upgrade)
cancel_button = Button(app, text="取消升级",width = 8,height = 1,command=cancel) 
listen_connect = threading.Thread(target=listen_connect_thread)
send_data_mutex = threading.Lock()
ymodem_sender = YMODEM(sender_getc, sender_putc)def init_layout():app.title("xx科技")app.iconbitmap(".\\xxxx.ico")app.geometry('400x200') app.protocol("WM_DELETE_WINDOW", on_closing)app.resizable(width=False, height=False)Label(app, text="端口:", font=('Arial', 14)).place(x=10, y=10)comportbox["value"] = ("COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","COM10")comportbox.current(2)comportbox.place(x=75, y=14)Label(app, text="波特率:", font=('Arial', 14)).place(x=200, y=10)baudratebox["value"] = ("9600","115200","230400","576000")baudratebox.current(1)baudratebox.place(x=285, y=14)connect_button.place(x=10,y=50)disconnect_button.place(x=10,y=100)cancel_button.place(x=285,y=50)upgrade_button.place(x=285,y=100)show_progress_bar(False)set_connect_logo(False)def main():init_layout()mainloop()def on_closing():exit_listen = Truesleep(0.4)try:ser.close()except Exception as e:print(e)pass app.destroy()if __name__ == '__main__':main()
# -*- coding: utf-8 -*-import logging
from time import sleep
logging.basicConfig(level = logging.DEBUG, format = '%(asctime)s - %(levelname)s - %(message)s')# ymodem data header byte
SOH = b'\x01'
STX = b'\x02'
EOT = b'\x04'
ACK = b'\x06'
NAK = b'\x15'
CAN = b'\x18'
CRC = b'C'class YMODEM(object):# initializedef __init__(self, getc, putc, mode='ymodem', header_pad=b'\x00', pad=b'\x1a'):self.getc = getcself.putc = putcself.mode = modeself.header_pad = header_padself.pad = padself.log = logging.getLogger('YReporter')# send abort(CAN) twicedef abort(self, count=2):for _ in range(count):self.putc(CAN)'''send entry'''def send(self, file_stream, file_name, file_size=0, retry=20, timeout=15, callback=None):try:packet_size = dict(ymodem = 1024,ymodem128 = 128)[self.mode]except KeyError:raise ValueError("Invalid mode specified: {self.mode!r}".format(self=self))self.log.debug('Begin start sequence')# Receive first charactererror_count = 0cancel = 0while True:char = self.getc(1)if char:if char == CRC:# Expected CRCself.log.info("<<< CRC")breakelif char == CAN:self.log.info("<<< CAN")if cancel:return Falseelse:cancel = 1else:self.log.error("send error, expected CRC or CAN, but got " + hex(ord(char)))error_count += 1if error_count > retry:self.abort()self.log.error("send error: error_count reached %d aborting", retry)return Falseheader = self._make_send_header(128, 0)name = bytes(file_name, encoding = "utf8")size = bytes(str(file_size),encoding = "utf8")data = name + b'\x00' + size + b'\x20'data = data.ljust(128, self.header_pad)checksum = self._make_send_checksum(data)data_for_send = header + data + checksumself.putc(data_for_send)#self.log.info("Packet 0 >>> " + str(len(data_for_send)))error_count = 0cancel = 0# Receive reponse of first packetwhile True:char = self.getc(1)if char:if char == ACK:self.log.info("<<< ACK")char2 = self.getc(1)if char2 == CRC:self.log.info("<<< CRC")breakelse:self.log.warn("ACK wasnt CRCd")breakelif char == CAN:self.log.info("<<< CAN")if cancel:return Falseelse:cancel = 1else:if (ord(char)) >= 0x20 and (ord(char)) <= 0x7e:self.log.error("test" + str(char))else:self.log.error("send error, expected ACK or CAN, but got " + hex(ord(char)))error_count = 0cancel = 0total_packets = 1sequence = 1sleep(1)while True:# Read raw data from file streamdata = file_stream.read(packet_size)if not data:self.log.debug('send: at EOF')breaktotal_packets += 1header = self._make_send_header(packet_size, sequence)data = data.ljust(packet_size, self.pad)checksum = self._make_send_checksum(data)while True:data_for_send = header + data + checksum# data_in_hexstring = "".join("%02x" % b for b in data_for_send)# Send file data packetself.putc(data_for_send)#self.log.info("Packet " + str(sequence) + " >>>" + str(len(data_for_send)))error_count = 0while True:char = self.getc(1)if char == ACK:breakelse:error_count += 1if error_count > retry:self.abort()return Falseerror_count = 0if char == ACK:# Expected response#self.log.info("<<< ACK")if callable(callback):callback(total_packets,file_size,file_name)error_count = 0breakerror_count += 1if error_count > retry:self.abort()self.log.error('send error: NAK received %d , aborting', retry)return Falsesequence = (sequence + 1) % 0x100# Send EOT and expect final ACKerror_count = 0while True:self.putc(EOT)self.log.info(">>> EOT")char = self.getc(1)if char == ACK:self.log.info("<<< ACK")breakelse:error_count += 1if error_count > retry:self.abort()self.log.warn('EOT wasnt ACKd, aborting transfer')return Falseheader = self._make_send_header(128, 0)data = bytearray(b'\x00')data = data.ljust(128, self.header_pad)checksum = self._make_send_checksum(data)data_for_send = header + data + checksumself.putc(data_for_send)error_count = 0while True:char = self.getc(1)if char == ACK :breakelse:error_count += 1if error_count > retry:self.abort()self.log.warn('SOH wasnt ACK, aborting transfer')return Falseself.log.info('Transmission successful (ACK received)')return True# Header bytedef _make_send_header(self, packet_size, sequence):assert packet_size in (128, 1024), packet_size_bytes = []if packet_size == 128:_bytes.append(ord(SOH))elif packet_size == 1024:_bytes.append(ord(STX))_bytes.extend([sequence, 0xff - sequence])return bytearray(_bytes)# Make check codedef _make_send_checksum(self, data):_bytes = []crc = self.calc_crc(data)_bytes.extend([crc >> 8, crc & 0xff])return bytearray(_bytes)def _verify_recv_checksum(self, data):_checksum = bytearray(data[-2:])their_sum = (_checksum[0] << 8) + _checksum[1]data = data[:-2]our_sum = self.calc_crc(data)valid = bool(their_sum == our_sum)return valid, data# For CRC algorithmcrctable = [0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,]# CRC algorithm: CCITT-0def calc_crc(self, data, crc=0):for char in bytearray(data):crctbl_idx = ((crc >> 8) ^ char) & 0xffcrc = ((crc << 8) ^ self.crctable[crctbl_idx]) & 0xffffreturn crc & 0xffffif __name__ == '__main__':pass

参考:
https://blog.csdn.net/u012993936/article/details/125102816
https://blog.csdn.net/gitblog_00099/article/details/137135096
https://blog.csdn.net/xuyinxin/article/details/104174587
https://github.com/alexwoo1900/ymodem.git

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

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

相关文章

Python | Leetcode Python题解之第89题格雷编码

题目&#xff1a; 题解&#xff1a; class Solution:def grayCode(self, n: int) -> List[int]:ans [0] * (1 << n)for i in range(1 << n):ans[i] (i >> 1) ^ ireturn ans

如何在云电脑实现虚拟应用—数据分层(应用分层)技术简介

如何在云电脑实现虚拟应用—数据分层&#xff08;应用分层&#xff09;技术简介 近几年虚拟化市场实现了非常大的发展&#xff0c;桌面虚拟化在企业中应用越来越广泛&#xff0c;其拥有的如下优点得到大量企业的青睐&#xff1a; 数据安全不落地。在虚拟化环境下面数据保存在…

STL库简介

一、STL库的概念 STL&#xff1a;是C标准库的重要追组成部分&#xff0c;不仅是一个可以复用的组件库&#xff0c;而且还是一个包含了数据结构和算法的软件框架。 二、STL的版本 原始版本 Alexander Stepanov、 Meng Lee 在惠普实验室完成的原始版本&#xff0c; 是一个开源…

JVM 双亲委派机制详解

文章目录 1. 双亲委派机制2. 证明3. 优势与劣势 1. 双亲委派机制 类加载器用来把类加载到 Java 虚拟机中。从JDK1.2版本开始&#xff0c;类的加载过程采用双亲委派机制&#xff0c;这种机制能更好地保证 Java 平台的安全。 1.定义 如果一个类加载器在接到加载类的请求时&…

(done) NLP+HMM 协作,还有维特比算法

参考视频&#xff1a;https://www.bilibili.com/video/BV1aP4y147gA/?p2&spm_id_frompageDriver&vd_source7a1a0bc74158c6993c7355c5490fc600 &#xff08;这实际上是 “序列标注任务”&#xff09; HMM 的训练和预测如下图 训练过程&#xff1a;我们首先先给出一个语…

web学习记录--(5.14)

1.Sublime安装与汉化 直接点击windows即可下载&#xff0c;安装即可 Thank You - Sublime Text 汉化 Install Package ChineseLocalzation 2.PHPstorm下载以及激活,汉化 直接下载&#xff0c;然后找激活码激活即可 汉化 plugins&#xff08;插件&#xff09;/chinese&…

SpringBoot接收参数的19种方式

https://juejin.cn/post/7343243744479625267?share_token6D3AD82C-0404-47A7-949C-CA71F9BC9583

未授权访问:ZooKeeper 未授权访问漏洞

目录 1、漏洞原理 2、环境搭建 3、未授权访问 防御手段 今天继续学习各种未授权访问的知识和相关的实操实验&#xff0c;一共有好多篇&#xff0c;内容主要是参考先知社区的一位大佬的关于未授权访问的好文章&#xff0c;还有其他大佬总结好的文章&#xff1a; 这里附上大…

2025年第十一届北京国际印刷技术展览会

2025年第十一届北京国际印刷技术展览会 展览时间&#xff1a;2025年5月15-19日 展览地点&#xff1a;北京中国国际展览中心&#xff08;顺义馆&#xff09; 主办单位&#xff1a;中国印刷及设备器材工业协会中国国际展览中心集团有限公司 承办单位&#xff1a;北京中印协华港国…

海思Hi3065H 200MHz 高性能 RISCV32 A² MCU

这是一款海思自研的RISCV32内核的高性能实时控制专用MCU&#xff0c; 具有高性能、高集成度、高可靠性、易开发的特点&#xff0c;同时还有嵌入式AI能力。 CPU • RISC-V200MHzFPU 存储 • Up to 152KB Code Flash • 8KB Data Flash • 16KB SRAM 个人认为这是MCU梯队非常…

【PB案例学习笔记】-02 目录浏览器

写在前面 这是PB案例学习笔记系列文章的第二篇&#xff0c;该系列文章适合具有一定PB基础的读者&#xff0c; 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上…

基于Django实现的(bert)深度学习文本相似度检测系统设计

基于Django实现的&#xff08;bert&#xff09;深度学习文本相似度检测系统设计 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系统功能实现 登录页面 注册页面&#xff1a;用户账号&#xff0c;密码…

05-14 周二 PyTorch动态量化和静态量化理解

05-14 周二 PyTorch动态量化和静态量化理解 时间版本修改人描述2024年5月14日10:44:30V0.1宋全恒新建文档2024年5月14日16:28:16V1.0宋全恒填充了PyTorch对于两种量化方式的内容 简介 Pytorch动态量化 设计神经网络时&#xff0c;可以进行许多权衡。在模型开发和训练期间&…

Dilworth定理:最少的下降序列个数就等于整个序列最长上升子序列的长度

概念如下&#xff1a; 狄尔沃斯定理_百度百科 (baidu.com) 本质就是找要求序列中最长的单调的子序列&#xff08;不一定连续&#xff09;的长度。 模板如下&#xff1a; 时间复杂度为O&#xff08;N^2&#xff09; #include<iostream>using namespace std;int dp[100…

RK3568平台开发系列讲解(SPI篇)SPI数据的传输

🚀返回专栏总目录 文章目录 一、数据结构1.1、spi_transfer 结构体1.2、spi_message二、数据发送程序分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 参考资料: spi_transferspi_message一、数据结构 spi 数据传输主要使用了 spi_message 和 spi_transfer 结构…

二叉树的前序遍历(leetcode)

144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 这道题的启发性真的很强 &#xff0c;这里必须传入i的指针进去&#xff0c;下一次栈帧i&#xff0c;但回到了上一层i又变回到了原来的i&#…

docker network ls(用于列出 Docker 主机上的所有网络)

docker network ls 是一个 Docker 命令&#xff0c;用于列出 Docker 主机上的所有网络。Docker 允许你创建自定义的网络&#xff0c;以便更好地控制容器之间的通信。 当你运行 docker network ls 命令时&#xff0c;你可能会看到如下类似的输出&#xff08;输出可能会根据你的…

每日一题12:Pandas:数据重塑-融合

一、每日一题 解答&#xff1a; import pandas as pddef meltTable(report: pd.DataFrame) -> pd.DataFrame:reshaped_report report.melt(id_varsproduct, var_namequarter, value_namesales)return reshaped_report 题源&#xff1a;Leetcode 二、总结 melt()函数是Pa…

Nginx生产环境最佳实践之配置灰度环境

你好呀&#xff0c;我是赵兴晨&#xff0c;文科程序员。 下面的内容可以说是干货满满建议先收藏再慢慢细品。 今天&#xff0c;我想与大家深入探讨一个我们日常工作中不可或缺的话题——灰度环境。你是否在工作中使用过灰度环境&#xff1f;如果是&#xff0c;你的使用体验如…

AI图像生成-基本步骤

模型板块 1、新建采样器&#xff1a;新建节点-》采样器-》K采样器 2、拖动模型节点后放开&#xff0c;选择checkpoint加载器&#xff08;简易&#xff09;&#xff0c;模型新建成功 提示词板块 1、拖动正面条件节点后放开&#xff0c;选择CLIP文本编码器&#xff0c;模型新建…