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

可视化网站建设wordpress导入用户数据库

可视化网站建设,wordpress导入用户数据库,丽水微信网站建设报价,四川手机网站前言在嵌入式软件开发中#xff0c;硬件初始化与寄存器配置长期依赖人工编写重复代码。以STM32外设初始化为例#xff0c;开发者需手动完成时钟使能、引脚模式设置、参数配置等步骤#xff0c;不仅耗时易错#xff08;如位掩码写反、模式枚举值混淆#xff09;#xff0c…前言在嵌入式软件开发中硬件初始化与寄存器配置长期依赖人工编写重复代码。以STM32外设初始化为例开发者需手动完成时钟使能、引脚模式设置、参数配置等步骤不仅耗时易错如位掩码写反、模式枚举值混淆更因代码冗余导致维护成本高——修改一个外设参数可能需同步调整多处代码稍有不慎便引发硬件异常。当看到同事通过GUI配置自动生成底层代码后其效率提升让我意识到传统手写代码文档的模式已难以适应复杂嵌入式系统的开发需求。为此我简要探索了一下​​配置即代码Configuration-as-Code​​方案目标是通过结构化配置文件与自动化工具链实现零手写代码生成高质量嵌入式初始化代码同时兼顾可维护性与灵活性。技术选型与核心架构针对嵌入式开发的特殊性配置工具需满足三大核心需求​​严格的Schema验证机制​​确保配置文件符合硬件约束如引脚复用冲突、参数取值范围从源头避免无效配置​​树形结构清晰表达层级​​映射硬件物理层级的嵌套关系如外设→端口→引脚→参数提升配置文件的可读性与可维护性​​注释能力便于维护​​支持多语言注释如中文硬件说明、英文API提示降低团队协作与后续迭代的沟通成本。架构分层设计工具采用配置模型-数据绑定-代码生成三层架构如图1所示​​配置模型层​​基于XML SchemaXSD定义标准化配置结构约束各字段的取值范围与层级关系​​数据绑定层​​通过双向数据绑定机制实现UI操作与XML配置的实时同步​​代码生成层​​根据目标平台如STM32系列的HAL库规范将XML配置转换为平台相关的初始化代码。关键技术实现UI与XML的实时绑定UI状态与XML数据模型通过​​双向数据绑定​​实现同步当用户在UI修改GPIO0模式为输出时XML中gpio id0mode节点的值立即更新为输出当通过脚本修改XML中gpio id1pull节点为下拉时UI中对应引脚的下拉框会自动选中下拉选项。示例XMLSTM32_GPIO配置片段​​ stm32_gpio_config version1.0gpio id0pinPA0/pinmode输入/modeoutput_typeN/A/output_typespeedN/A/speedpull上拉/pull/gpiogpio id1pinPA1/pinmode输出/modeoutput_type推挽/output_typespeed中速/speedpull无/pull/gpiogpio id2pinPA2/pinmode复用/modeoutput_type开漏/output_typespeed中速/speedpull无/pull/gpio /stm32_gpio_config自动转换逻辑在代码生成阶段根据目标平台选择对应的映射规则将通用配置转换为平台特定的HAL库参数。例如当目标平台为STM32F1时配置中的“输出”、“推挽”会自动替换为GPIO_Mode_Out_PP避免手动修改错误。双向同步机制为支持遗留项目改造工具提供​​代码→XML的双向同步​​能力​​GUI→代码​​用户在UI的修改实时生成符合HAL库规范的初始化代码如MX_GPIO_Init函数直接替换手写代码​​代码→GUI​​通过静态代码分析工具解析现有工程的HAL库初始化代码如提取GPIO_InitStruct.GPIO_Mode的值逆向生成XML配置快速实现遗留项目的可视化改造。端口聚合优化减少冗余寄存器操作传统手写代码中每个外设引脚的初始化需单独调用GPIO_Init函数导致大量重复的寄存器操作如多次使能同一端口的时钟。我们的工具通过​​端口聚合优化​​将同端口的配置合并显著减少代码冗余并提升执行效率。优化前手写代码 // 传统手写代码示例STM32F103 GPIO初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 时钟使能 GPIO_InitTypeDef GPIO_InitStruct;// PA0配置输入浮空 GPIO_InitStruct.GPIO_Pin GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStruct);// PA1配置输出推挽 GPIO_InitStruct.GPIO_Pin GPIO_Pin_1; GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_PP; GPIO_Init(GPIOA, GPIO_InitStruct);// PA2配置复用开漏 GPIO_InitStruct.GPIO_Pin GPIO_Pin_2; GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; GPIO_Init(GPIOA, GPIO_InitStruct);优化后工具生成代码 /* 自动生成的STM32F103 GPIO初始化代码 */ #include stm32f10x.h// 合并时钟使能仅调用1次 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);// 按端口聚合配置仅调用3次GPIO_Init覆盖所有引脚 GPIO_InitTypeDef GPIO_InitStruct_0; GPIO_InitStruct_0.GPIO_Pin GPIO_Pin_0; GPIO_InitStruct_0.GPIO_Mode GPIO_Mode_IN_FLOATING; // PA0输入浮空 GPIO_Init(GPIOA, GPIO_InitStruct_0);GPIO_InitTypeDef GPIO_InitStruct_1; GPIO_InitStruct_1.GPIO_Pin GPIO_Pin_1; GPIO_InitStruct_1.GPIO_Mode GPIO_Mode_Out_PP; // PA1输出推挽 GPIO_Init(GPIOA, GPIO_InitStruct_1);GPIO_InitTypeDef GPIO_InitStruct_2; GPIO_InitStruct_2.GPIO_Pin GPIO_Pin_2; GPIO_InitStruct_2.GPIO_Mode GPIO_Mode_AF_PP; // PA2复用开漏 GPIO_Init(GPIOA, GPIO_InitStruct_2);展望这次探索自动代码生成的经历本质上是一次对开发流程智能化的小范围实践。通过引入XML/JSON这样的中间配置文件作为意图载体我把原本固化的代码生成逻辑变成了可维护、可追溯的结构化数据不仅解决了重复编码的效率问题还摸索出一套配置驱动开发的轻量级方法。过程中几个关键收获值得好好总结首先是​​配置文件的标准化设计​​。XML/JSON的可扩展性和语义明确性让它们既能描述复杂业务规则比如条件分支、动态组件加载又能通过版本控制工具如Git追踪配置变更方便团队协作和回滚。未来如果能结合领域特定语言DSL进一步抽象配置语法配置的可读性和表达能力应该还能提升。其次是​​AI辅助工具链的价值​​。传统工具链里开发者得同时懂配置语法、生成逻辑和调试技巧但在AI的帮助下我只需要说清楚业务需求AI就能自动补全配置细节、生成符合规范的代码还能根据运行反馈定位问题。这种需求到代码的智能映射正在模糊开发者和工具的边界推动开发角色向需求架构师转变。最后是​​自动化生成的边界​​。自动代码生成最适合模式化、低风险、高重复的任务而不是替代开发者的创造性工作。未来的工具链应该更注重人机协同——AI处理标准化部分开发者聚焦创新和灵活需求形成分层协作的生态。以上是AI生成的文章以下才是我想表达的之前在用ST单片机时我一直是用标准库来写代码对每一行代码的细节都要了解清楚对未知的代码就特别想了解清楚。最开始接触到自动代码生成是大学时了解到CubeMX只需要在GUI界面配置IO端口配置时钟树。当时对这个功能其实也不算很震惊甚至感觉不过如此可能是因为了解得太少吧。不过我还是查了很多文章差不多是为什么ST官方要推出CubeMX、HAL库有什么优势。最近工作时我发现同事在用自动代码生成工具这才是真正震惊到我的地方因为它就实实在在发生在我的身边。我也明白了为什么经常有人调侃自己是码农因为有些代码的编写真的跟搬砖没区别只不过门槛高一些罢了。有了AI后其实很多重复性的代码都不需要人来开发而我们的核心价值也就在创造性上面文学艺术创作除外哭笑在于人的主观能动性至少在我所从事的汽车电子行业是这样。最近也大概了解了自动代码生成了解相关技术及工具最开始无从下手也是边问AI边了解慢慢深入。后面在QtCreater和PyQt、JSON和XML之间均选择了后者。今天趁着周末外面还在下雨能安心下来初探嵌入式软件配置工具自动代码生成。我让AI帮我生成代码时间从早上10点一直到晚上10点。离谱的是后面的代码我基本上是看不懂了但我还是通过表达我的想法让AI生成代码我在PyCharm上调试将问题反馈给AI一直在迭代整个过程有点像在训练AI模型。到后面代码超过500行时整个AI思考和推理生成代码的时间特别久最长需要5分钟不过最终也实现了基础功能。嵌入式软件配置自动生成代码核心思想就是下面这张图。以我现有水平和精力将代码逆向解析成数据结构有点难度所以还没实现。不过整个流程基本上是跑通了也完成了核心的工作。最后AI生成的效果属实是有点意料之外没想到能做得这么好。 /* 自动生成的STM32F103 GPIO初始化代码 */ #include stm32f10x.hRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOPA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);/* GPIO初始化配置 */ GPIO_InitTypeDef GPIO_InitStruct_0; GPIO_InitStruct_0.GPIO_Pin GPIO_Pin_0; GPIO_InitStruct_0.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_InitStruct_0.GPIO_PuPd GPIO_PuPd_NOPULL;GPIO_InitTypeDef GPIO_InitStruct_1; GPIO_InitStruct_1.GPIO_Pin GPIO_Pin_1; GPIO_InitStruct_1.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStruct_1.GPIO_Speed GPIO_Speed_10MHz;GPIO_InitTypeDef GPIO_InitStruct_2; GPIO_InitStruct_2.GPIO_Pin GPIO_Pin_2; GPIO_InitStruct_2.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStruct_2.GPIO_Speed GPIO_Speed_10MHz; GPIO_InitStruct_2.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitTypeDef GPIO_InitStruct_3; GPIO_InitStruct_3.GPIO_Pin GPIO_Pin_3; GPIO_InitStruct_3.GPIO_Mode GPIO_Mode_AIN; GPIO_InitStruct_3.GPIO_PuPd GPIO_PuPd_NOPULL;/* 初始化所有GPIO */ GPIO_Init(GPIOPA, GPIO_InitStruct_0); GPIO_Init(GPIOPA, GPIO_InitStruct_1); GPIO_Init(GPIOPA, GPIO_InitStruct_2); GPIO_Init(GPIOPA, GPIO_InitStruct_3);/* 初始化完成 */完整代码放在下面 import sys import re import os import xml.etree.ElementTree as ET from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QLabel, QComboBox, QPushButton, QFileDialog, QMessageBox,QScrollArea) from PyQt6.QtCore import Qt from PyQt6.QtGui import QFontclass STM32GPIOConfigTool(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle(STM32F103 GPIO配置工具 (增强版))self.setGeometry(100, 100, 900, 650)# 设置应用样式self.setStyleSheet(QMainWindow {background-color: #F5F5F5;}QLabel {font-weight: bold;}QPushButton {background-color: #4CAF50;color: white;border: none;padding: 8px 16px;border-radius: 4px;font-weight: bold;}QPushButton:hover {background-color: #45a049;}QPushButton:pressed {background-color: #3d8b40;}QComboBox {padding: 4px;border: 1px solid #ccc;border-radius: 4px;}QScrollArea {background-color: white;border: none;}QWidget#config_row {background-color: white;border-radius: 6px;padding: 8px;margin: 4px;border: 1px solid #E0E0E0;})# 初始化数据存储self.gpio_configs [] # 存储有效配置含引脚、模式等self.used_pins set() # 记录已使用的引脚防止重复# 主布局main_widget QWidget()self.setCentralWidget(main_widget)main_layout QVBoxLayout(main_widget)main_layout.setSpacing(15)main_layout.setContentsMargins(15, 15, 15, 15)# 标题title_label QLabel(STM32F103 GPIO配置工具 (增强版))title_label.setFont(QFont(Arial, 16, QFont.Weight.Bold))title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)main_layout.addWidget(title_label)# 操作按钮区域btn_layout QHBoxLayout()btn_layout.setSpacing(10)self.btn_add QPushButton(添加引脚配置)self.btn_add.clicked.connect(self.add_gpio_row)self.btn_import QPushButton(导入XML配置)self.btn_import.clicked.connect(self.import_xml)self.btn_save_xml QPushButton(保存XML配置)self.btn_save_xml.clicked.connect(self.save_xml)self.btn_generate QPushButton(生成STM32 HAL代码)self.btn_generate.clicked.connect(self.generate_code)btn_layout.addWidget(self.btn_add)btn_layout.addWidget(self.btn_import)btn_layout.addWidget(self.btn_save_xml)btn_layout.addWidget(self.btn_generate)main_layout.addLayout(btn_layout)# 配置区域标题config_title QLabel(GPIO引脚配置)config_title.setFont(QFont(Arial, 12, QFont.Weight.Bold))main_layout.addWidget(config_title)# 滚动区域支持多行滚动self.scroll_area QScrollArea()self.scroll_area.setWidgetResizable(True)self.scroll_content QWidget()self.gpio_layout QVBoxLayout(self.scroll_content)self.gpio_layout.setSpacing(10)self.gpio_layout.setContentsMargins(10, 10, 10, 10)self.scroll_area.setWidget(self.scroll_content)main_layout.addWidget(self.scroll_area)# 添加初始行self.add_gpio_row()def add_gpio_row(self):添加新行并自动分配未使用的GPIO优化PA0优先try:# 创建行部件row_widget QWidget()row_widget.setObjectName(config_row)row_layout QHBoxLayout(row_widget)row_layout.setContentsMargins(10, 10, 10, 10)row_layout.setSpacing(15)# 引脚选择PA0-PB15pin_label QLabel(引脚:)pin_combo QComboBox()pin_combo.addItems([fPA{i} for i in range(16)] [fPB{i} for i in range(16)])row_layout.addWidget(pin_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(pin_combo, 1)# 模式选择输入/输出/复用/模拟mode_label QLabel(模式:)mode_combo QComboBox()mode_combo.addItems([输入, 输出, 复用, 模拟])row_layout.addWidget(mode_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(mode_combo, 1)# 输出类型仅输出/复用模式有效type_label QLabel(输出类型:)type_combo QComboBox()type_combo.addItems([推挽, 开漏])type_combo.setEnabled(False)row_layout.addWidget(type_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(type_combo, 1)# 速度等级仅输出/复用模式有效speed_label QLabel(速度:)speed_combo QComboBox()speed_combo.addItems([低速, 中速, 高速, 最高速])speed_combo.setEnabled(False)row_layout.addWidget(speed_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(speed_combo, 1)# 上下拉电阻仅输入/模拟模式有效pull_label QLabel(上下拉:)pull_combo QComboBox()pull_combo.addItems([无, 上拉, 下拉])pull_combo.setCurrentText(无)row_layout.addWidget(pull_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(pull_combo, 1)# 行内删除按钮del_btn QPushButton(删除)del_btn.setFixedSize(80, 30)del_btn.setStyleSheet(QPushButton {background-color: #f44336;color: white;border-radius: 4px;font-weight: bold;}QPushButton:hover {background-color: #d32f2f;}QPushButton:pressed {background-color: #b71c1c;})del_btn.clicked.connect(lambda: self.remove_gpio_row(row_widget))row_layout.addWidget(del_btn, 0, Qt.AlignmentFlag.AlignRight)# 绑定事件mode_combo.currentTextChanged.connect(lambda mode, tctype_combo, scspeed_combo, pcpull_combo:self.toggle_gpio_options(mode, tc, sc, pc))pin_combo.currentTextChanged.connect(lambda text, rwrow_widget: self.on_pin_selected(text, rw))# 自动分配未使用的引脚优化优先PA0available_pins self._get_unused_pins()if available_pins:selected_pin available_pins[0] # 优先PA0pin_combo.setCurrentText(selected_pin)self.used_pins.add(selected_pin) # 标记为已使用else:QMessageBox.warning(self, 警告, 所有GPIO引脚已被使用)return# 初始化配置对象config {widget: row_widget,pin_combo: pin_combo,mode_combo: mode_combo,type_combo: type_combo,speed_combo: speed_combo,pull_combo: pull_combo,pin: pin_combo.currentText(),index: len(self.gpio_configs)}self.gpio_configs.append(config)# 添加行到布局self.gpio_layout.addWidget(row_widget)# 设置初始模式为输入mode_combo.setCurrentText(输入)except Exception as e:QMessageBox.critical(self, 错误, f添加行失败{str(e)})if row_widget in locals():row_widget.deleteLater()def _get_unused_pins(self):获取所有未使用的GPIO引脚PA0优先all_pins [fPA{i} for i in range(16)] [fPB{i} for i in range(16)]unused [p for p in all_pins if p not in self.used_pins]# 优先PA0如果有if PA0 in unused:return [PA0] [p for p in unused if p ! PA0]return unuseddef remove_gpio_row(self, row_widget):删除行并释放对应引脚try:# 查找对应的配置for i, cfg in enumerate(self.gpio_configs):if cfg[widget] row_widget:# 释放引脚if cfg[pin] in self.used_pins:self.used_pins.remove(cfg[pin])# 移除配置self.gpio_configs.pop(i)break# 从布局移除部件self.gpio_layout.removeWidget(row_widget)row_widget.deleteLater()except Exception as e:QMessageBox.critical(self, 错误, f删除行失败{str(e)})def on_pin_selected(self, selected_pin, row_widget):引脚选择实时检测重复/格式校验try:# 查找对应的配置config Nonefor cfg in self.gpio_configs:if cfg[widget] row_widget:config cfgbreakif not config:return# 清除之前的错误状态row_widget.setStyleSheet()# 校验1引脚格式是否合法if not re.fullmatch(r^PA\d{1,2}$|^PB\d{1,2}$, selected_pin):row_widget.setStyleSheet(background-color: #FFCCCC;)QMessageBox.warning(self, 警告, 无效引脚格式请使用PA0-PA15或PB0-PB15)# 重置为之前的有效选择config[pin_combo].setCurrentText(config[pin])return# 校验2引脚是否已被使用排除自身other_used [cfg for cfg in self.gpio_configsif cfg[pin] selected_pin and cfg ! config]if other_used:row_widget.setStyleSheet(background-color: #FFCCCC;)QMessageBox.warning(self, 警告, f引脚 {selected_pin} 已被使用请选择其他引脚)# 重置为之前的有效选择config[pin_combo].setCurrentText(config[pin])return# 更新配置old_pin config[pin]config[pin] selected_pin# 更新使用记录if old_pin in self.used_pins:self.used_pins.remove(old_pin)self.used_pins.add(selected_pin)# 触发模式相关控件状态更新self.toggle_gpio_options(config[mode_combo].currentText(),config[type_combo],config[speed_combo],config[pull_combo])except Exception as e:QMessageBox.critical(self, 错误, f引脚检查失败{str(e)})def toggle_gpio_options(self, mode, type_combo, speed_combo, pull_combo):根据模式控制控件状态is_input mode 输入is_analog mode 模拟is_output_remap mode in [输出, 复用]# 控制上下拉pull_combo.setEnabled(is_input or is_analog)if is_analog:pull_combo.setCurrentText(无)pull_combo.setEnabled(False)# 控制输出类型和速度仅输出/复用模式type_combo.setEnabled(is_output_remap)speed_combo.setEnabled(is_output_remap)# 输出/复用模式下禁用上下拉if is_output_remap:pull_combo.setEnabled(False)pull_combo.setCurrentText(无)def save_xml(self):保存XML配置try:# 检查重复引脚if not self._check_duplicates():return# 构建XMLroot ET.Element(stm32_gpio_config, version1.0)for idx, cfg in enumerate(self.gpio_configs):gpio_elem ET.SubElement(root, gpio, idstr(idx))ET.SubElement(gpio_elem, pin).text cfg[pin]ET.SubElement(gpio_elem, mode).text cfg[mode_combo].currentText()if cfg[mode_combo].currentText() in [输出, 复用]:ET.SubElement(gpio_elem, output_type).text cfg[type_combo].currentText()ET.SubElement(gpio_elem, speed).text cfg[speed_combo].currentText()ET.SubElement(gpio_elem, pull).text 无else:ET.SubElement(gpio_elem, output_type).text N/AET.SubElement(gpio_elem, speed).text N/AET.SubElement(gpio_elem, pull).text cfg[pull_combo].currentText()# 保存文件file_path, _ QFileDialog.getSaveFileName(self, 保存XML, gpio_config.xml, XML文件 (*.xml))if not file_path:returnos.makedirs(os.path.dirname(file_path), exist_okTrue)with open(file_path, w, encodingutf-8) as f:f.write(?xml version1.0 encodingutf-8?\n)f.write(ET.tostring(root, encodingutf-8, methodxml).decode(utf-8))QMessageBox.information(self, 成功, fXML已保存至{file_path})except Exception as e:QMessageBox.critical(self, 错误, f保存XML失败{str(e)})def _check_duplicates(self):检查重复引脚pins [cfg[pin] for cfg in self.gpio_configs]duplicates set([pin for pin in pins if pins.count(pin) 1])if duplicates:error_msg 发现重复引脚\nfor pin in duplicates:indices [str(i 1) for i, cfg in enumerate(self.gpio_configs) if cfg[pin] pin]error_msg f{pin}行 {, .join(indices)}\nQMessageBox.warning(self, 错误, error_msg)return False# 清除所有错误背景for cfg in self.gpio_configs:cfg[widget].setStyleSheet()return Truedef import_xml(self):导入XML配置try:file_path, _ QFileDialog.getOpenFileName(self, 导入XML, , XML文件 (*.xml))if not file_path:return# 清空当前配置self._clear_configs()# 解析XMLtree ET.parse(file_path)root tree.getroot()if root.tag ! stm32_gpio_config:QMessageBox.warning(self, 警告, 无效的STM32 GPIO配置文件)return# 遍历所有gpio节点for gpio_node in root.findall(gpio):# 解析节点pin gpio_node.find(pin).text.strip() if gpio_node.find(pin) is not None else mode gpio_node.find(mode).text.strip() if gpio_node.find(mode) is not None else output_type gpio_node.find(output_type).text.strip() if gpio_node.find(output_type) is not None else N/Aspeed gpio_node.find(speed).text.strip() if gpio_node.find(speed) is not None else N/Apull gpio_node.find(pull).text.strip() if gpio_node.find(pull) is not None else 无# 添加新配置config {widget: None,pin_combo: None,mode_combo: None,type_combo: None,speed_combo: None,pull_combo: None,pin: pin,mode: mode,output_type: output_type,speed: speed,pull: pull,index: len(self.gpio_configs)}self.gpio_configs.append(config)self.used_pins.add(pin)# 创建行控件for cfg in self.gpio_configs:self._add_gpio_row_from_config(cfg)QMessageBox.information(self, 导入成功, f成功导入 {len(self.gpio_configs)} 个配置)except Exception as e:QMessageBox.critical(self, 导入失败, f导入XML失败{str(e)})def _clear_configs(self):清空当前配置# 删除所有行部件for i in reversed(range(self.gpio_layout.count())):widget self.gpio_layout.itemAt(i).widget()if widget:widget.deleteLater()# 清空配置列表和使用记录self.gpio_configs.clear()self.used_pins.clear()def _add_gpio_row_from_config(self, config):从配置创建行控件try:row_widget QWidget()row_widget.setObjectName(config_row)row_layout QHBoxLayout(row_widget)row_layout.setContentsMargins(10, 10, 10, 10)row_layout.setSpacing(15)# 引脚选择pin_label QLabel(引脚:)pin_combo QComboBox()pin_combo.addItems([fPA{i} for i in range(16)] [fPB{i} for i in range(16)])pin_combo.setCurrentText(config[pin])row_layout.addWidget(pin_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(pin_combo, 1)# 模式选择mode_label QLabel(模式:)mode_combo QComboBox()mode_combo.addItems([输入, 输出, 复用, 模拟])mode_combo.setCurrentText(config.get(mode, 输入))row_layout.addWidget(mode_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(mode_combo, 1)# 输出类型type_label QLabel(输出类型:)type_combo QComboBox()type_combo.addItems([推挽, 开漏])type_combo.setCurrentText(config.get(output_type, 推挽))type_combo.setEnabled(False)row_layout.addWidget(type_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(type_combo, 1)# 速度speed_label QLabel(速度:)speed_combo QComboBox()speed_combo.addItems([低速, 中速, 高速, 最高速])speed_combo.setCurrentText(config.get(speed, 低速))speed_combo.setEnabled(False)row_layout.addWidget(speed_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(speed_combo, 1)# 上下拉pull_label QLabel(上下拉:)pull_combo QComboBox()pull_combo.addItems([无, 上拉, 下拉])pull_combo.setCurrentText(config.get(pull, 无))row_layout.addWidget(pull_label, 0, Qt.AlignmentFlag.AlignRight)row_layout.addWidget(pull_combo, 1)# 删除按钮del_btn QPushButton(删除)del_btn.setFixedSize(80, 30)del_btn.setStyleSheet(QPushButton {background-color: #f44336;color: white;border-radius: 4px;font-weight: bold;}QPushButton:hover {background-color: #d32f2f;}QPushButton:pressed {background-color: #b71c1c;})del_btn.clicked.connect(lambda: self.remove_gpio_row(row_widget))row_layout.addWidget(del_btn, 0, Qt.AlignmentFlag.AlignRight)# 绑定事件mode_combo.currentTextChanged.connect(lambda mode, tctype_combo, scspeed_combo, pcpull_combo:self.toggle_gpio_options(mode, tc, sc, pc))pin_combo.currentTextChanged.connect(lambda text, rwrow_widget: self.on_pin_selected(text, rw))# 保存配置config[widget] row_widgetconfig[pin_combo] pin_comboconfig[mode_combo] mode_comboconfig[type_combo] type_comboconfig[speed_combo] speed_comboconfig[pull_combo] pull_combo# 添加行到布局self.gpio_layout.addWidget(row_widget)# 设置模式以更新控件状态mode_combo.currentTextChanged.emit(mode_combo.currentText())except Exception as e:QMessageBox.critical(self, 错误, f创建行失败{str(e)})def generate_code(self):生成STM32 HAL代码try:# 检查重复引脚if not self._check_duplicates():return# 准备代码模板code [/* 自动生成的STM32F103 GPIO初始化代码 */,#include \stm32f10x.h\\n]# 时钟使能rcc_groups set()for cfg in self.gpio_configs:pin cfg[pin]pin_group pin[:2] # PA/PBrcc fRCC_APB2Periph_GPIO{pin_group}rcc_groups.add(rcc)if rcc_groups:for rcc in rcc_groups:code.append(fRCC_APB2PeriphClockCmd({rcc}, ENABLE);)if any(cfg[mode_combo].currentText() 复用 for cfg in self.gpio_configs):code.append(RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);)code.append(\n/* GPIO初始化配置 */)PULL_MAP {无: GPIO_PuPd_NOPULL, 上拉: GPIO_PuPd_UP, 下拉: GPIO_PuPd_DOWN}SPEED_MAP {低速: GPIO_Speed_2MHz, 中速: GPIO_Speed_10MHz,高速: GPIO_Speed_50MHz, 最高速: GPIO_Speed_100MHz}MODE_MAP {输入: GPIO_Mode_IN_FLOATING,输出: GPIO_Mode_Out_PP,复用: GPIO_Mode_AF_PP,模拟: GPIO_Mode_AIN}for i, cfg in enumerate(self.gpio_configs):pin cfg[pin]pin_num int(.join(filter(str.isdigit, pin)))code.append(fGPIO_InitTypeDef GPIO_InitStruct_{i};)code.append(fGPIO_InitStruct_{i}.GPIO_Pin GPIO_Pin_{pin_num};)code.append(fGPIO_InitStruct_{i}.GPIO_Mode {MODE_MAP[cfg[mode_combo].currentText()]};)if cfg[mode_combo].currentText() in [输出, 复用]:code.append(fGPIO_InitStruct_{i}.GPIO_Speed {SPEED_MAP[cfg[speed_combo].currentText()]};)if cfg[mode_combo].currentText() 复用:code.append(fGPIO_InitStruct_{i}.GPIO_Mode GPIO_Mode_AF_PP;) # 复用推挽else:code.append(fGPIO_InitStruct_{i}.GPIO_PuPd {PULL_MAP[cfg[pull_combo].currentText()]};)code.append()code.append(\n/* 初始化所有GPIO */)for i, cfg in enumerate(self.gpio_configs):pin_group cfg[pin][:2]code.append(fGPIO_Init(GPIO{pin_group}, GPIO_InitStruct_{i});)code.append(\n/* 初始化完成 */)# 保存代码file_path, _ QFileDialog.getSaveFileName(self, 保存代码, STM32F103_GPIO.c, C文件 (*.c))if not file_path:returnos.makedirs(os.path.dirname(file_path), exist_okTrue)with open(file_path, w, encodingutf-8) as f:f.write(\n.join(code))QMessageBox.information(self, 成功, f代码已生成至{file_path})except Exception as e:QMessageBox.critical(self, 错误, f生成代码失败{str(e)})if __name__ __main__:app QApplication(sys.argv)tool STM32GPIOConfigTool()tool.show()sys.exit(app.exec()) 以下是迭代过程
http://www.zqtcl.cn/news/955081/

相关文章:

  • 怎么把网站链接做二维码app跟网站的区别是什么
  • 南通住房和城乡建设局网站wordpress exif
  • 在谷歌上做网站广告要多少钱萍乡网站开发
  • 资源站 wordpress仙游县住房和城乡建设局网站
  • 锦州做网站公司北京互联网公司名单
  • 免费英文 网站模板公司做网站多少钱乐器
  • 软文营销推广成都seo正规优化
  • soho建设外贸网站怎样取消网站备案
  • 建设部网站实名制举报wordpress.org去掉
  • 网站地址ip域名查询公司网站建设安全的风险
  • 盐城建设厅网站设计备案网站创建服务
  • wp如何做双语网站个人网站首页内容
  • 网络推广网站排行榜百度怎么搜索网址打开网页
  • 网站制作和如何推广深圳西乡
  • 男生女生做污事网站免费西安企业展厅设计公司
  • 做网络写手最好进那个网站网页建站需要多少钱
  • 网站打开不对摄影设计说明200字
  • 无锡网站制作公司排名网站开发与应用 大作业作业
  • 网站建设中搜索引擎wordpress 不在首页显示文章
  • 先做网站先备案嘉兴网站建设推广
  • 建设法律法规文本查询网站Html手机浏览网站变形
  • 怎么拥有个人网站wordpress做的网站
  • wordpress建什么站江苏网站建设效果
  • 建设网站网站多少钱东莞网站建设 光龙
  • 天津和平做网站哪家好搞笑网站建设目的和意义
  • 一般做网站带宽选择多大的wordpress页面侧菜单
  • 海淀青岛网站建设友情链接适用网站
  • 青海建设厅官方网站资阳seo
  • 网站个人备案 企业备案深圳高端网站建设网页设计
  • 网站广东省备案国产最好的a级suv88814