mirror of
https://github.com/goldenfishs/MRobot.git
synced 2026-02-04 18:00:19 +08:00
Compare commits
No commits in common. "843936525ffaaba73d9efb2435c55ccdea853724" and "4a3e0d8391f0720ed5f129dcad3d96ac090acf69" have entirely different histories.
843936525f
...
4a3e0d8391
@ -2,11 +2,8 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QStackedWidget, QSizePolicy
|
|||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from qfluentwidgets import PushSettingCard, FluentIcon, TabBar
|
from qfluentwidgets import PushSettingCard, FluentIcon, TabBar
|
||||||
from qfluentwidgets import TitleLabel, BodyLabel, PushButton, FluentIcon
|
from qfluentwidgets import TitleLabel, BodyLabel, PushButton, FluentIcon
|
||||||
from PyQt5.QtWidgets import QFileDialog, QDialog, QHBoxLayout
|
from PyQt5.QtWidgets import QFileDialog
|
||||||
from qfluentwidgets import ComboBox, PrimaryPushButton, SubtitleLabel
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
from .function_fit_interface import FunctionFitInterface
|
from .function_fit_interface import FunctionFitInterface
|
||||||
from .ai_interface import AIInterface
|
from .ai_interface import AIInterface
|
||||||
from qfluentwidgets import InfoBar
|
from qfluentwidgets import InfoBar
|
||||||
@ -59,10 +56,6 @@ class CodeConfigurationInterface(QWidget):
|
|||||||
self.update_template_btn.setFixedWidth(200)
|
self.update_template_btn.setFixedWidth(200)
|
||||||
mainLayout.addWidget(self.update_template_btn, alignment=Qt.AlignmentFlag.AlignCenter)
|
mainLayout.addWidget(self.update_template_btn, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
self.preset_ioc_btn = PushButton(FluentIcon.LIBRARY, "获取预设IOC")
|
|
||||||
self.preset_ioc_btn.setFixedWidth(200)
|
|
||||||
mainLayout.addWidget(self.preset_ioc_btn, alignment=Qt.AlignmentFlag.AlignCenter)
|
|
||||||
|
|
||||||
mainLayout.addSpacing(10)
|
mainLayout.addSpacing(10)
|
||||||
mainLayout.addStretch()
|
mainLayout.addStretch()
|
||||||
|
|
||||||
@ -76,7 +69,6 @@ class CodeConfigurationInterface(QWidget):
|
|||||||
self.tabBar.tabCloseRequested.connect(self.onCloseTab)
|
self.tabBar.tabCloseRequested.connect(self.onCloseTab)
|
||||||
self.choose_btn.clicked.connect(self.choose_project_folder) # 启用选择项目路径按钮
|
self.choose_btn.clicked.connect(self.choose_project_folder) # 启用选择项目路径按钮
|
||||||
self.update_template_btn.clicked.connect(self.on_update_template)
|
self.update_template_btn.clicked.connect(self.on_update_template)
|
||||||
self.preset_ioc_btn.clicked.connect(self.use_preset_ioc) # 启用预设工程按钮
|
|
||||||
|
|
||||||
|
|
||||||
def on_update_template(self):
|
def on_update_template(self):
|
||||||
@ -96,170 +88,6 @@ class CodeConfigurationInterface(QWidget):
|
|||||||
)
|
)
|
||||||
update_code(parent=self, info_callback=info, error_callback=error)
|
update_code(parent=self, info_callback=info, error_callback=error)
|
||||||
|
|
||||||
def get_preset_ioc_files(self):
|
|
||||||
"""获取预设的ioc文件列表"""
|
|
||||||
try:
|
|
||||||
preset_ioc_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "assets", "User_code", "ioc")
|
|
||||||
if not os.path.exists(preset_ioc_dir):
|
|
||||||
return []
|
|
||||||
|
|
||||||
ioc_files = []
|
|
||||||
for filename in os.listdir(preset_ioc_dir):
|
|
||||||
if filename.endswith('.ioc'):
|
|
||||||
ioc_files.append({
|
|
||||||
'name': os.path.splitext(filename)[0],
|
|
||||||
'filename': filename,
|
|
||||||
'path': os.path.join(preset_ioc_dir, filename)
|
|
||||||
})
|
|
||||||
return ioc_files
|
|
||||||
except Exception as e:
|
|
||||||
print(f"获取预设ioc文件失败: {e}")
|
|
||||||
return []
|
|
||||||
|
|
||||||
def use_preset_ioc(self):
|
|
||||||
"""使用预设ioc文件"""
|
|
||||||
preset_files = self.get_preset_ioc_files()
|
|
||||||
if not preset_files:
|
|
||||||
InfoBar.warning(
|
|
||||||
title="无预设工程",
|
|
||||||
content="未找到可用的预设工程文件",
|
|
||||||
parent=self,
|
|
||||||
duration=2000
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
# 创建选择对话框
|
|
||||||
dialog = QDialog(self)
|
|
||||||
dialog.setWindowTitle("获取预设IOC")
|
|
||||||
dialog.resize(400, 200)
|
|
||||||
dialog.setModal(True)
|
|
||||||
|
|
||||||
layout = QVBoxLayout(dialog)
|
|
||||||
layout.setContentsMargins(24, 24, 24, 24)
|
|
||||||
layout.setSpacing(16)
|
|
||||||
|
|
||||||
# 标题
|
|
||||||
title_label = SubtitleLabel("选择要使用的IOC模版")
|
|
||||||
layout.addWidget(title_label)
|
|
||||||
|
|
||||||
# 选择下拉框
|
|
||||||
select_layout = QHBoxLayout()
|
|
||||||
select_label = BodyLabel("预设IOC:")
|
|
||||||
preset_combo = ComboBox()
|
|
||||||
|
|
||||||
# 修复ComboBox数据问题
|
|
||||||
for i, preset in enumerate(preset_files):
|
|
||||||
preset_combo.addItem(preset['name'])
|
|
||||||
|
|
||||||
select_layout.addWidget(select_label)
|
|
||||||
select_layout.addWidget(preset_combo)
|
|
||||||
layout.addLayout(select_layout)
|
|
||||||
|
|
||||||
layout.addSpacing(16)
|
|
||||||
|
|
||||||
# 按钮区域
|
|
||||||
btn_layout = QHBoxLayout()
|
|
||||||
btn_layout.addStretch()
|
|
||||||
|
|
||||||
cancel_btn = PushButton("取消")
|
|
||||||
ok_btn = PrimaryPushButton("保存到")
|
|
||||||
|
|
||||||
cancel_btn.clicked.connect(dialog.reject)
|
|
||||||
ok_btn.clicked.connect(dialog.accept)
|
|
||||||
|
|
||||||
btn_layout.addWidget(cancel_btn)
|
|
||||||
btn_layout.addWidget(ok_btn)
|
|
||||||
layout.addLayout(btn_layout)
|
|
||||||
|
|
||||||
# 显示对话框
|
|
||||||
if dialog.exec() == QDialog.Accepted:
|
|
||||||
selected_index = preset_combo.currentIndex()
|
|
||||||
if selected_index >= 0 and selected_index < len(preset_files):
|
|
||||||
selected_preset = preset_files[selected_index]
|
|
||||||
self.save_preset_template(selected_preset)
|
|
||||||
|
|
||||||
def save_preset_template(self, preset_info):
|
|
||||||
"""保存预设模板到用户指定位置"""
|
|
||||||
try:
|
|
||||||
# 让用户选择保存位置
|
|
||||||
save_dir = QFileDialog.getExistingDirectory(
|
|
||||||
self,
|
|
||||||
f"选择保存 {preset_info['name']} 模板的位置",
|
|
||||||
os.path.expanduser("~")
|
|
||||||
)
|
|
||||||
|
|
||||||
if not save_dir:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 复制ioc文件到用户选择的目录
|
|
||||||
target_path = os.path.join(save_dir, preset_info['filename'])
|
|
||||||
|
|
||||||
# 检查目标文件是否已存在
|
|
||||||
if os.path.exists(target_path):
|
|
||||||
from qfluentwidgets import Dialog
|
|
||||||
dialog = Dialog("文件已存在", f"目标位置已存在 {preset_info['filename']},是否覆盖?", self)
|
|
||||||
if dialog.exec() != Dialog.Accepted:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 复制文件
|
|
||||||
shutil.copy2(preset_info['path'], target_path)
|
|
||||||
|
|
||||||
InfoBar.success(
|
|
||||||
title="模板保存成功",
|
|
||||||
content=f"预设模板 {preset_info['name']} 已保存到:\n{target_path}",
|
|
||||||
parent=self,
|
|
||||||
duration=3000
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
InfoBar.error(
|
|
||||||
title="保存失败",
|
|
||||||
content=f"保存预设模板失败: {str(e)}",
|
|
||||||
parent=self,
|
|
||||||
duration=3000
|
|
||||||
)
|
|
||||||
|
|
||||||
def open_project_from_path(self, folder_path):
|
|
||||||
"""从指定路径打开工程"""
|
|
||||||
try:
|
|
||||||
if not os.path.exists(folder_path):
|
|
||||||
return
|
|
||||||
|
|
||||||
ioc_files = [f for f in os.listdir(folder_path) if f.endswith('.ioc')]
|
|
||||||
if ioc_files:
|
|
||||||
# 检查是否已存在 codeGenPage 标签页
|
|
||||||
for i in range(self.stackedWidget.count()):
|
|
||||||
widget = self.stackedWidget.widget(i)
|
|
||||||
if widget is not None and widget.objectName() == "codeGenPage":
|
|
||||||
# 如果已存在,则切换到该标签页,并更新路径显示
|
|
||||||
if hasattr(widget, "project_path"):
|
|
||||||
widget.project_path = folder_path
|
|
||||||
if hasattr(widget, "refresh"):
|
|
||||||
widget.refresh()
|
|
||||||
self.stackedWidget.setCurrentWidget(widget)
|
|
||||||
self.tabBar.setCurrentTab("codeGenPage")
|
|
||||||
return
|
|
||||||
|
|
||||||
# 不存在则新建
|
|
||||||
code_gen_page = CodeGenerateInterface(folder_path, self)
|
|
||||||
self.addSubInterface(code_gen_page, "codeGenPage", "代码生成")
|
|
||||||
self.stackedWidget.setCurrentWidget(code_gen_page)
|
|
||||||
self.tabBar.setCurrentTab("codeGenPage")
|
|
||||||
else:
|
|
||||||
InfoBar.error(
|
|
||||||
title="未找到.ioc文件",
|
|
||||||
content="所选文件夹不是有效的CUBEMX工程目录",
|
|
||||||
parent=self,
|
|
||||||
duration=3000
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
InfoBar.error(
|
|
||||||
title="打开工程失败",
|
|
||||||
content=f"打开工程失败: {str(e)}",
|
|
||||||
parent=self,
|
|
||||||
duration=3000
|
|
||||||
)
|
|
||||||
|
|
||||||
def choose_project_folder(self):
|
def choose_project_folder(self):
|
||||||
folder = QFileDialog.getExistingDirectory(self, "选择CUBEMX工程目录")
|
folder = QFileDialog.getExistingDirectory(self, "选择CUBEMX工程目录")
|
||||||
if not folder:
|
if not folder:
|
||||||
|
|||||||
@ -917,48 +917,10 @@ class bsp_spi(BspPeripheralBase):
|
|||||||
|
|
||||||
|
|
||||||
def patch_uart_interrupts(project_path, uart_instances):
|
def patch_uart_interrupts(project_path, uart_instances):
|
||||||
"""自动修改中断文件,插入 UART BSP 相关代码(支持 F1/F4/H7 等系列)"""
|
"""自动修改 stm32f4xx_it.c,插入 UART BSP 相关代码"""
|
||||||
# 检测MCU型号,确定正确的中断文件
|
it_path = os.path.join(project_path, "Core/Src/stm32f4xx_it.c")
|
||||||
ioc_files = [f for f in os.listdir(project_path) if f.endswith('.ioc')]
|
|
||||||
if not ioc_files:
|
|
||||||
return
|
|
||||||
|
|
||||||
ioc_path = os.path.join(project_path, ioc_files[0])
|
|
||||||
mcu_name = analyzing_ioc.get_mcu_name_from_ioc(ioc_path)
|
|
||||||
|
|
||||||
if not mcu_name:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 根据MCU型号确定中断文件名
|
|
||||||
mcu_upper = mcu_name.upper()
|
|
||||||
if 'STM32F1' in mcu_upper:
|
|
||||||
it_file = "stm32f1xx_it.c"
|
|
||||||
elif 'STM32F4' in mcu_upper:
|
|
||||||
it_file = "stm32f4xx_it.c"
|
|
||||||
elif 'STM32H7' in mcu_upper:
|
|
||||||
it_file = "stm32h7xx_it.c"
|
|
||||||
elif 'STM32F7' in mcu_upper:
|
|
||||||
it_file = "stm32f7xx_it.c"
|
|
||||||
elif 'STM32G4' in mcu_upper:
|
|
||||||
it_file = "stm32g4xx_it.c"
|
|
||||||
elif 'STM32L4' in mcu_upper:
|
|
||||||
it_file = "stm32l4xx_it.c"
|
|
||||||
else:
|
|
||||||
# 通用处理:尝试从MCU名称提取系列信息
|
|
||||||
# 格式通常为 STM32X0XXX,提取 X0 部分
|
|
||||||
import re as regex
|
|
||||||
match = regex.match(r'STM32([A-Z]\d)', mcu_upper)
|
|
||||||
if match:
|
|
||||||
series = match.group(1).lower()
|
|
||||||
it_file = f"stm32{series}xx_it.c"
|
|
||||||
else:
|
|
||||||
# 默认尝试 F4
|
|
||||||
it_file = "stm32f4xx_it.c"
|
|
||||||
|
|
||||||
it_path = os.path.join(project_path, f"Core/Src/{it_file}")
|
|
||||||
if not os.path.exists(it_path):
|
if not os.path.exists(it_path):
|
||||||
return
|
return
|
||||||
|
|
||||||
with open(it_path, "r", encoding="utf-8") as f:
|
with open(it_path, "r", encoding="utf-8") as f:
|
||||||
code = f.read()
|
code = f.read()
|
||||||
|
|
||||||
|
|||||||
@ -637,31 +637,6 @@ class DataInterface(QWidget):
|
|||||||
for t in task_list:
|
for t in task_list:
|
||||||
desc = t.get("description", "")
|
desc = t.get("description", "")
|
||||||
desc_wrapped = "\n ".join(textwrap.wrap(desc, 20))
|
desc_wrapped = "\n ".join(textwrap.wrap(desc, 20))
|
||||||
|
|
||||||
# 检查是否是预设任务
|
|
||||||
if t.get("preset_task"):
|
|
||||||
# 使用预设任务的代码
|
|
||||||
preset_task_name = t["preset_task"]
|
|
||||||
from app.tools.code_generator import CodeGenerator
|
|
||||||
task_template_dir = CodeGenerator.get_assets_dir("User_code/task/template_task")
|
|
||||||
preset_task_file = os.path.join(task_template_dir, f"{preset_task_name}.c")
|
|
||||||
|
|
||||||
if os.path.exists(preset_task_file):
|
|
||||||
# 直接复制预设任务文件
|
|
||||||
task_c_path = os.path.join(output_dir, f"{t['name']}.c")
|
|
||||||
with open(preset_task_file, 'r', encoding='utf-8') as f:
|
|
||||||
preset_code = f.read()
|
|
||||||
|
|
||||||
# 如果任务名称不同,需要替换函数名
|
|
||||||
if preset_task_name != t["name"]:
|
|
||||||
# 替换任务函数名
|
|
||||||
preset_code = preset_code.replace(f"Task_{preset_task_name}", t["function"])
|
|
||||||
preset_code = preset_code.replace(f" {preset_task_name} Task", f" {t['name']} Task")
|
|
||||||
|
|
||||||
save_with_preserve(task_c_path, preset_code)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 使用默认模板生成任务代码
|
|
||||||
context_task = {
|
context_task = {
|
||||||
"task_name": t["name"],
|
"task_name": t["name"],
|
||||||
"task_function": t["function"],
|
"task_function": t["function"],
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QWidget, QScrollArea
|
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QWidget, QScrollArea
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
BodyLabel, TitleLabel, HorizontalSeparator, PushButton, PrimaryPushButton,
|
BodyLabel, TitleLabel, HorizontalSeparator, PushButton, PrimaryPushButton,
|
||||||
LineEdit, SpinBox, DoubleSpinBox, CheckBox, TextEdit, ComboBox
|
LineEdit, SpinBox, DoubleSpinBox, CheckBox, TextEdit
|
||||||
)
|
)
|
||||||
from qfluentwidgets import theme, Theme
|
from qfluentwidgets import theme, Theme
|
||||||
import yaml
|
import yaml
|
||||||
@ -76,20 +76,12 @@ class TaskConfigDialog(QDialog):
|
|||||||
self.add_btn = PrimaryPushButton("创建新任务")
|
self.add_btn = PrimaryPushButton("创建新任务")
|
||||||
self.add_btn.setAutoDefault(False) # 禁止回车触发
|
self.add_btn.setAutoDefault(False) # 禁止回车触发
|
||||||
self.add_btn.setDefault(False)
|
self.add_btn.setDefault(False)
|
||||||
|
|
||||||
# 新增:预设任务按钮
|
|
||||||
self.preset_btn = PushButton("使用预设任务")
|
|
||||||
self.preset_btn.setAutoDefault(False)
|
|
||||||
self.preset_btn.setDefault(False)
|
|
||||||
|
|
||||||
self.del_btn = PushButton("删除当前任务")
|
self.del_btn = PushButton("删除当前任务")
|
||||||
self.del_btn.setAutoDefault(False) # 禁止回车触发
|
self.del_btn.setAutoDefault(False) # 禁止回车触发
|
||||||
self.del_btn.setDefault(False)
|
self.del_btn.setDefault(False)
|
||||||
self.add_btn.clicked.connect(self.add_task)
|
self.add_btn.clicked.connect(self.add_task)
|
||||||
self.preset_btn.clicked.connect(self.add_preset_task)
|
|
||||||
self.del_btn.clicked.connect(self.delete_current_task)
|
self.del_btn.clicked.connect(self.delete_current_task)
|
||||||
btn_layout.addWidget(self.add_btn)
|
btn_layout.addWidget(self.add_btn)
|
||||||
btn_layout.addWidget(self.preset_btn)
|
|
||||||
btn_layout.addWidget(self.del_btn)
|
btn_layout.addWidget(self.del_btn)
|
||||||
btn_layout.addStretch() # 添加/删除靠左,stretch在中间
|
btn_layout.addStretch() # 添加/删除靠左,stretch在中间
|
||||||
|
|
||||||
@ -143,274 +135,6 @@ class TaskConfigDialog(QDialog):
|
|||||||
self.task_btn_layout.addWidget(btn)
|
self.task_btn_layout.addWidget(btn)
|
||||||
self.task_btn_layout.addStretch()
|
self.task_btn_layout.addStretch()
|
||||||
|
|
||||||
def get_preset_tasks(self):
|
|
||||||
"""获取所有可用的预设任务"""
|
|
||||||
from app.tools.code_generator import CodeGenerator
|
|
||||||
task_dir = CodeGenerator.get_assets_dir("User_code/task/template_task")
|
|
||||||
preset_tasks = []
|
|
||||||
|
|
||||||
if not os.path.exists(task_dir):
|
|
||||||
return preset_tasks
|
|
||||||
|
|
||||||
for filename in os.listdir(task_dir):
|
|
||||||
if filename.endswith('.c') and not filename.endswith('.template'):
|
|
||||||
task_name = os.path.splitext(filename)[0]
|
|
||||||
preset_tasks.append(task_name)
|
|
||||||
|
|
||||||
return preset_tasks
|
|
||||||
|
|
||||||
def load_preset_task_config(self, task_name):
|
|
||||||
"""从 yaml 配置文件中加载预设任务的配置"""
|
|
||||||
try:
|
|
||||||
from app.tools.code_generator import CodeGenerator
|
|
||||||
template_dir = CodeGenerator.get_assets_dir("User_code/task/template_task")
|
|
||||||
config_file = os.path.join(template_dir, "task.yaml")
|
|
||||||
|
|
||||||
if not os.path.exists(config_file):
|
|
||||||
return None
|
|
||||||
|
|
||||||
with open(config_file, 'r', encoding='utf-8') as f:
|
|
||||||
config_data = yaml.safe_load(f)
|
|
||||||
|
|
||||||
if config_data and task_name in config_data:
|
|
||||||
return config_data[task_name]
|
|
||||||
return None
|
|
||||||
except Exception as e:
|
|
||||||
print(f"加载预设任务配置失败: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def load_preset_task_code(self, task_name):
|
|
||||||
"""加载预设任务的代码内容"""
|
|
||||||
from app.tools.code_generator import CodeGenerator
|
|
||||||
task_dir = CodeGenerator.get_assets_dir("User_code/task/template_task")
|
|
||||||
task_file = os.path.join(task_dir, f"{task_name}.c")
|
|
||||||
|
|
||||||
if os.path.exists(task_file):
|
|
||||||
with open(task_file, 'r', encoding='utf-8') as f:
|
|
||||||
return f.read()
|
|
||||||
return None
|
|
||||||
|
|
||||||
def add_preset_task(self):
|
|
||||||
"""添加预设任务"""
|
|
||||||
preset_tasks = self.get_preset_tasks()
|
|
||||||
if not preset_tasks:
|
|
||||||
InfoBar.warning(
|
|
||||||
title="无预设任务",
|
|
||||||
content="未找到可用的预设任务模板",
|
|
||||||
parent=self,
|
|
||||||
duration=2000
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
# 创建自适应主题的对话框
|
|
||||||
dialog = QDialog(self)
|
|
||||||
dialog.setWindowTitle("选择预设任务")
|
|
||||||
dialog.resize(600, 500)
|
|
||||||
dialog.setModal(True)
|
|
||||||
|
|
||||||
layout = QVBoxLayout(dialog)
|
|
||||||
layout.setContentsMargins(24, 24, 24, 24)
|
|
||||||
layout.setSpacing(18)
|
|
||||||
|
|
||||||
# 固定内容区域
|
|
||||||
fixed_content = QWidget()
|
|
||||||
fixed_content.setFixedHeight(180) # 减少固定高度
|
|
||||||
fixed_layout = QVBoxLayout(fixed_content)
|
|
||||||
fixed_layout.setContentsMargins(0, 0, 0, 0)
|
|
||||||
fixed_layout.setSpacing(18)
|
|
||||||
|
|
||||||
# 标题
|
|
||||||
title_label = TitleLabel("选择预设任务模板")
|
|
||||||
fixed_layout.addWidget(title_label)
|
|
||||||
|
|
||||||
# 说明文字
|
|
||||||
desc_label = BodyLabel("选择一个预设任务模板,系统将自动复制相应的代码和配置")
|
|
||||||
fixed_layout.addWidget(desc_label)
|
|
||||||
|
|
||||||
fixed_layout.addWidget(HorizontalSeparator())
|
|
||||||
|
|
||||||
# 任务选择
|
|
||||||
select_layout = QHBoxLayout()
|
|
||||||
select_layout.setSpacing(12)
|
|
||||||
|
|
||||||
select_label = BodyLabel("预设任务:")
|
|
||||||
preset_combo = ComboBox()
|
|
||||||
preset_combo.addItems(preset_tasks)
|
|
||||||
preset_combo.setCurrentIndex(0)
|
|
||||||
preset_combo.setMinimumWidth(160)
|
|
||||||
|
|
||||||
select_layout.addWidget(select_label)
|
|
||||||
select_layout.addWidget(preset_combo)
|
|
||||||
select_layout.addStretch()
|
|
||||||
|
|
||||||
fixed_layout.addLayout(select_layout)
|
|
||||||
|
|
||||||
# 参数信息 - 单行显示
|
|
||||||
params_layout = QHBoxLayout()
|
|
||||||
params_layout.setSpacing(24) # 适中的间距
|
|
||||||
|
|
||||||
self.info_freq = BodyLabel("")
|
|
||||||
self.info_delay = BodyLabel("")
|
|
||||||
self.info_stack = BodyLabel("")
|
|
||||||
self.info_ctrl = BodyLabel("")
|
|
||||||
|
|
||||||
self.info_freq.setMinimumWidth(120)
|
|
||||||
self.info_delay.setMinimumWidth(100)
|
|
||||||
self.info_stack.setMinimumWidth(120)
|
|
||||||
self.info_ctrl.setMinimumWidth(100)
|
|
||||||
|
|
||||||
params_layout.addWidget(self.info_freq)
|
|
||||||
params_layout.addWidget(self.info_delay)
|
|
||||||
params_layout.addWidget(self.info_stack)
|
|
||||||
params_layout.addWidget(self.info_ctrl)
|
|
||||||
params_layout.addStretch()
|
|
||||||
|
|
||||||
fixed_layout.addLayout(params_layout)
|
|
||||||
fixed_layout.addStretch() # 在固定区域内保持紧凑
|
|
||||||
|
|
||||||
layout.addWidget(fixed_content)
|
|
||||||
|
|
||||||
# 弹性描述区域
|
|
||||||
desc_layout = QVBoxLayout()
|
|
||||||
desc_layout.setSpacing(8)
|
|
||||||
|
|
||||||
desc_title = BodyLabel("描述:")
|
|
||||||
desc_title.setStyleSheet("font-weight: bold;")
|
|
||||||
desc_layout.addWidget(desc_title)
|
|
||||||
|
|
||||||
self.preview_desc = TextEdit()
|
|
||||||
self.preview_desc.setReadOnly(True)
|
|
||||||
self.preview_desc.setMinimumHeight(60) # 最小高度
|
|
||||||
desc_layout.addWidget(self.preview_desc)
|
|
||||||
|
|
||||||
layout.addLayout(desc_layout, stretch=1) # 弹性伸缩
|
|
||||||
|
|
||||||
# 按钮区域
|
|
||||||
layout.addWidget(HorizontalSeparator())
|
|
||||||
btn_layout = QHBoxLayout()
|
|
||||||
btn_layout.addStretch()
|
|
||||||
|
|
||||||
cancel_btn = PushButton("取消")
|
|
||||||
ok_btn = PrimaryPushButton("确定添加")
|
|
||||||
|
|
||||||
cancel_btn.clicked.connect(dialog.reject)
|
|
||||||
ok_btn.clicked.connect(dialog.accept)
|
|
||||||
|
|
||||||
btn_layout.addWidget(cancel_btn)
|
|
||||||
btn_layout.addWidget(ok_btn)
|
|
||||||
layout.addLayout(btn_layout)
|
|
||||||
|
|
||||||
# 预览更新函数
|
|
||||||
def update_preview():
|
|
||||||
selected = preset_combo.currentText()
|
|
||||||
self.update_preset_preview(selected)
|
|
||||||
|
|
||||||
preset_combo.currentTextChanged.connect(update_preview)
|
|
||||||
|
|
||||||
# 存储对话框状态
|
|
||||||
self.current_preview_dialog = dialog
|
|
||||||
self.preview_combo = preset_combo
|
|
||||||
|
|
||||||
# 初始化预览
|
|
||||||
if preset_tasks:
|
|
||||||
update_preview()
|
|
||||||
|
|
||||||
# 显示对话框
|
|
||||||
if dialog.exec() == QDialog.Accepted:
|
|
||||||
selected_task = preset_combo.currentText()
|
|
||||||
self.save_form()
|
|
||||||
new_idx = len(self.tasks)
|
|
||||||
|
|
||||||
# 从配置文件加载预设任务参数
|
|
||||||
config = self.load_preset_task_config(selected_task)
|
|
||||||
if config:
|
|
||||||
new_task = self._make_task_obj({
|
|
||||||
"name": config.get("name", selected_task),
|
|
||||||
"frequency": config.get("frequency", 500),
|
|
||||||
"delay": config.get("delay", 0),
|
|
||||||
"stack": config.get("stack", 256),
|
|
||||||
"description": config.get("description", ""),
|
|
||||||
"freq_control": config.get("freq_control", True)
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
new_task = self._make_task_obj({"name": selected_task})
|
|
||||||
|
|
||||||
new_task["preset_task"] = selected_task
|
|
||||||
|
|
||||||
self.tasks.append(new_task)
|
|
||||||
self.current_index = new_idx
|
|
||||||
self.refresh_task_btns()
|
|
||||||
self.show_task_form(self.tasks[self.current_index])
|
|
||||||
|
|
||||||
InfoBar.success(
|
|
||||||
title="添加成功",
|
|
||||||
content=f"已添加预设任务:{selected_task}",
|
|
||||||
parent=self,
|
|
||||||
duration=2000
|
|
||||||
)
|
|
||||||
|
|
||||||
def update_preset_preview(self, task_name):
|
|
||||||
"""更新预设任务预览信息"""
|
|
||||||
# 从配置加载信息
|
|
||||||
config = self.load_preset_task_config(task_name)
|
|
||||||
if config:
|
|
||||||
self.info_freq.setText(f"频率: {config.get('frequency', 500)} Hz")
|
|
||||||
self.info_delay.setText(f"延时: {config.get('delay', 0)} ms")
|
|
||||||
self.info_stack.setText(f"堆栈: {config.get('stack', 256)} Bytes")
|
|
||||||
freq_ctrl = "启用" if config.get('freq_control', True) else "禁用"
|
|
||||||
self.info_ctrl.setText(f"频率控制: {freq_ctrl}")
|
|
||||||
|
|
||||||
description = config.get('description', f'预设任务:{task_name}')
|
|
||||||
self.preview_desc.setText(description)
|
|
||||||
else:
|
|
||||||
self.info_freq.setText("频率: 500 Hz")
|
|
||||||
self.info_delay.setText("延时: 0 ms")
|
|
||||||
self.info_stack.setText("堆栈: 256 Bytes")
|
|
||||||
self.info_ctrl.setText("频率控制: 启用")
|
|
||||||
self.preview_desc.setText(f"预设任务:{task_name}")
|
|
||||||
|
|
||||||
def on_preset_task_selected(self, task_name):
|
|
||||||
"""预设任务选择事件(向后兼容)"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_preset_task_description(self, task_name):
|
|
||||||
"""获取预设任务的描述信息"""
|
|
||||||
# 首先尝试从 yaml 配置中获取描述
|
|
||||||
config = self.load_preset_task_config(task_name)
|
|
||||||
if config and 'description' in config:
|
|
||||||
return f"预设任务:{task_name}\n\n{config['description']}\n\n频率控制:{'启用' if config.get('freq_control', True) else '禁用'}\n运行频率:{config.get('frequency', 500)} Hz\n堆栈大小:{config.get('stack', 256)} Bytes\n初始延时:{config.get('delay', 0)} ms"
|
|
||||||
|
|
||||||
# 如果没有配置文件,则从代码注释中提取
|
|
||||||
try:
|
|
||||||
task_code = self.load_preset_task_code(task_name)
|
|
||||||
if task_code:
|
|
||||||
# 尝试从注释中提取描述
|
|
||||||
lines = task_code.split('\n')
|
|
||||||
description_lines = []
|
|
||||||
in_comment = False
|
|
||||||
|
|
||||||
for line in lines[:20]: # 只检查前20行
|
|
||||||
line = line.strip()
|
|
||||||
if line.startswith('/*'):
|
|
||||||
in_comment = True
|
|
||||||
if 'Task' in line and line != '/*':
|
|
||||||
description_lines.append(line.replace('/*', '').strip())
|
|
||||||
continue
|
|
||||||
elif line.endswith('*/'):
|
|
||||||
in_comment = False
|
|
||||||
break
|
|
||||||
elif in_comment and line and not line.startswith('*'):
|
|
||||||
description_lines.append(line)
|
|
||||||
|
|
||||||
if description_lines:
|
|
||||||
return '\n'.join(description_lines)
|
|
||||||
else:
|
|
||||||
return f"预设任务:{task_name}\n这是一个预定义的任务模板,包含完整的实现代码。"
|
|
||||||
else:
|
|
||||||
return f"预设任务:{task_name}\n无法读取任务描述。"
|
|
||||||
except Exception as e:
|
|
||||||
return f"预设任务:{task_name}\n读取描述时出现错误:{str(e)}"
|
|
||||||
|
|
||||||
def add_task(self):
|
def add_task(self):
|
||||||
self.save_form()
|
self.save_form()
|
||||||
new_idx = len(self.tasks)
|
new_idx = len(self.tasks)
|
||||||
@ -578,10 +302,5 @@ class TaskConfigDialog(QDialog):
|
|||||||
}
|
}
|
||||||
if freq_ctrl:
|
if freq_ctrl:
|
||||||
task["frequency"] = freq
|
task["frequency"] = freq
|
||||||
|
|
||||||
# 保留预设任务信息
|
|
||||||
if "preset_task" in t:
|
|
||||||
task["preset_task"] = t["preset_task"]
|
|
||||||
|
|
||||||
tasks.append(task)
|
tasks.append(task)
|
||||||
return tasks
|
return tasks
|
||||||
BIN
assets/.DS_Store
vendored
BIN
assets/.DS_Store
vendored
Binary file not shown.
@ -21,19 +21,19 @@
|
|||||||
#define FDCAN1_FILTER_CONFIG_TABLE(X) \
|
#define FDCAN1_FILTER_CONFIG_TABLE(X) \
|
||||||
X(0, FDCAN_STANDARD_ID, FDCAN_FILTER_MASK, 0x000 , 0x000 , 0) \
|
X(0, FDCAN_STANDARD_ID, FDCAN_FILTER_MASK, 0x000 , 0x000 , 0) \
|
||||||
X(1, FDCAN_EXTENDED_ID, FDCAN_FILTER_MASK, 0x00000000, 0x00000000, 0)
|
X(1, FDCAN_EXTENDED_ID, FDCAN_FILTER_MASK, 0x00000000, 0x00000000, 0)
|
||||||
#define FDCAN1_GLOBAL_FILTER FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE
|
#define FDCAN1_GLOBAL_FILTER FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE/* 全局过滤器参数(用于 HAL_FDCAN_ConfigGlobalFilter) */
|
||||||
#endif
|
#endif
|
||||||
#ifdef FDCAN2_EN
|
#ifdef FDCAN2_EN
|
||||||
#define FDCAN2_FILTER_CONFIG_TABLE(X) \
|
#define FDCAN2_FILTER_CONFIG_TABLE(X) \
|
||||||
X(0, FDCAN_STANDARD_ID, FDCAN_FILTER_MASK, 0x000 , 0x000 , 0) \
|
X(0, FDCAN_STANDARD_ID, FDCAN_FILTER_MASK, 0x000 , 0x000 , 0) \
|
||||||
X(1, FDCAN_EXTENDED_ID, FDCAN_FILTER_MASK, 0x00000000, 0x00000000, 0)
|
X(1, FDCAN_EXTENDED_ID, FDCAN_FILTER_MASK, 0x00000000, 0x00000000, 0)
|
||||||
#define FDCAN2_GLOBAL_FILTER FDCAN_ACCEPT_IN_RX_FIFO1, FDCAN_ACCEPT_IN_RX_FIFO1, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE
|
#define FDCAN2_GLOBAL_FILTER FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE/* 全局过滤器参数(用于 HAL_FDCAN_ConfigGlobalFilter) */
|
||||||
#endif
|
#endif
|
||||||
#ifdef FDCAN3_EN
|
#ifdef FDCAN3_EN
|
||||||
#define FDCAN3_FILTER_CONFIG_TABLE(X) \
|
#define FDCAN3_FILTER_CONFIG_TABLE(X) \
|
||||||
X(0, FDCAN_STANDARD_ID, FDCAN_FILTER_MASK, 0x000 , 0x000 , 0) \
|
X(0, FDCAN_STANDARD_ID, FDCAN_FILTER_MASK, 0x000 , 0x000 , 0) \
|
||||||
X(1, FDCAN_EXTENDED_ID, FDCAN_FILTER_MASK, 0x00000000, 0x00000000, 0)
|
X(1, FDCAN_EXTENDED_ID, FDCAN_FILTER_MASK, 0x00000000, 0x00000000, 0)
|
||||||
#define FDCAN3_GLOBAL_FILTER FDCAN_ACCEPT_IN_RX_FIFO1, FDCAN_ACCEPT_IN_RX_FIFO1, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE
|
#define FDCAN3_GLOBAL_FILTER FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE/* 全局过滤器参数(用于 HAL_FDCAN_ConfigGlobalFilter) */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ====宏展开实现==== */
|
/* ====宏展开实现==== */
|
||||||
|
|||||||
@ -69,7 +69,6 @@ int8_t BSP_GPIO_EnableIRQ(BSP_GPIO_t gpio) {
|
|||||||
default:
|
default:
|
||||||
return BSP_ERR;
|
return BSP_ERR;
|
||||||
}
|
}
|
||||||
return BSP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t BSP_GPIO_DisableIRQ(BSP_GPIO_t gpio) {
|
int8_t BSP_GPIO_DisableIRQ(BSP_GPIO_t gpio) {
|
||||||
@ -78,7 +77,6 @@ int8_t BSP_GPIO_DisableIRQ(BSP_GPIO_t gpio) {
|
|||||||
default:
|
default:
|
||||||
return BSP_ERR;
|
return BSP_ERR;
|
||||||
}
|
}
|
||||||
return BSP_OK;
|
|
||||||
}
|
}
|
||||||
int8_t BSP_GPIO_WritePin(BSP_GPIO_t gpio, bool value){
|
int8_t BSP_GPIO_WritePin(BSP_GPIO_t gpio, bool value){
|
||||||
if (gpio >= BSP_GPIO_NUM) return BSP_ERR;
|
if (gpio >= BSP_GPIO_NUM) return BSP_ERR;
|
||||||
|
|||||||
@ -6,4 +6,3 @@ pid,component/filter
|
|||||||
filter,component/ahrs
|
filter,component/ahrs
|
||||||
mixer,component/user_math.h
|
mixer,component/user_math.h
|
||||||
ui,component/user_math.h
|
ui,component/user_math.h
|
||||||
kalman_filter,arm_math.h
|
|
||||||
|
@ -12,4 +12,3 @@ mixer,混控器
|
|||||||
ui,用户交互
|
ui,用户交互
|
||||||
user_math,用户自定义数学函数
|
user_math,用户自定义数学函数
|
||||||
pid,PID控制器
|
pid,PID控制器
|
||||||
kalman_filter,卡尔曼滤波器
|
|
||||||
|
@ -28,9 +28,6 @@
|
|||||||
#ifndef COMMAND_INTERPRETER_H
|
#ifndef COMMAND_INTERPRETER_H
|
||||||
#define COMMAND_INTERPRETER_H
|
#define COMMAND_INTERPRETER_H
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
|
|
||||||
/* This config should be defined in FreeRTOSConfig.h. But due to the limition of CubeMX I put it here. */
|
/* This config should be defined in FreeRTOSConfig.h. But due to the limition of CubeMX I put it here. */
|
||||||
#define configCOMMAND_INT_MAX_OUTPUT_SIZE 512
|
#define configCOMMAND_INT_MAX_OUTPUT_SIZE 512
|
||||||
|
|
||||||
|
|||||||
@ -1,591 +0,0 @@
|
|||||||
/*
|
|
||||||
卡尔曼滤波器 modified from wang hongxi
|
|
||||||
支持动态量测调整,使用ARM CMSIS DSP优化矩阵运算
|
|
||||||
|
|
||||||
主要特性:
|
|
||||||
- 基于量测有效性的 H、R、K 矩阵动态调整
|
|
||||||
- 支持不同传感器采样频率
|
|
||||||
- 矩阵 P 防过度收敛机制
|
|
||||||
- ARM CMSIS DSP 优化的矩阵运算
|
|
||||||
- 可扩展架构,支持用户自定义函数(EKF/UKF/ESKF)
|
|
||||||
|
|
||||||
使用说明:
|
|
||||||
1. 矩阵初始化:P、F、Q 使用标准初始化方式
|
|
||||||
H、R 在使用自动调整时需要配置量测映射
|
|
||||||
|
|
||||||
2. 自动调整模式 (use_auto_adjustment = 1):
|
|
||||||
- 提供 measurement_map:每个量测对应的状态索引
|
|
||||||
- 提供 measurement_degree:H 矩阵元素值
|
|
||||||
- 提供 mat_r_diagonal_elements:量测噪声方差
|
|
||||||
|
|
||||||
3. 固定模式 (use_auto_adjustment = 0):
|
|
||||||
- 像初始化 P 矩阵那样正常初始化 z、H、R
|
|
||||||
|
|
||||||
4. 量测更新:
|
|
||||||
- 在传感器回调函数中更新 measured_vector
|
|
||||||
- 值为 0 表示量测无效
|
|
||||||
- 向量在每次 KF 更新后会被重置为 0
|
|
||||||
|
|
||||||
5. 防过度收敛:
|
|
||||||
- 设置 state_min_variance 防止 P 矩阵过度收敛
|
|
||||||
- 帮助滤波器适应缓慢变化的状态
|
|
||||||
|
|
||||||
使用示例:高度估计
|
|
||||||
状态向量 x =
|
|
||||||
| 高度 |
|
|
||||||
| 速度 |
|
|
||||||
| 加速度 |
|
|
||||||
|
|
||||||
KF_t Height_KF;
|
|
||||||
|
|
||||||
void INS_Task_Init(void)
|
|
||||||
{
|
|
||||||
// 初始协方差矩阵 P
|
|
||||||
static float P_Init[9] =
|
|
||||||
{
|
|
||||||
10, 0, 0,
|
|
||||||
0, 30, 0,
|
|
||||||
0, 0, 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 状态转移矩阵 F(根据运动学模型)
|
|
||||||
static float F_Init[9] =
|
|
||||||
{
|
|
||||||
1, dt, 0.5*dt*dt,
|
|
||||||
0, 1, dt,
|
|
||||||
0, 0, 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 过程噪声协方差矩阵 Q
|
|
||||||
static float Q_Init[9] =
|
|
||||||
{
|
|
||||||
0.25*dt*dt*dt*dt, 0.5*dt*dt*dt, 0.5*dt*dt,
|
|
||||||
0.5*dt*dt*dt, dt*dt, dt,
|
|
||||||
0.5*dt*dt, dt, 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 设置状态最小方差(防止过度收敛)
|
|
||||||
static float state_min_variance[3] = {0.03, 0.005, 0.1};
|
|
||||||
|
|
||||||
// 开启自动调整
|
|
||||||
Height_KF.use_auto_adjustment = 1;
|
|
||||||
|
|
||||||
// 量测映射:[气压高度对应状态1, GPS高度对应状态1, 加速度计对应状态3]
|
|
||||||
static uint8_t measurement_reference[3] = {1, 1, 3};
|
|
||||||
|
|
||||||
// 量测系数(H矩阵元素值)
|
|
||||||
static float measurement_degree[3] = {1, 1, 1};
|
|
||||||
// 根据 measurement_reference 与 measurement_degree 生成 H 矩阵如下
|
|
||||||
// (在当前周期全部量测数据有效的情况下)
|
|
||||||
// |1 0 0|
|
|
||||||
// |1 0 0|
|
|
||||||
// |0 0 1|
|
|
||||||
|
|
||||||
// 量测噪声方差(R矩阵对角元素)
|
|
||||||
static float mat_r_diagonal_elements[3] = {30, 25, 35};
|
|
||||||
// 根据 mat_r_diagonal_elements 生成 R 矩阵如下
|
|
||||||
// (在当前周期全部量测数据有效的情况下)
|
|
||||||
// |30 0 0|
|
|
||||||
// | 0 25 0|
|
|
||||||
// | 0 0 35|
|
|
||||||
|
|
||||||
// 初始化卡尔曼滤波器(状态维数3,控制维数0,量测维数3)
|
|
||||||
KF_Init(&Height_KF, 3, 0, 3);
|
|
||||||
|
|
||||||
// 设置矩阵初值
|
|
||||||
memcpy(Height_KF.P_data, P_Init, sizeof(P_Init));
|
|
||||||
memcpy(Height_KF.F_data, F_Init, sizeof(F_Init));
|
|
||||||
memcpy(Height_KF.Q_data, Q_Init, sizeof(Q_Init));
|
|
||||||
memcpy(Height_KF.measurement_map, measurement_reference,
|
|
||||||
sizeof(measurement_reference));
|
|
||||||
memcpy(Height_KF.measurement_degree, measurement_degree,
|
|
||||||
sizeof(measurement_degree));
|
|
||||||
memcpy(Height_KF.mat_r_diagonal_elements, mat_r_diagonal_elements,
|
|
||||||
sizeof(mat_r_diagonal_elements));
|
|
||||||
memcpy(Height_KF.state_min_variance, state_min_variance,
|
|
||||||
sizeof(state_min_variance));
|
|
||||||
}
|
|
||||||
|
|
||||||
void INS_Task(void const *pvParameters)
|
|
||||||
{
|
|
||||||
// 循环更新卡尔曼滤波器
|
|
||||||
KF_Update(&Height_KF);
|
|
||||||
vTaskDelay(ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 传感器回调函数示例:在数据就绪时更新 measured_vector
|
|
||||||
void Barometer_Read_Over(void)
|
|
||||||
{
|
|
||||||
......
|
|
||||||
INS_KF.measured_vector[0] = baro_height; // 气压计高度
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPS_Read_Over(void)
|
|
||||||
{
|
|
||||||
......
|
|
||||||
INS_KF.measured_vector[1] = GPS_height; // GPS高度
|
|
||||||
}
|
|
||||||
|
|
||||||
void Acc_Data_Process(void)
|
|
||||||
{
|
|
||||||
......
|
|
||||||
INS_KF.measured_vector[2] = acc.z; // Z轴加速度
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "kalman_filter.h"
|
|
||||||
|
|
||||||
/* USER INCLUDE BEGIN */
|
|
||||||
|
|
||||||
/* USER INCLUDE END */
|
|
||||||
|
|
||||||
/* USER DEFINE BEGIN */
|
|
||||||
|
|
||||||
/* USER DEFINE END */
|
|
||||||
|
|
||||||
/* 私有函数声明 */
|
|
||||||
static void KF_AdjustHKR(KF_t *kf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 初始化卡尔曼滤波器并分配矩阵内存
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @param xhat_size 状态向量维度
|
|
||||||
* @param u_size 控制向量维度(无控制输入时设为0)
|
|
||||||
* @param z_size 量测向量维度
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_Init(KF_t *kf, uint8_t xhat_size, uint8_t u_size, uint8_t z_size) {
|
|
||||||
if (kf == NULL) return -1;
|
|
||||||
|
|
||||||
kf->xhat_size = xhat_size;
|
|
||||||
kf->u_size = u_size;
|
|
||||||
kf->z_size = z_size;
|
|
||||||
|
|
||||||
kf->measurement_valid_num = 0;
|
|
||||||
|
|
||||||
/* 量测标志分配 */
|
|
||||||
kf->measurement_map = (uint8_t *)user_malloc(sizeof(uint8_t) * z_size);
|
|
||||||
memset(kf->measurement_map, 0, sizeof(uint8_t) * z_size);
|
|
||||||
|
|
||||||
kf->measurement_degree = (float *)user_malloc(sizeof(float) * z_size);
|
|
||||||
memset(kf->measurement_degree, 0, sizeof(float) * z_size);
|
|
||||||
|
|
||||||
kf->mat_r_diagonal_elements = (float *)user_malloc(sizeof(float) * z_size);
|
|
||||||
memset(kf->mat_r_diagonal_elements, 0, sizeof(float) * z_size);
|
|
||||||
|
|
||||||
kf->state_min_variance = (float *)user_malloc(sizeof(float) * xhat_size);
|
|
||||||
memset(kf->state_min_variance, 0, sizeof(float) * xhat_size);
|
|
||||||
|
|
||||||
kf->temp = (uint8_t *)user_malloc(sizeof(uint8_t) * z_size);
|
|
||||||
memset(kf->temp, 0, sizeof(uint8_t) * z_size);
|
|
||||||
|
|
||||||
/* 滤波数据分配 */
|
|
||||||
kf->filtered_value = (float *)user_malloc(sizeof(float) * xhat_size);
|
|
||||||
memset(kf->filtered_value, 0, sizeof(float) * xhat_size);
|
|
||||||
|
|
||||||
kf->measured_vector = (float *)user_malloc(sizeof(float) * z_size);
|
|
||||||
memset(kf->measured_vector, 0, sizeof(float) * z_size);
|
|
||||||
|
|
||||||
kf->control_vector = (float *)user_malloc(sizeof(float) * u_size);
|
|
||||||
memset(kf->control_vector, 0, sizeof(float) * u_size);
|
|
||||||
|
|
||||||
/* 状态估计 xhat x(k|k) */
|
|
||||||
kf->xhat_data = (float *)user_malloc(sizeof(float) * xhat_size);
|
|
||||||
memset(kf->xhat_data, 0, sizeof(float) * xhat_size);
|
|
||||||
KF_MatInit(&kf->xhat, kf->xhat_size, 1, kf->xhat_data);
|
|
||||||
|
|
||||||
/* 先验状态估计 xhatminus x(k|k-1) */
|
|
||||||
kf->xhatminus_data = (float *)user_malloc(sizeof(float) * xhat_size);
|
|
||||||
memset(kf->xhatminus_data, 0, sizeof(float) * xhat_size);
|
|
||||||
KF_MatInit(&kf->xhatminus, kf->xhat_size, 1, kf->xhatminus_data);
|
|
||||||
|
|
||||||
/* 控制向量 u */
|
|
||||||
if (u_size != 0) {
|
|
||||||
kf->u_data = (float *)user_malloc(sizeof(float) * u_size);
|
|
||||||
memset(kf->u_data, 0, sizeof(float) * u_size);
|
|
||||||
KF_MatInit(&kf->u, kf->u_size, 1, kf->u_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 量测向量 z */
|
|
||||||
kf->z_data = (float *)user_malloc(sizeof(float) * z_size);
|
|
||||||
memset(kf->z_data, 0, sizeof(float) * z_size);
|
|
||||||
KF_MatInit(&kf->z, kf->z_size, 1, kf->z_data);
|
|
||||||
|
|
||||||
/* 协方差矩阵 P(k|k) */
|
|
||||||
kf->P_data = (float *)user_malloc(sizeof(float) * xhat_size * xhat_size);
|
|
||||||
memset(kf->P_data, 0, sizeof(float) * xhat_size * xhat_size);
|
|
||||||
KF_MatInit(&kf->P, kf->xhat_size, kf->xhat_size, kf->P_data);
|
|
||||||
|
|
||||||
/* 先验协方差矩阵 P(k|k-1) */
|
|
||||||
kf->Pminus_data = (float *)user_malloc(sizeof(float) * xhat_size * xhat_size);
|
|
||||||
memset(kf->Pminus_data, 0, sizeof(float) * xhat_size * xhat_size);
|
|
||||||
KF_MatInit(&kf->Pminus, kf->xhat_size, kf->xhat_size, kf->Pminus_data);
|
|
||||||
|
|
||||||
/* 状态转移矩阵 F 及其转置 FT */
|
|
||||||
kf->F_data = (float *)user_malloc(sizeof(float) * xhat_size * xhat_size);
|
|
||||||
kf->FT_data = (float *)user_malloc(sizeof(float) * xhat_size * xhat_size);
|
|
||||||
memset(kf->F_data, 0, sizeof(float) * xhat_size * xhat_size);
|
|
||||||
memset(kf->FT_data, 0, sizeof(float) * xhat_size * xhat_size);
|
|
||||||
KF_MatInit(&kf->F, kf->xhat_size, kf->xhat_size, kf->F_data);
|
|
||||||
KF_MatInit(&kf->FT, kf->xhat_size, kf->xhat_size, kf->FT_data);
|
|
||||||
|
|
||||||
/* 控制矩阵 B */
|
|
||||||
if (u_size != 0) {
|
|
||||||
kf->B_data = (float *)user_malloc(sizeof(float) * xhat_size * u_size);
|
|
||||||
memset(kf->B_data, 0, sizeof(float) * xhat_size * u_size);
|
|
||||||
KF_MatInit(&kf->B, kf->xhat_size, kf->u_size, kf->B_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 量测矩阵 H 及其转置 HT */
|
|
||||||
kf->H_data = (float *)user_malloc(sizeof(float) * z_size * xhat_size);
|
|
||||||
kf->HT_data = (float *)user_malloc(sizeof(float) * xhat_size * z_size);
|
|
||||||
memset(kf->H_data, 0, sizeof(float) * z_size * xhat_size);
|
|
||||||
memset(kf->HT_data, 0, sizeof(float) * xhat_size * z_size);
|
|
||||||
KF_MatInit(&kf->H, kf->z_size, kf->xhat_size, kf->H_data);
|
|
||||||
KF_MatInit(&kf->HT, kf->xhat_size, kf->z_size, kf->HT_data);
|
|
||||||
|
|
||||||
/* 过程噪声协方差矩阵 Q */
|
|
||||||
kf->Q_data = (float *)user_malloc(sizeof(float) * xhat_size * xhat_size);
|
|
||||||
memset(kf->Q_data, 0, sizeof(float) * xhat_size * xhat_size);
|
|
||||||
KF_MatInit(&kf->Q, kf->xhat_size, kf->xhat_size, kf->Q_data);
|
|
||||||
|
|
||||||
/* 量测噪声协方差矩阵 R */
|
|
||||||
kf->R_data = (float *)user_malloc(sizeof(float) * z_size * z_size);
|
|
||||||
memset(kf->R_data, 0, sizeof(float) * z_size * z_size);
|
|
||||||
KF_MatInit(&kf->R, kf->z_size, kf->z_size, kf->R_data);
|
|
||||||
|
|
||||||
/* 卡尔曼增益 K */
|
|
||||||
kf->K_data = (float *)user_malloc(sizeof(float) * xhat_size * z_size);
|
|
||||||
memset(kf->K_data, 0, sizeof(float) * xhat_size * z_size);
|
|
||||||
KF_MatInit(&kf->K, kf->xhat_size, kf->z_size, kf->K_data);
|
|
||||||
|
|
||||||
/* 临时矩阵分配 */
|
|
||||||
kf->S_data = (float *)user_malloc(sizeof(float) * xhat_size * xhat_size);
|
|
||||||
kf->temp_matrix_data =
|
|
||||||
(float *)user_malloc(sizeof(float) * xhat_size * xhat_size);
|
|
||||||
kf->temp_matrix_data1 =
|
|
||||||
(float *)user_malloc(sizeof(float) * xhat_size * xhat_size);
|
|
||||||
kf->temp_vector_data = (float *)user_malloc(sizeof(float) * xhat_size);
|
|
||||||
kf->temp_vector_data1 = (float *)user_malloc(sizeof(float) * xhat_size);
|
|
||||||
|
|
||||||
KF_MatInit(&kf->S, kf->xhat_size, kf->xhat_size, kf->S_data);
|
|
||||||
KF_MatInit(&kf->temp_matrix, kf->xhat_size, kf->xhat_size,
|
|
||||||
kf->temp_matrix_data);
|
|
||||||
KF_MatInit(&kf->temp_matrix1, kf->xhat_size, kf->xhat_size,
|
|
||||||
kf->temp_matrix_data1);
|
|
||||||
KF_MatInit(&kf->temp_vector, kf->xhat_size, 1, kf->temp_vector_data);
|
|
||||||
KF_MatInit(&kf->temp_vector1, kf->xhat_size, 1, kf->temp_vector_data1);
|
|
||||||
|
|
||||||
/* 初始化跳过标志 */
|
|
||||||
kf->skip_eq1 = 0;
|
|
||||||
kf->skip_eq2 = 0;
|
|
||||||
kf->skip_eq3 = 0;
|
|
||||||
kf->skip_eq4 = 0;
|
|
||||||
kf->skip_eq5 = 0;
|
|
||||||
|
|
||||||
/* 初始化用户函数指针 */
|
|
||||||
kf->User_Func0_f = NULL;
|
|
||||||
kf->User_Func1_f = NULL;
|
|
||||||
kf->User_Func2_f = NULL;
|
|
||||||
kf->User_Func3_f = NULL;
|
|
||||||
kf->User_Func4_f = NULL;
|
|
||||||
kf->User_Func5_f = NULL;
|
|
||||||
kf->User_Func6_f = NULL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取量测并在启用自动调整时调整矩阵
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_Measure(KF_t *kf) {
|
|
||||||
if (kf == NULL) return -1;
|
|
||||||
|
|
||||||
/* 根据量测有效性自动调整 H, K, R 矩阵 */
|
|
||||||
if (kf->use_auto_adjustment != 0) {
|
|
||||||
KF_AdjustHKR(kf);
|
|
||||||
} else {
|
|
||||||
memcpy(kf->z_data, kf->measured_vector, sizeof(float) * kf->z_size);
|
|
||||||
memset(kf->measured_vector, 0, sizeof(float) * kf->z_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(kf->u_data, kf->control_vector, sizeof(float) * kf->u_size);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤1:先验状态估计 - xhat'(k) = F·xhat(k-1) + B·u
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_PredictState(KF_t *kf) {
|
|
||||||
if (kf == NULL) return -1;
|
|
||||||
|
|
||||||
if (!kf->skip_eq1) {
|
|
||||||
if (kf->u_size > 0) {
|
|
||||||
/* 有控制输入: xhat'(k) = F·xhat(k-1) + B·u */
|
|
||||||
kf->temp_vector.numRows = kf->xhat_size;
|
|
||||||
kf->temp_vector.numCols = 1;
|
|
||||||
kf->mat_status = KF_MatMult(&kf->F, &kf->xhat, &kf->temp_vector);
|
|
||||||
|
|
||||||
kf->temp_vector1.numRows = kf->xhat_size;
|
|
||||||
kf->temp_vector1.numCols = 1;
|
|
||||||
kf->mat_status = KF_MatMult(&kf->B, &kf->u, &kf->temp_vector1);
|
|
||||||
kf->mat_status =
|
|
||||||
KF_MatAdd(&kf->temp_vector, &kf->temp_vector1, &kf->xhatminus);
|
|
||||||
} else {
|
|
||||||
/* 无控制输入: xhat'(k) = F·xhat(k-1) */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->F, &kf->xhat, &kf->xhatminus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤2:先验协方差 - P'(k) = F·P(k-1)·F^T + Q
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_PredictCovariance(KF_t *kf) {
|
|
||||||
if (kf == NULL) return -1;
|
|
||||||
|
|
||||||
if (!kf->skip_eq2) {
|
|
||||||
kf->mat_status = KF_MatTrans(&kf->F, &kf->FT);
|
|
||||||
kf->mat_status = KF_MatMult(&kf->F, &kf->P, &kf->Pminus);
|
|
||||||
kf->temp_matrix.numRows = kf->Pminus.numRows;
|
|
||||||
kf->temp_matrix.numCols = kf->FT.numCols;
|
|
||||||
/* F·P(k-1)·F^T */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->Pminus, &kf->FT, &kf->temp_matrix);
|
|
||||||
kf->mat_status = KF_MatAdd(&kf->temp_matrix, &kf->Q, &kf->Pminus);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤3:卡尔曼增益 - K = P'(k)·H^T / (H·P'(k)·H^T + R)
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_CalcGain(KF_t *kf) {
|
|
||||||
if (kf == NULL) return -1;
|
|
||||||
|
|
||||||
if (!kf->skip_eq3) {
|
|
||||||
kf->mat_status = KF_MatTrans(&kf->H, &kf->HT);
|
|
||||||
kf->temp_matrix.numRows = kf->H.numRows;
|
|
||||||
kf->temp_matrix.numCols = kf->Pminus.numCols;
|
|
||||||
/* H·P'(k) */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->H, &kf->Pminus, &kf->temp_matrix);
|
|
||||||
kf->temp_matrix1.numRows = kf->temp_matrix.numRows;
|
|
||||||
kf->temp_matrix1.numCols = kf->HT.numCols;
|
|
||||||
/* H·P'(k)·H^T */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->temp_matrix, &kf->HT, &kf->temp_matrix1);
|
|
||||||
kf->S.numRows = kf->R.numRows;
|
|
||||||
kf->S.numCols = kf->R.numCols;
|
|
||||||
/* S = H·P'(k)·H^T + R */
|
|
||||||
kf->mat_status = KF_MatAdd(&kf->temp_matrix1, &kf->R, &kf->S);
|
|
||||||
/* S^-1 */
|
|
||||||
kf->mat_status = KF_MatInv(&kf->S, &kf->temp_matrix1);
|
|
||||||
kf->temp_matrix.numRows = kf->Pminus.numRows;
|
|
||||||
kf->temp_matrix.numCols = kf->HT.numCols;
|
|
||||||
/* P'(k)·H^T */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->Pminus, &kf->HT, &kf->temp_matrix);
|
|
||||||
/* K = P'(k)·H^T·S^-1 */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->temp_matrix, &kf->temp_matrix1, &kf->K);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤4:状态更新 - xhat(k) = xhat'(k) + K·(z - H·xhat'(k))
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_UpdateState(KF_t *kf) {
|
|
||||||
if (kf == NULL) return -1;
|
|
||||||
|
|
||||||
if (!kf->skip_eq4) {
|
|
||||||
kf->temp_vector.numRows = kf->H.numRows;
|
|
||||||
kf->temp_vector.numCols = 1;
|
|
||||||
/* H·xhat'(k) */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->H, &kf->xhatminus, &kf->temp_vector);
|
|
||||||
kf->temp_vector1.numRows = kf->z.numRows;
|
|
||||||
kf->temp_vector1.numCols = 1;
|
|
||||||
/* 新息: z - H·xhat'(k) */
|
|
||||||
kf->mat_status = KF_MatSub(&kf->z, &kf->temp_vector, &kf->temp_vector1);
|
|
||||||
kf->temp_vector.numRows = kf->K.numRows;
|
|
||||||
kf->temp_vector.numCols = 1;
|
|
||||||
/* K·新息 */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->K, &kf->temp_vector1, &kf->temp_vector);
|
|
||||||
/* xhat = xhat' + K·新息 */
|
|
||||||
kf->mat_status = KF_MatAdd(&kf->xhatminus, &kf->temp_vector, &kf->xhat);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤5:协方差更新 - P(k) = P'(k) - K·H·P'(k)
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_UpdateCovariance(KF_t *kf) {
|
|
||||||
if (kf == NULL) return -1;
|
|
||||||
|
|
||||||
if (!kf->skip_eq5) {
|
|
||||||
kf->temp_matrix.numRows = kf->K.numRows;
|
|
||||||
kf->temp_matrix.numCols = kf->H.numCols;
|
|
||||||
kf->temp_matrix1.numRows = kf->temp_matrix.numRows;
|
|
||||||
kf->temp_matrix1.numCols = kf->Pminus.numCols;
|
|
||||||
/* K·H */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->K, &kf->H, &kf->temp_matrix);
|
|
||||||
/* K·H·P'(k) */
|
|
||||||
kf->mat_status = KF_MatMult(&kf->temp_matrix, &kf->Pminus, &kf->temp_matrix1);
|
|
||||||
/* P = P' - K·H·P' */
|
|
||||||
kf->mat_status = KF_MatSub(&kf->Pminus, &kf->temp_matrix1, &kf->P);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 执行完整的卡尔曼滤波周期(五大方程)
|
|
||||||
*
|
|
||||||
* 实现标准KF,并支持用户自定义函数钩子用于扩展(EKF/UKF/ESKF/AUKF)。
|
|
||||||
* 每个步骤都可以通过 User_Func 回调函数替换。
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return float* 滤波后的状态估计值指针
|
|
||||||
*/
|
|
||||||
float *KF_Update(KF_t *kf) {
|
|
||||||
if (kf == NULL) return NULL;
|
|
||||||
|
|
||||||
/* 步骤0: 量测获取和矩阵调整 */
|
|
||||||
KF_Measure(kf);
|
|
||||||
if (kf->User_Func0_f != NULL) kf->User_Func0_f(kf);
|
|
||||||
|
|
||||||
/* 步骤1: 先验状态估计 - xhat'(k) = F·xhat(k-1) + B·u */
|
|
||||||
KF_PredictState(kf);
|
|
||||||
if (kf->User_Func1_f != NULL) kf->User_Func1_f(kf);
|
|
||||||
|
|
||||||
/* 步骤2: 先验协方差 - P'(k) = F·P(k-1)·F^T + Q */
|
|
||||||
KF_PredictCovariance(kf);
|
|
||||||
if (kf->User_Func2_f != NULL) kf->User_Func2_f(kf);
|
|
||||||
|
|
||||||
/* 量测更新(仅在存在有效量测时执行) */
|
|
||||||
if (kf->measurement_valid_num != 0 || kf->use_auto_adjustment == 0) {
|
|
||||||
/* 步骤3: 卡尔曼增益 - K = P'(k)·H^T / (H·P'(k)·H^T + R) */
|
|
||||||
KF_CalcGain(kf);
|
|
||||||
if (kf->User_Func3_f != NULL) kf->User_Func3_f(kf);
|
|
||||||
|
|
||||||
/* 步骤4: 状态更新 - xhat(k) = xhat'(k) + K·(z - H·xhat'(k)) */
|
|
||||||
KF_UpdateState(kf);
|
|
||||||
if (kf->User_Func4_f != NULL) kf->User_Func4_f(kf);
|
|
||||||
|
|
||||||
/* 步骤5: 协方差更新 - P(k) = P'(k) - K·H·P'(k) */
|
|
||||||
KF_UpdateCovariance(kf);
|
|
||||||
} else {
|
|
||||||
/* 无有效量测 - 仅预测 */
|
|
||||||
memcpy(kf->xhat_data, kf->xhatminus_data, sizeof(float) * kf->xhat_size);
|
|
||||||
memcpy(kf->P_data, kf->Pminus_data,
|
|
||||||
sizeof(float) * kf->xhat_size * kf->xhat_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 后处理钩子 */
|
|
||||||
if (kf->User_Func5_f != NULL) kf->User_Func5_f(kf);
|
|
||||||
|
|
||||||
/* 防过度收敛:强制最小方差 */
|
|
||||||
for (uint8_t i = 0; i < kf->xhat_size; i++) {
|
|
||||||
if (kf->P_data[i * kf->xhat_size + i] < kf->state_min_variance[i])
|
|
||||||
kf->P_data[i * kf->xhat_size + i] = kf->state_min_variance[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 复制结果到输出 */
|
|
||||||
memcpy(kf->filtered_value, kf->xhat_data, sizeof(float) * kf->xhat_size);
|
|
||||||
|
|
||||||
/* 附加后处理钩子 */
|
|
||||||
if (kf->User_Func6_f != NULL) kf->User_Func6_f(kf);
|
|
||||||
|
|
||||||
return kf->filtered_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 重置卡尔曼滤波器状态
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
*/
|
|
||||||
void KF_Reset(KF_t *kf) {
|
|
||||||
if (kf == NULL) return;
|
|
||||||
|
|
||||||
memset(kf->xhat_data, 0, sizeof(float) * kf->xhat_size);
|
|
||||||
memset(kf->xhatminus_data, 0, sizeof(float) * kf->xhat_size);
|
|
||||||
memset(kf->filtered_value, 0, sizeof(float) * kf->xhat_size);
|
|
||||||
kf->measurement_valid_num = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 根据量测有效性动态调整 H, R, K 矩阵
|
|
||||||
*
|
|
||||||
* 该函数根据当前周期中哪些量测有效(非零)来重建量测相关矩阵。
|
|
||||||
* 支持具有不同采样率的异步传感器。
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
*/
|
|
||||||
static void KF_AdjustHKR(KF_t *kf) {
|
|
||||||
kf->measurement_valid_num = 0;
|
|
||||||
|
|
||||||
/* 复制并重置量测向量 */
|
|
||||||
memcpy(kf->z_data, kf->measured_vector, sizeof(float) * kf->z_size);
|
|
||||||
memset(kf->measured_vector, 0, sizeof(float) * kf->z_size);
|
|
||||||
|
|
||||||
/* 清空 H 和 R 矩阵 */
|
|
||||||
memset(kf->R_data, 0, sizeof(float) * kf->z_size * kf->z_size);
|
|
||||||
memset(kf->H_data, 0, sizeof(float) * kf->xhat_size * kf->z_size);
|
|
||||||
|
|
||||||
/* 识别有效量测并重建 z, H */
|
|
||||||
for (uint8_t i = 0; i < kf->z_size; i++) {
|
|
||||||
if (kf->z_data[i] != 0) { /* 非零表示有效量测 */
|
|
||||||
/* 将有效量测压缩到 z */
|
|
||||||
kf->z_data[kf->measurement_valid_num] = kf->z_data[i];
|
|
||||||
kf->temp[kf->measurement_valid_num] = i;
|
|
||||||
|
|
||||||
/* 重建 H 矩阵行 */
|
|
||||||
kf->H_data[kf->xhat_size * kf->measurement_valid_num +
|
|
||||||
kf->measurement_map[i] - 1] = kf->measurement_degree[i];
|
|
||||||
kf->measurement_valid_num++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 用有效量测方差重建 R 矩阵 */
|
|
||||||
for (uint8_t i = 0; i < kf->measurement_valid_num; i++) {
|
|
||||||
kf->R_data[i * kf->measurement_valid_num + i] =
|
|
||||||
kf->mat_r_diagonal_elements[kf->temp[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 调整矩阵维度以匹配有效量测数量 */
|
|
||||||
kf->H.numRows = kf->measurement_valid_num;
|
|
||||||
kf->H.numCols = kf->xhat_size;
|
|
||||||
kf->HT.numRows = kf->xhat_size;
|
|
||||||
kf->HT.numCols = kf->measurement_valid_num;
|
|
||||||
kf->R.numRows = kf->measurement_valid_num;
|
|
||||||
kf->R.numCols = kf->measurement_valid_num;
|
|
||||||
kf->K.numRows = kf->xhat_size;
|
|
||||||
kf->K.numCols = kf->measurement_valid_num;
|
|
||||||
kf->z.numRows = kf->measurement_valid_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* USER FUNCTION BEGIN */
|
|
||||||
|
|
||||||
/* USER FUNCTION END */
|
|
||||||
@ -1,199 +0,0 @@
|
|||||||
/*
|
|
||||||
卡尔曼滤波器
|
|
||||||
支持动态量测调整,使用ARM CMSIS DSP优化矩阵运算
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "arm_math.h"
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* USER INCLUDE BEGIN */
|
|
||||||
|
|
||||||
/* USER INCLUDE END */
|
|
||||||
|
|
||||||
/* USER DEFINE BEGIN */
|
|
||||||
|
|
||||||
/* USER DEFINE END */
|
|
||||||
|
|
||||||
/* 内存分配配置 */
|
|
||||||
#ifndef user_malloc
|
|
||||||
#ifdef _CMSIS_OS_H
|
|
||||||
#define user_malloc pvPortMalloc /* FreeRTOS堆分配 */
|
|
||||||
#else
|
|
||||||
#define user_malloc malloc /* 标准C库分配 */
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ARM CMSIS DSP 矩阵运算别名 */
|
|
||||||
#define KF_Mat arm_matrix_instance_f32
|
|
||||||
#define KF_MatInit arm_mat_init_f32
|
|
||||||
#define KF_MatAdd arm_mat_add_f32
|
|
||||||
#define KF_MatSub arm_mat_sub_f32
|
|
||||||
#define KF_MatMult arm_mat_mult_f32
|
|
||||||
#define KF_MatTrans arm_mat_trans_f32
|
|
||||||
#define KF_MatInv arm_mat_inverse_f32
|
|
||||||
|
|
||||||
/* 卡尔曼滤波器主结构体 */
|
|
||||||
typedef struct KF_s {
|
|
||||||
/* 输出和输入向量 */
|
|
||||||
float *filtered_value; /* 滤波后的状态估计输出 */
|
|
||||||
float *measured_vector; /* 量测输入向量 */
|
|
||||||
float *control_vector; /* 控制输入向量 */
|
|
||||||
|
|
||||||
/* 维度 */
|
|
||||||
uint8_t xhat_size; /* 状态向量维度 */
|
|
||||||
uint8_t u_size; /* 控制向量维度 */
|
|
||||||
uint8_t z_size; /* 量测向量维度 */
|
|
||||||
|
|
||||||
/* 自动调整参数 */
|
|
||||||
uint8_t use_auto_adjustment; /* 启用动态 H/R/K 调整 */
|
|
||||||
uint8_t measurement_valid_num; /* 有效量测数量 */
|
|
||||||
|
|
||||||
/* 量测配置 */
|
|
||||||
uint8_t *measurement_map; /* 量测到状态的映射 */
|
|
||||||
float *measurement_degree; /* 每个量测的H矩阵元素值 */
|
|
||||||
float *mat_r_diagonal_elements; /* 量测噪声方差(R对角线) */
|
|
||||||
float *state_min_variance; /* 最小状态方差(防过度收敛) */
|
|
||||||
uint8_t *temp; /* 临时缓冲区 */
|
|
||||||
|
|
||||||
/* 方程跳过标志(用于自定义用户函数) */
|
|
||||||
uint8_t skip_eq1, skip_eq2, skip_eq3, skip_eq4, skip_eq5;
|
|
||||||
|
|
||||||
/* 卡尔曼滤波器矩阵 */
|
|
||||||
KF_Mat xhat; /* 状态估计 x(k|k) */
|
|
||||||
KF_Mat xhatminus; /* 先验状态估计 x(k|k-1) */
|
|
||||||
KF_Mat u; /* 控制向量 */
|
|
||||||
KF_Mat z; /* 量测向量 */
|
|
||||||
KF_Mat P; /* 后验误差协方差 P(k|k) */
|
|
||||||
KF_Mat Pminus; /* 先验误差协方差 P(k|k-1) */
|
|
||||||
KF_Mat F, FT; /* 状态转移矩阵及其转置 */
|
|
||||||
KF_Mat B; /* 控制矩阵 */
|
|
||||||
KF_Mat H, HT; /* 量测矩阵及其转置 */
|
|
||||||
KF_Mat Q; /* 过程噪声协方差 */
|
|
||||||
KF_Mat R; /* 量测噪声协方差 */
|
|
||||||
KF_Mat K; /* 卡尔曼增益 */
|
|
||||||
KF_Mat S; /* 临时矩阵 S */
|
|
||||||
KF_Mat temp_matrix, temp_matrix1; /* 临时矩阵 */
|
|
||||||
KF_Mat temp_vector, temp_vector1; /* 临时向量 */
|
|
||||||
|
|
||||||
int8_t mat_status; /* 矩阵运算状态 */
|
|
||||||
|
|
||||||
/* 用户自定义函数指针(用于EKF/UKF/ESKF扩展) */
|
|
||||||
void (*User_Func0_f)(struct KF_s *kf); /* 自定义量测处理 */
|
|
||||||
void (*User_Func1_f)(struct KF_s *kf); /* 自定义状态预测 */
|
|
||||||
void (*User_Func2_f)(struct KF_s *kf); /* 自定义协方差预测 */
|
|
||||||
void (*User_Func3_f)(struct KF_s *kf); /* 自定义卡尔曼增益计算 */
|
|
||||||
void (*User_Func4_f)(struct KF_s *kf); /* 自定义状态更新 */
|
|
||||||
void (*User_Func5_f)(struct KF_s *kf); /* 自定义后处理 */
|
|
||||||
void (*User_Func6_f)(struct KF_s *kf); /* 附加自定义函数 */
|
|
||||||
|
|
||||||
/* 矩阵数据存储指针 */
|
|
||||||
float *xhat_data, *xhatminus_data;
|
|
||||||
float *u_data;
|
|
||||||
float *z_data;
|
|
||||||
float *P_data, *Pminus_data;
|
|
||||||
float *F_data, *FT_data;
|
|
||||||
float *B_data;
|
|
||||||
float *H_data, *HT_data;
|
|
||||||
float *Q_data;
|
|
||||||
float *R_data;
|
|
||||||
float *K_data;
|
|
||||||
float *S_data;
|
|
||||||
float *temp_matrix_data, *temp_matrix_data1;
|
|
||||||
float *temp_vector_data, *temp_vector_data1;
|
|
||||||
} KF_t;
|
|
||||||
|
|
||||||
/* USER STRUCT BEGIN */
|
|
||||||
|
|
||||||
/* USER STRUCT END */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 初始化卡尔曼滤波器并分配矩阵内存
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @param xhat_size 状态向量维度
|
|
||||||
* @param u_size 控制向量维度(无控制输入时设为0)
|
|
||||||
* @param z_size 量测向量维度
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_Init(KF_t *kf, uint8_t xhat_size, uint8_t u_size, uint8_t z_size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取量测并在启用自动调整时调整矩阵
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_Measure(KF_t *kf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤1:先验状态估计 - xhat'(k) = F·xhat(k-1) + B·u
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_PredictState(KF_t *kf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤2:先验协方差 - P'(k) = F·P(k-1)·F^T + Q
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_PredictCovariance(KF_t *kf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤3:卡尔曼增益 - K = P'(k)·H^T / (H·P'(k)·H^T + R)
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_CalcGain(KF_t *kf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤4:状态更新 - xhat(k) = xhat'(k) + K·(z - H·xhat'(k))
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_UpdateState(KF_t *kf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 步骤5:协方差更新 - P(k) = P'(k) - K·H·P'(k)
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return int8_t 0对应没有错误
|
|
||||||
*/
|
|
||||||
int8_t KF_UpdateCovariance(KF_t *kf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 执行完整的卡尔曼滤波周期(五大方程)
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
* @return float* 滤波后的状态估计值指针
|
|
||||||
*/
|
|
||||||
float *KF_Update(KF_t *kf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 重置卡尔曼滤波器状态
|
|
||||||
*
|
|
||||||
* @param kf 卡尔曼滤波器结构体指针
|
|
||||||
*/
|
|
||||||
void KF_Reset(KF_t *kf);
|
|
||||||
|
|
||||||
/* USER FUNCTION BEGIN */
|
|
||||||
|
|
||||||
/* USER FUNCTION END */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -105,8 +105,3 @@ float HeatLimit_ShootFreq(float heat, float heat_limit, float cooling_rate,
|
|||||||
else
|
else
|
||||||
return (heat_percent > 0.7f) ? stable_freq : 3.0f * stable_freq;
|
return (heat_percent > 0.7f) ? stable_freq : 3.0f * stable_freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* USER CODE BEGIN */
|
|
||||||
|
|
||||||
/* USER CODE END */
|
|
||||||
@ -61,7 +61,3 @@ float PowerLimit_TargetPower(float power_limit, float power_buffer);
|
|||||||
*/
|
*/
|
||||||
float HeatLimit_ShootFreq(float heat, float heat_limit, float cooling_rate,
|
float HeatLimit_ShootFreq(float heat, float heat_limit, float cooling_rate,
|
||||||
float heat_increase, bool is_big);
|
float heat_increase, bool is_big);
|
||||||
|
|
||||||
/* USER CODE BEGIN */
|
|
||||||
|
|
||||||
/* USER CODE END */
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
bsp,can,fdcan,dwt,gpio,i2c,mm,spi,uart,pwm,time,flash
|
bsp,can,fdcan,dwt,gpio,i2c,mm,spi,uart,pwm,time,flash
|
||||||
component,ahrs,capacity,cmd,crc8,crc16,error_detect,filter,FreeRTOS_CLI,limiter,mixer,pid,ui,user_math
|
component,ahrs,capacity,cmd,crc8,crc16,error_detect,filter,FreeRTOS_CLI,limiter,mixer,pid,ui,user_math
|
||||||
device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9,oid,lcd_driver,mrobot
|
device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9,oid,lcd_driver
|
||||||
module,
|
module,
|
||||||
|
@ -260,18 +260,3 @@ devices:
|
|||||||
files:
|
files:
|
||||||
header: "lcd.h"
|
header: "lcd.h"
|
||||||
source: "lcd.c"
|
source: "lcd.c"
|
||||||
|
|
||||||
mrobot:
|
|
||||||
name: "MRobot CLI"
|
|
||||||
description: "基于 FreeRTOS CLI 的嵌入式调试命令行系统,支持设备注册与监控、类 Unix 文件系统命令、htop 风格任务监控等"
|
|
||||||
dependencies:
|
|
||||||
bsp: ["uart", "mm"]
|
|
||||||
component: ["freertos_cli"]
|
|
||||||
bsp_requirements:
|
|
||||||
- type: "uart"
|
|
||||||
var_name: "BSP_UART_MROBOT"
|
|
||||||
description: "用于 MRobot CLI 命令行交互"
|
|
||||||
thread_signals: []
|
|
||||||
files:
|
|
||||||
header: "mrobot.h"
|
|
||||||
source: "mrobot.c"
|
|
||||||
@ -111,21 +111,11 @@ static int8_t MOTOR_DM_SendMITCmd(MOTOR_DM_t *motor, MOTOR_MIT_Output_t *output)
|
|||||||
uint16_t pos_tmp,vel_tmp,kp_tmp,kd_tmp,tor_tmp;
|
uint16_t pos_tmp,vel_tmp,kp_tmp,kd_tmp,tor_tmp;
|
||||||
uint16_t id = motor->param.can_id;
|
uint16_t id = motor->param.can_id;
|
||||||
|
|
||||||
/* 根据 reverse 参数调整控制值 */
|
pos_tmp = float_to_uint(output->angle, DM_P_MIN , DM_P_MAX, 16);
|
||||||
float angle = output->angle;
|
vel_tmp = float_to_uint(output->velocity, DM_V_MIN , DM_V_MAX, 12);
|
||||||
float velocity = output->velocity;
|
|
||||||
float torque = output->torque;
|
|
||||||
if (motor->param.reverse) {
|
|
||||||
angle = -angle;
|
|
||||||
velocity = -velocity;
|
|
||||||
torque = -torque;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos_tmp = float_to_uint(angle, DM_P_MIN , DM_P_MAX, 16);
|
|
||||||
vel_tmp = float_to_uint(velocity, DM_V_MIN , DM_V_MAX, 12);
|
|
||||||
kp_tmp = float_to_uint(output->kp, DM_KP_MIN, DM_KP_MAX, 12);
|
kp_tmp = float_to_uint(output->kp, DM_KP_MIN, DM_KP_MAX, 12);
|
||||||
kd_tmp = float_to_uint(output->kd, DM_KD_MIN, DM_KD_MAX, 12);
|
kd_tmp = float_to_uint(output->kd, DM_KD_MIN, DM_KD_MAX, 12);
|
||||||
tor_tmp = float_to_uint(torque, DM_T_MIN , DM_T_MAX, 12);
|
tor_tmp = float_to_uint(output->torque, DM_T_MIN , DM_T_MAX, 12);
|
||||||
|
|
||||||
/* 打包数据 */
|
/* 打包数据 */
|
||||||
data[0] = (pos_tmp >> 8);
|
data[0] = (pos_tmp >> 8);
|
||||||
@ -161,11 +151,6 @@ static int8_t MOTOR_DM_SendPosVelCmd(MOTOR_DM_t *motor, float pos, float vel) {
|
|||||||
|
|
||||||
uint8_t data[8] = {0};
|
uint8_t data[8] = {0};
|
||||||
|
|
||||||
/* 根据 reverse 参数调整控制值 */
|
|
||||||
if (motor->param.reverse) {
|
|
||||||
pos = -pos;
|
|
||||||
vel = -vel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 直接发送浮点数数据 */
|
/* 直接发送浮点数数据 */
|
||||||
memcpy(&data[0], &pos, 4); // 位置,低位在前
|
memcpy(&data[0], &pos, 4); // 位置,低位在前
|
||||||
@ -194,11 +179,6 @@ static int8_t MOTOR_DM_SendVelCmd(MOTOR_DM_t *motor, float vel) {
|
|||||||
|
|
||||||
uint8_t data[4] = {0};
|
uint8_t data[4] = {0};
|
||||||
|
|
||||||
/* 根据 reverse 参数调整控制值 */
|
|
||||||
if (motor->param.reverse) {
|
|
||||||
vel = -vel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 直接发送浮点数数据 */
|
/* 直接发送浮点数数据 */
|
||||||
memcpy(&data[0], &vel, 4); // 速度,低位在前
|
memcpy(&data[0], &vel, 4); // 速度,低位在前
|
||||||
|
|
||||||
|
|||||||
@ -1,874 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file mrobot.c
|
|
||||||
* @brief MRobot CLI 实现
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Includes ----------------------------------------------------------------- */
|
|
||||||
#include "device/mrobot.h"
|
|
||||||
#include "component/freertos_cli.h"
|
|
||||||
#include "bsp/uart.h"
|
|
||||||
#include "bsp/mm.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <FreeRTOS.h>
|
|
||||||
#include <task.h>
|
|
||||||
#include <semphr.h>
|
|
||||||
#include <cmsis_os2.h>
|
|
||||||
|
|
||||||
/* Private constants -------------------------------------------------------- */
|
|
||||||
static const char *const CLI_WELCOME_MESSAGE =
|
|
||||||
"\r\n"
|
|
||||||
" __ __ _____ _ _ \r\n"
|
|
||||||
" | \\/ | __ \\ | | | | \r\n"
|
|
||||||
" | \\ / | |__) |___ | |__ ___ | |_ \r\n"
|
|
||||||
" | |\\/| | _ // _ \\| '_ \\ / _ \\| __|\r\n"
|
|
||||||
" | | | | | \\ \\ (_) | |_) | (_) | |_ \r\n"
|
|
||||||
" |_| |_|_| \\_\\___/|_.__/ \\___/ \\__|\r\n"
|
|
||||||
" ------------------------------------\r\n"
|
|
||||||
" Welcome to use MRobot CLI. Type 'help' to view a list of registered commands.\r\n"
|
|
||||||
"\r\n";
|
|
||||||
|
|
||||||
/* ANSI 转义序列 */
|
|
||||||
#define ANSI_CLEAR_SCREEN "\033[2J\033[H"
|
|
||||||
#define ANSI_CURSOR_HOME "\033[H"
|
|
||||||
#define ANSI_BACKSPACE "\b \b"
|
|
||||||
|
|
||||||
/* Private types ------------------------------------------------------------ */
|
|
||||||
/* CLI 上下文结构体 - 封装所有状态 */
|
|
||||||
typedef struct {
|
|
||||||
/* 设备管理 */
|
|
||||||
MRobot_Device_t devices[MROBOT_MAX_DEVICES];
|
|
||||||
uint8_t device_count;
|
|
||||||
|
|
||||||
/* 自定义命令 */
|
|
||||||
CLI_Command_Definition_t *custom_cmds[MROBOT_MAX_CUSTOM_COMMANDS];
|
|
||||||
uint8_t custom_cmd_count;
|
|
||||||
|
|
||||||
/* CLI 状态 */
|
|
||||||
MRobot_State_t state;
|
|
||||||
char current_path[MROBOT_PATH_MAX_LEN];
|
|
||||||
|
|
||||||
/* 命令缓冲区 */
|
|
||||||
uint8_t cmd_buffer[MROBOT_CMD_BUFFER_SIZE];
|
|
||||||
volatile uint8_t cmd_index;
|
|
||||||
volatile bool cmd_ready;
|
|
||||||
|
|
||||||
/* UART 相关 */
|
|
||||||
uint8_t uart_rx_char;
|
|
||||||
volatile bool tx_complete;
|
|
||||||
volatile bool htop_exit;
|
|
||||||
|
|
||||||
/* 输出缓冲区 */
|
|
||||||
char output_buffer[MROBOT_OUTPUT_BUFFER_SIZE];
|
|
||||||
|
|
||||||
/* 初始化标志 */
|
|
||||||
bool initialized;
|
|
||||||
|
|
||||||
/* 互斥锁 */
|
|
||||||
SemaphoreHandle_t mutex;
|
|
||||||
} MRobot_Context_t;
|
|
||||||
|
|
||||||
/* Private variables -------------------------------------------------------- */
|
|
||||||
static MRobot_Context_t ctx = {
|
|
||||||
.device_count = 0,
|
|
||||||
.custom_cmd_count = 0,
|
|
||||||
.state = MROBOT_STATE_IDLE,
|
|
||||||
.current_path = "/",
|
|
||||||
.cmd_index = 0,
|
|
||||||
.cmd_ready = false,
|
|
||||||
.tx_complete = true,
|
|
||||||
.htop_exit = false,
|
|
||||||
.initialized = false,
|
|
||||||
.mutex = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Private function prototypes ---------------------------------------------- */
|
|
||||||
/* 命令处理函数 */
|
|
||||||
static BaseType_t cmd_help(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
|
|
||||||
static BaseType_t cmd_htop(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
|
|
||||||
static BaseType_t cmd_cd(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
|
|
||||||
static BaseType_t cmd_ls(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
|
|
||||||
static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
|
|
||||||
|
|
||||||
/* 内部辅助函数 */
|
|
||||||
static void uart_tx_callback(void);
|
|
||||||
static void uart_rx_callback(void);
|
|
||||||
static void send_string(const char *str);
|
|
||||||
static void send_prompt(void);
|
|
||||||
static int format_float_va(char *buf, size_t size, const char *fmt, va_list args);
|
|
||||||
|
|
||||||
/* CLI 命令定义表 */
|
|
||||||
static const CLI_Command_Definition_t builtin_commands[] = {
|
|
||||||
{ "help", " --help: 显示所有可用命令\r\n", cmd_help, 0 },
|
|
||||||
{ "htop", " --htop: 动态显示 FreeRTOS 任务状态 (按 'q' 退出)\r\n", cmd_htop, 0 },
|
|
||||||
{ "cd", " --cd <path>: 切换目录\r\n", cmd_cd, 1 },
|
|
||||||
{ "ls", " --ls: 列出当前目录内容\r\n", cmd_ls, 0 },
|
|
||||||
{ "show", " --show [device] [count]: 显示设备信息\r\n", cmd_show, -1 },
|
|
||||||
};
|
|
||||||
#define BUILTIN_CMD_COUNT (sizeof(builtin_commands) / sizeof(builtin_commands[0]))
|
|
||||||
|
|
||||||
/* ========================================================================== */
|
|
||||||
/* 辅助函数实现 */
|
|
||||||
/* ========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 发送字符串到 UART(阻塞等待完成)
|
|
||||||
*/
|
|
||||||
static void send_string(const char *str) {
|
|
||||||
if (str == NULL || *str == '\0') return;
|
|
||||||
|
|
||||||
ctx.tx_complete = false;
|
|
||||||
BSP_UART_Transmit(BSP_UART_MROBOT, (uint8_t *)str, strlen(str), true);
|
|
||||||
while (!ctx.tx_complete) { osDelay(1); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 发送命令提示符
|
|
||||||
*/
|
|
||||||
static void send_prompt(void) {
|
|
||||||
char prompt[MROBOT_PATH_MAX_LEN + 32];
|
|
||||||
snprintf(prompt, sizeof(prompt), MROBOT_USER_NAME "@" MROBOT_HOST_NAME ":%s$ ", ctx.current_path);
|
|
||||||
send_string(prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief UART 发送完成回调
|
|
||||||
*/
|
|
||||||
static void uart_tx_callback(void) {
|
|
||||||
ctx.tx_complete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief UART 接收回调
|
|
||||||
*/
|
|
||||||
static void uart_rx_callback(void) {
|
|
||||||
uint8_t ch = ctx.uart_rx_char;
|
|
||||||
|
|
||||||
/* htop 模式下检查退出键 */
|
|
||||||
if (ctx.state == MROBOT_STATE_HTOP) {
|
|
||||||
if (ch == 'q' || ch == 'Q' || ch == 27) {
|
|
||||||
ctx.htop_exit = true;
|
|
||||||
}
|
|
||||||
BSP_UART_Receive(BSP_UART_MROBOT, &ctx.uart_rx_char, 1, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 正常命令输入处理 */
|
|
||||||
if (ch == '\r' || ch == '\n') {
|
|
||||||
if (ctx.cmd_index > 0) {
|
|
||||||
ctx.cmd_buffer[ctx.cmd_index] = '\0';
|
|
||||||
ctx.cmd_ready = true;
|
|
||||||
BSP_UART_Transmit(BSP_UART_MROBOT, (uint8_t *)"\r\n", 2, false);
|
|
||||||
}
|
|
||||||
} else if (ch == 127 || ch == 8) { /* 退格键 */
|
|
||||||
if (ctx.cmd_index > 0) {
|
|
||||||
ctx.cmd_index--;
|
|
||||||
BSP_UART_Transmit(BSP_UART_MROBOT, (uint8_t *)ANSI_BACKSPACE, 3, false);
|
|
||||||
}
|
|
||||||
} else if (ch >= 32 && ch < 127 && ctx.cmd_index < sizeof(ctx.cmd_buffer) - 1) {
|
|
||||||
ctx.cmd_buffer[ctx.cmd_index++] = ch;
|
|
||||||
/* 回显:使用静态变量地址,避免异步发送时局部变量已失效 */
|
|
||||||
BSP_UART_Transmit(BSP_UART_MROBOT, &ctx.uart_rx_char, 1, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
BSP_UART_Receive(BSP_UART_MROBOT, &ctx.uart_rx_char, 1, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================== */
|
|
||||||
/* CLI 命令实现 */
|
|
||||||
/* ========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief help 命令 - 显示帮助信息
|
|
||||||
*/
|
|
||||||
static BaseType_t cmd_help(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
|
|
||||||
(void)pcCommandString;
|
|
||||||
|
|
||||||
int offset = snprintf(pcWriteBuffer, xWriteBufferLen,
|
|
||||||
"MRobot CLI v2.0\r\n"
|
|
||||||
"================\r\n"
|
|
||||||
"Built-in Commands:\r\n");
|
|
||||||
|
|
||||||
for (size_t i = 0; i < BUILTIN_CMD_COUNT && offset < (int)xWriteBufferLen - 50; i++) {
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
" %s", builtin_commands[i].pcHelpString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.custom_cmd_count > 0) {
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
"\r\nCustom Commands:\r\n");
|
|
||||||
for (uint8_t i = 0; i < ctx.custom_cmd_count && offset < (int)xWriteBufferLen - 50; i++) {
|
|
||||||
if (ctx.custom_cmds[i] != NULL) {
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
" %s", ctx.custom_cmds[i]->pcHelpString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief htop 命令 - 设置 htop 模式标志
|
|
||||||
*/
|
|
||||||
static BaseType_t cmd_htop(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
|
|
||||||
(void)pcCommandString;
|
|
||||||
(void)pcWriteBuffer;
|
|
||||||
(void)xWriteBufferLen;
|
|
||||||
/* htop 模式在 MRobot_Run 中处理 */
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief cd 命令 - 切换目录
|
|
||||||
*/
|
|
||||||
static BaseType_t cmd_cd(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
|
|
||||||
const char *param;
|
|
||||||
BaseType_t param_len;
|
|
||||||
|
|
||||||
param = FreeRTOS_CLIGetParameter(pcCommandString, 1, ¶m_len);
|
|
||||||
|
|
||||||
if (param == NULL) {
|
|
||||||
/* 无参数时切换到根目录 */
|
|
||||||
strcpy(ctx.current_path, "/");
|
|
||||||
snprintf(pcWriteBuffer, xWriteBufferLen, "Changed to: %s\r\n", ctx.current_path);
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 安全复制路径参数 */
|
|
||||||
char path[MROBOT_PATH_MAX_LEN];
|
|
||||||
size_t copy_len = (size_t)param_len < sizeof(path) - 1 ? (size_t)param_len : sizeof(path) - 1;
|
|
||||||
strncpy(path, param, copy_len);
|
|
||||||
path[copy_len] = '\0';
|
|
||||||
|
|
||||||
/* 路径解析 */
|
|
||||||
if (strcmp(path, "/") == 0 || strcmp(path, "..") == 0 || strcmp(path, "~") == 0) {
|
|
||||||
strcpy(ctx.current_path, "/");
|
|
||||||
} else if (strcmp(path, "dev") == 0 || strcmp(path, "/dev") == 0) {
|
|
||||||
strcpy(ctx.current_path, "/dev");
|
|
||||||
} else if (strcmp(path, "modules") == 0 || strcmp(path, "/modules") == 0) {
|
|
||||||
strcpy(ctx.current_path, "/modules");
|
|
||||||
} else {
|
|
||||||
snprintf(pcWriteBuffer, xWriteBufferLen, "Error: Directory '%s' not found\r\n", path);
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(pcWriteBuffer, xWriteBufferLen, "Changed to: %s\r\n", ctx.current_path);
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief ls 命令 - 列出目录内容
|
|
||||||
*/
|
|
||||||
static BaseType_t cmd_ls(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
|
|
||||||
(void)pcCommandString;
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
if (strcmp(ctx.current_path, "/") == 0) {
|
|
||||||
snprintf(pcWriteBuffer, xWriteBufferLen,
|
|
||||||
"dev/\r\n"
|
|
||||||
"modules/\r\n");
|
|
||||||
} else if (strcmp(ctx.current_path, "/dev") == 0) {
|
|
||||||
offset = snprintf(pcWriteBuffer, xWriteBufferLen,
|
|
||||||
"Device List (%d devices)\r\n\r\n",
|
|
||||||
ctx.device_count);
|
|
||||||
|
|
||||||
if (ctx.device_count == 0) {
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
" (No devices)\r\n");
|
|
||||||
} else {
|
|
||||||
/* 直接列出所有设备 */
|
|
||||||
for (uint8_t i = 0; i < ctx.device_count && offset < (int)xWriteBufferLen - 50; i++) {
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
" - %s\r\n", ctx.devices[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (strcmp(ctx.current_path, "/modules") == 0) {
|
|
||||||
snprintf(pcWriteBuffer, xWriteBufferLen,
|
|
||||||
"Module functions not yet implemented\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief show 命令 - 显示设备信息
|
|
||||||
*/
|
|
||||||
static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
|
|
||||||
const char *param;
|
|
||||||
const char *count_param;
|
|
||||||
BaseType_t param_len, count_param_len;
|
|
||||||
|
|
||||||
/* 使用局部静态变量跟踪多次打印状态 */
|
|
||||||
static uint32_t print_count = 0;
|
|
||||||
static uint32_t current_iter = 0;
|
|
||||||
static char target_device[MROBOT_DEVICE_NAME_LEN] = {0};
|
|
||||||
|
|
||||||
/* 首次调用时解析参数 */
|
|
||||||
if (current_iter == 0) {
|
|
||||||
/* 检查是否在 /dev 目录 */
|
|
||||||
if (strcmp(ctx.current_path, "/dev") != 0) {
|
|
||||||
snprintf(pcWriteBuffer, xWriteBufferLen,
|
|
||||||
"Error: 'show' command only works in /dev directory\r\n"
|
|
||||||
"Hint: Use 'cd /dev' to switch to device directory\r\n");
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
param = FreeRTOS_CLIGetParameter(pcCommandString, 1, ¶m_len);
|
|
||||||
count_param = FreeRTOS_CLIGetParameter(pcCommandString, 2, &count_param_len);
|
|
||||||
|
|
||||||
/* 解析打印次数 */
|
|
||||||
print_count = 1;
|
|
||||||
if (count_param != NULL) {
|
|
||||||
char count_str[16];
|
|
||||||
size_t copy_len = (size_t)count_param_len < sizeof(count_str) - 1 ?
|
|
||||||
(size_t)count_param_len : sizeof(count_str) - 1;
|
|
||||||
strncpy(count_str, count_param, copy_len);
|
|
||||||
count_str[copy_len] = '\0';
|
|
||||||
int parsed = atoi(count_str);
|
|
||||||
if (parsed > 0 && parsed <= 1000) {
|
|
||||||
print_count = (uint32_t)parsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 保存目标设备名称 */
|
|
||||||
if (param != NULL) {
|
|
||||||
size_t copy_len = (size_t)param_len < sizeof(target_device) - 1 ?
|
|
||||||
(size_t)param_len : sizeof(target_device) - 1;
|
|
||||||
strncpy(target_device, param, copy_len);
|
|
||||||
target_device[copy_len] = '\0';
|
|
||||||
} else {
|
|
||||||
target_device[0] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
/* 连续打印模式:清屏 */
|
|
||||||
if (print_count > 1) {
|
|
||||||
offset = snprintf(pcWriteBuffer, xWriteBufferLen, "%s[%lu/%lu]\r\n",
|
|
||||||
ANSI_CLEAR_SCREEN,
|
|
||||||
(unsigned long)(current_iter + 1),
|
|
||||||
(unsigned long)print_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target_device[0] == '\0') {
|
|
||||||
/* 显示所有设备 */
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
"=== All Devices ===\r\n\r\n");
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ctx.device_count && offset < (int)xWriteBufferLen - 100; i++) {
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
"--- %s ---\r\n", ctx.devices[i].name);
|
|
||||||
|
|
||||||
if (ctx.devices[i].print_cb != NULL) {
|
|
||||||
int written = ctx.devices[i].print_cb(ctx.devices[i].data,
|
|
||||||
pcWriteBuffer + offset,
|
|
||||||
xWriteBufferLen - offset);
|
|
||||||
offset += (written > 0) ? written : 0;
|
|
||||||
} else {
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
" (No print function)\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.device_count == 0) {
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
" (No devices registered)\r\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* 显示指定设备 */
|
|
||||||
const MRobot_Device_t *dev = MRobot_FindDevice(target_device);
|
|
||||||
|
|
||||||
if (dev == NULL) {
|
|
||||||
snprintf(pcWriteBuffer, xWriteBufferLen,
|
|
||||||
"Error: Device '%s' not found\r\n",
|
|
||||||
target_device);
|
|
||||||
current_iter = 0;
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
"=== %s ===\r\n", dev->name);
|
|
||||||
|
|
||||||
if (dev->print_cb != NULL) {
|
|
||||||
dev->print_cb(dev->data, pcWriteBuffer + offset, xWriteBufferLen - offset);
|
|
||||||
} else {
|
|
||||||
snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
|
|
||||||
" (No print function)\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 判断是否继续打印 */
|
|
||||||
current_iter++;
|
|
||||||
if (current_iter < print_count) {
|
|
||||||
osDelay(MROBOT_HTOP_REFRESH_MS);
|
|
||||||
return pdTRUE;
|
|
||||||
} else {
|
|
||||||
current_iter = 0;
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* htop 模式处理
|
|
||||||
* ========================================================================== */
|
|
||||||
static void handle_htop_mode(void) {
|
|
||||||
send_string(ANSI_CLEAR_SCREEN);
|
|
||||||
send_string("=== MRobot Task Monitor (Press 'q' to exit) ===\r\n\r\n");
|
|
||||||
|
|
||||||
/* 获取任务列表 */
|
|
||||||
char task_buffer[1024];
|
|
||||||
char display_line[128];
|
|
||||||
|
|
||||||
vTaskList(task_buffer);
|
|
||||||
|
|
||||||
/* 表头 */
|
|
||||||
send_string("Task Name State Prio Stack Num\r\n");
|
|
||||||
send_string("------------------------------------------------\r\n");
|
|
||||||
|
|
||||||
/* 解析并格式化任务列表 */
|
|
||||||
char *line = strtok(task_buffer, "\r\n");
|
|
||||||
while (line != NULL) {
|
|
||||||
char name[17] = {0};
|
|
||||||
char state_char = '?';
|
|
||||||
int prio = 0, stack = 0, num = 0;
|
|
||||||
|
|
||||||
if (sscanf(line, "%16s %c %d %d %d", name, &state_char, &prio, &stack, &num) == 5) {
|
|
||||||
const char *state_str;
|
|
||||||
switch (state_char) {
|
|
||||||
case 'R': state_str = "Running"; break;
|
|
||||||
case 'B': state_str = "Blocked"; break;
|
|
||||||
case 'S': state_str = "Suspend"; break;
|
|
||||||
case 'D': state_str = "Deleted"; break;
|
|
||||||
case 'X': state_str = "Ready "; break;
|
|
||||||
default: state_str = "Unknown"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(display_line, sizeof(display_line),
|
|
||||||
"%-16s %-8s %-4d %-8d %-4d\r\n",
|
|
||||||
name, state_str, prio, stack, num);
|
|
||||||
send_string(display_line);
|
|
||||||
}
|
|
||||||
line = strtok(NULL, "\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 显示系统信息 */
|
|
||||||
snprintf(display_line, sizeof(display_line),
|
|
||||||
"------------------------------------------------\r\n"
|
|
||||||
"System Tick: %lu | Free Heap: %lu bytes\r\n",
|
|
||||||
(unsigned long)xTaskGetTickCount(),
|
|
||||||
(unsigned long)xPortGetFreeHeapSize());
|
|
||||||
send_string(display_line);
|
|
||||||
|
|
||||||
/* 检查退出 */
|
|
||||||
if (ctx.htop_exit) {
|
|
||||||
ctx.state = MROBOT_STATE_IDLE;
|
|
||||||
ctx.htop_exit = false;
|
|
||||||
send_string(ANSI_CLEAR_SCREEN);
|
|
||||||
send_prompt();
|
|
||||||
}
|
|
||||||
|
|
||||||
osDelay(MROBOT_HTOP_REFRESH_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================== */
|
|
||||||
/* 公共 API 实现 */
|
|
||||||
/* ========================================================================== */
|
|
||||||
|
|
||||||
void MRobot_Init(void) {
|
|
||||||
if (ctx.initialized) return;
|
|
||||||
|
|
||||||
/* 创建互斥锁 */
|
|
||||||
ctx.mutex = xSemaphoreCreateMutex();
|
|
||||||
|
|
||||||
/* 初始化状态(保留已注册的设备) */
|
|
||||||
// 注意:不清除 devices 和 device_count,因为其他任务可能已经注册了设备
|
|
||||||
ctx.custom_cmd_count = 0;
|
|
||||||
ctx.state = MROBOT_STATE_IDLE;
|
|
||||||
strcpy(ctx.current_path, "/");
|
|
||||||
ctx.cmd_index = 0;
|
|
||||||
ctx.cmd_ready = false;
|
|
||||||
ctx.tx_complete = true;
|
|
||||||
ctx.htop_exit = false;
|
|
||||||
|
|
||||||
/* 注册内置命令 */
|
|
||||||
for (size_t i = 0; i < BUILTIN_CMD_COUNT; i++) {
|
|
||||||
FreeRTOS_CLIRegisterCommand(&builtin_commands[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 注册 UART 回调 */
|
|
||||||
BSP_UART_RegisterCallback(BSP_UART_MROBOT, BSP_UART_RX_CPLT_CB, uart_rx_callback);
|
|
||||||
BSP_UART_RegisterCallback(BSP_UART_MROBOT, BSP_UART_TX_CPLT_CB, uart_tx_callback);
|
|
||||||
|
|
||||||
/* 启动 UART 接收 */
|
|
||||||
BSP_UART_Receive(BSP_UART_MROBOT, &ctx.uart_rx_char, 1, false);
|
|
||||||
|
|
||||||
/* 等待用户按下回车 */
|
|
||||||
while (ctx.uart_rx_char != '\r' && ctx.uart_rx_char != '\n') {
|
|
||||||
osDelay(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 发送欢迎消息和提示符 */
|
|
||||||
send_string(CLI_WELCOME_MESSAGE);
|
|
||||||
send_prompt();
|
|
||||||
|
|
||||||
ctx.initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MRobot_DeInit(void) {
|
|
||||||
if (!ctx.initialized) return;
|
|
||||||
|
|
||||||
/* 释放自定义命令内存 */
|
|
||||||
for (uint8_t i = 0; i < ctx.custom_cmd_count; i++) {
|
|
||||||
if (ctx.custom_cmds[i] != NULL) {
|
|
||||||
BSP_Free(ctx.custom_cmds[i]);
|
|
||||||
ctx.custom_cmds[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 删除互斥锁 */
|
|
||||||
if (ctx.mutex != NULL) {
|
|
||||||
vSemaphoreDelete(ctx.mutex);
|
|
||||||
ctx.mutex = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.initialized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MRobot_State_t MRobot_GetState(void) {
|
|
||||||
return ctx.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
MRobot_Error_t MRobot_RegisterDevice(const char *name, void *data, MRobot_PrintCallback_t print_cb) {
|
|
||||||
if (name == NULL || data == NULL) {
|
|
||||||
return MROBOT_ERR_NULL_PTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.device_count >= MROBOT_MAX_DEVICES) {
|
|
||||||
return MROBOT_ERR_FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 检查重名 */
|
|
||||||
for (uint8_t i = 0; i < ctx.device_count; i++) {
|
|
||||||
if (strcmp(ctx.devices[i].name, name) == 0) {
|
|
||||||
return MROBOT_ERR_INVALID_ARG; /* 设备名已存在 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 线程安全写入 */
|
|
||||||
if (ctx.mutex != NULL) {
|
|
||||||
xSemaphoreTake(ctx.mutex, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(ctx.devices[ctx.device_count].name, name, MROBOT_DEVICE_NAME_LEN - 1);
|
|
||||||
ctx.devices[ctx.device_count].name[MROBOT_DEVICE_NAME_LEN - 1] = '\0';
|
|
||||||
ctx.devices[ctx.device_count].data = data;
|
|
||||||
ctx.devices[ctx.device_count].print_cb = print_cb;
|
|
||||||
ctx.device_count++;
|
|
||||||
|
|
||||||
if (ctx.mutex != NULL) {
|
|
||||||
xSemaphoreGive(ctx.mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MROBOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MRobot_Error_t MRobot_UnregisterDevice(const char *name) {
|
|
||||||
if (name == NULL) {
|
|
||||||
return MROBOT_ERR_NULL_PTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.mutex != NULL) {
|
|
||||||
xSemaphoreTake(ctx.mutex, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ctx.device_count; i++) {
|
|
||||||
if (strcmp(ctx.devices[i].name, name) == 0) {
|
|
||||||
/* 移动后续设备 */
|
|
||||||
for (uint8_t j = i; j < ctx.device_count - 1; j++) {
|
|
||||||
ctx.devices[j] = ctx.devices[j + 1];
|
|
||||||
}
|
|
||||||
ctx.device_count--;
|
|
||||||
|
|
||||||
if (ctx.mutex != NULL) {
|
|
||||||
xSemaphoreGive(ctx.mutex);
|
|
||||||
}
|
|
||||||
return MROBOT_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.mutex != NULL) {
|
|
||||||
xSemaphoreGive(ctx.mutex);
|
|
||||||
}
|
|
||||||
return MROBOT_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
MRobot_Error_t MRobot_RegisterCommand(const char *command, const char *help_text,
|
|
||||||
MRobot_CommandCallback_t callback, int8_t param_count) {
|
|
||||||
if (command == NULL || help_text == NULL || callback == NULL) {
|
|
||||||
return MROBOT_ERR_NULL_PTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.custom_cmd_count >= MROBOT_MAX_CUSTOM_COMMANDS) {
|
|
||||||
return MROBOT_ERR_FULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 动态分配命令结构体 */
|
|
||||||
CLI_Command_Definition_t *cmd_def = BSP_Malloc(sizeof(CLI_Command_Definition_t));
|
|
||||||
if (cmd_def == NULL) {
|
|
||||||
return MROBOT_ERR_ALLOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 初始化命令定义 */
|
|
||||||
*(const char **)&cmd_def->pcCommand = command;
|
|
||||||
*(const char **)&cmd_def->pcHelpString = help_text;
|
|
||||||
*(pdCOMMAND_LINE_CALLBACK *)&cmd_def->pxCommandInterpreter = (pdCOMMAND_LINE_CALLBACK)callback;
|
|
||||||
cmd_def->cExpectedNumberOfParameters = param_count;
|
|
||||||
|
|
||||||
/* 注册到 FreeRTOS CLI */
|
|
||||||
FreeRTOS_CLIRegisterCommand(cmd_def);
|
|
||||||
|
|
||||||
ctx.custom_cmds[ctx.custom_cmd_count] = cmd_def;
|
|
||||||
ctx.custom_cmd_count++;
|
|
||||||
|
|
||||||
return MROBOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t MRobot_GetDeviceCount(void) {
|
|
||||||
return ctx.device_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MRobot_Device_t *MRobot_FindDevice(const char *name) {
|
|
||||||
if (name == NULL) return NULL;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ctx.device_count; i++) {
|
|
||||||
if (strcmp(ctx.devices[i].name, name) == 0) {
|
|
||||||
return &ctx.devices[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MRobot_Printf(const char *fmt, ...) {
|
|
||||||
if (fmt == NULL || !ctx.initialized) return -1;
|
|
||||||
|
|
||||||
char buffer[MROBOT_OUTPUT_BUFFER_SIZE];
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
int len = format_float_va(buffer, sizeof(buffer), fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if (len > 0) {
|
|
||||||
send_string(buffer);
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 内部函数:格式化浮点数到缓冲区(va_list 版本)
|
|
||||||
*/
|
|
||||||
static int format_float_va(char *buf, size_t size, const char *fmt, va_list args) {
|
|
||||||
if (buf == NULL || size == 0 || fmt == NULL) return 0;
|
|
||||||
|
|
||||||
char *buf_ptr = buf;
|
|
||||||
size_t buf_remain = size - 1;
|
|
||||||
|
|
||||||
const char *p = fmt;
|
|
||||||
while (*p && buf_remain > 0) {
|
|
||||||
if (*p != '%') {
|
|
||||||
*buf_ptr++ = *p++;
|
|
||||||
buf_remain--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
p++; /* 跳过 '%' */
|
|
||||||
|
|
||||||
/* 处理 %% */
|
|
||||||
if (*p == '%') {
|
|
||||||
*buf_ptr++ = '%';
|
|
||||||
buf_remain--;
|
|
||||||
p++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 解析精度 %.Nf */
|
|
||||||
int precision = 2; /* 默认精度 */
|
|
||||||
if (*p == '.') {
|
|
||||||
p++;
|
|
||||||
precision = 0;
|
|
||||||
while (*p >= '0' && *p <= '9') {
|
|
||||||
precision = precision * 10 + (*p - '0');
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (precision > 6) precision = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
int written = 0;
|
|
||||||
switch (*p) {
|
|
||||||
case 'f': { /* 浮点数 */
|
|
||||||
double val = va_arg(args, double);
|
|
||||||
written = MRobot_FormatFloat(buf_ptr, buf_remain, (float)val, precision);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'd':
|
|
||||||
case 'i': {
|
|
||||||
int val = va_arg(args, int);
|
|
||||||
written = snprintf(buf_ptr, buf_remain, "%d", val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'u': {
|
|
||||||
unsigned int val = va_arg(args, unsigned int);
|
|
||||||
written = snprintf(buf_ptr, buf_remain, "%u", val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'x': {
|
|
||||||
unsigned int val = va_arg(args, unsigned int);
|
|
||||||
written = snprintf(buf_ptr, buf_remain, "%x", val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'X': {
|
|
||||||
unsigned int val = va_arg(args, unsigned int);
|
|
||||||
written = snprintf(buf_ptr, buf_remain, "%X", val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 's': {
|
|
||||||
const char *str = va_arg(args, const char *);
|
|
||||||
if (str == NULL) str = "(null)";
|
|
||||||
written = snprintf(buf_ptr, buf_remain, "%s", str);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'c': {
|
|
||||||
int ch = va_arg(args, int);
|
|
||||||
*buf_ptr = (char)ch;
|
|
||||||
written = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'l': {
|
|
||||||
p++;
|
|
||||||
if (*p == 'd' || *p == 'i') {
|
|
||||||
long val = va_arg(args, long);
|
|
||||||
written = snprintf(buf_ptr, buf_remain, "%ld", val);
|
|
||||||
} else if (*p == 'u') {
|
|
||||||
unsigned long val = va_arg(args, unsigned long);
|
|
||||||
written = snprintf(buf_ptr, buf_remain, "%lu", val);
|
|
||||||
} else if (*p == 'x' || *p == 'X') {
|
|
||||||
unsigned long val = va_arg(args, unsigned long);
|
|
||||||
written = snprintf(buf_ptr, buf_remain, *p == 'x' ? "%lx" : "%lX", val);
|
|
||||||
} else {
|
|
||||||
p--;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
*buf_ptr++ = '%';
|
|
||||||
buf_remain--;
|
|
||||||
if (buf_remain > 0) {
|
|
||||||
*buf_ptr++ = *p;
|
|
||||||
buf_remain--;
|
|
||||||
}
|
|
||||||
written = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (written > 0) {
|
|
||||||
buf_ptr += written;
|
|
||||||
buf_remain -= (size_t)written;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*buf_ptr = '\0';
|
|
||||||
return (int)(buf_ptr - buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MRobot_Snprintf(char *buf, size_t size, const char *fmt, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
int len = format_float_va(buf, size, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MRobot_FormatFloat(char *buf, size_t size, float val, int precision) {
|
|
||||||
if (buf == NULL || size == 0) return 0;
|
|
||||||
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
/* 处理负数 */
|
|
||||||
if (val < 0) {
|
|
||||||
if (offset < (int)size - 1) buf[offset++] = '-';
|
|
||||||
val = -val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 限制精度范围 */
|
|
||||||
if (precision < 0) precision = 0;
|
|
||||||
if (precision > 6) precision = 6;
|
|
||||||
|
|
||||||
/* 计算乘数 */
|
|
||||||
int multiplier = 1;
|
|
||||||
for (int i = 0; i < precision; i++) multiplier *= 10;
|
|
||||||
|
|
||||||
int int_part = (int)val;
|
|
||||||
int frac_part = (int)((val - int_part) * multiplier + 0.5f);
|
|
||||||
|
|
||||||
/* 处理进位 */
|
|
||||||
if (frac_part >= multiplier) {
|
|
||||||
int_part++;
|
|
||||||
frac_part -= multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 格式化输出 */
|
|
||||||
int written;
|
|
||||||
if (precision > 0) {
|
|
||||||
written = snprintf(buf + offset, size - offset, "%d.%0*d", int_part, precision, frac_part);
|
|
||||||
} else {
|
|
||||||
written = snprintf(buf + offset, size - offset, "%d", int_part);
|
|
||||||
}
|
|
||||||
return (written > 0) ? (offset + written) : offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MRobot_Run(void) {
|
|
||||||
if (!ctx.initialized) return;
|
|
||||||
|
|
||||||
/* htop 模式 */
|
|
||||||
if (ctx.state == MROBOT_STATE_HTOP) {
|
|
||||||
handle_htop_mode();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 处理命令 */
|
|
||||||
if (ctx.cmd_ready) {
|
|
||||||
ctx.state = MROBOT_STATE_PROCESSING;
|
|
||||||
|
|
||||||
/* 检查是否是 htop 命令 */
|
|
||||||
if (strcmp((char *)ctx.cmd_buffer, "htop") == 0) {
|
|
||||||
ctx.state = MROBOT_STATE_HTOP;
|
|
||||||
ctx.htop_exit = false;
|
|
||||||
} else {
|
|
||||||
/* 处理其他命令 */
|
|
||||||
BaseType_t more;
|
|
||||||
do {
|
|
||||||
ctx.output_buffer[0] = '\0';
|
|
||||||
more = FreeRTOS_CLIProcessCommand((char *)ctx.cmd_buffer,
|
|
||||||
ctx.output_buffer,
|
|
||||||
sizeof(ctx.output_buffer));
|
|
||||||
|
|
||||||
if (ctx.output_buffer[0] != '\0') {
|
|
||||||
send_string(ctx.output_buffer);
|
|
||||||
}
|
|
||||||
} while (more != pdFALSE);
|
|
||||||
|
|
||||||
send_prompt();
|
|
||||||
ctx.state = MROBOT_STATE_IDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.cmd_index = 0;
|
|
||||||
ctx.cmd_ready = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
osDelay(10);
|
|
||||||
}
|
|
||||||
@ -1,313 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file mrobot.h
|
|
||||||
* @brief MRobot CLI - 基于 FreeRTOS CLI 的嵌入式调试命令行系统
|
|
||||||
*
|
|
||||||
* 功能特性:
|
|
||||||
* - 设备注册与监控(IMU、电机、传感器等)
|
|
||||||
* - 类 Unix 文件系统命令(cd, ls, pwd)
|
|
||||||
* - htop 风格的任务监控
|
|
||||||
* - 自定义命令扩展
|
|
||||||
* - 线程安全设计
|
|
||||||
*
|
|
||||||
* @example IMU 设备注册示例
|
|
||||||
* @code
|
|
||||||
* // 1. 定义 IMU 数据结构
|
|
||||||
* typedef struct {
|
|
||||||
* bool online;
|
|
||||||
* float accl[3];
|
|
||||||
* float gyro[3];
|
|
||||||
* float euler[3]; // roll, pitch, yaw (deg)
|
|
||||||
* float temp;
|
|
||||||
* } MyIMU_t;
|
|
||||||
*
|
|
||||||
* MyIMU_t my_imu;
|
|
||||||
*
|
|
||||||
* // 2. 实现打印回调
|
|
||||||
* static int print_imu(const void *data, char *buf, size_t size) {
|
|
||||||
* const MyIMU_t *imu = (const MyIMU_t *)data;
|
|
||||||
* return MRobot_Snprintf(buf, size,
|
|
||||||
* " Status: %s\r\n"
|
|
||||||
* " Accel : X=%.3f Y=%.3f Z=%.3f\r\n"
|
|
||||||
* " Euler : R=%.2f P=%.2f Y=%.2f\r\n"
|
|
||||||
* " Temp : %.1f C\r\n",
|
|
||||||
* imu->online ? "Online" : "Offline",
|
|
||||||
* imu->accl[0], imu->accl[1], imu->accl[2],
|
|
||||||
* imu->euler[0], imu->euler[1], imu->euler[2],
|
|
||||||
* imu->temp);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // 3. 注册设备
|
|
||||||
* MRobot_RegisterDevice("imu", &my_imu, print_imu);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @example 电机设备注册示例
|
|
||||||
* @code
|
|
||||||
* typedef struct {
|
|
||||||
* bool online;
|
|
||||||
* float angle; // deg
|
|
||||||
* float speed; // RPM
|
|
||||||
* float current; // A
|
|
||||||
* } MyMotor_t;
|
|
||||||
*
|
|
||||||
* MyMotor_t motor[4];
|
|
||||||
*
|
|
||||||
* static int print_motor(const void *data, char *buf, size_t size) {
|
|
||||||
* const MyMotor_t *m = (const MyMotor_t *)data;
|
|
||||||
* return MRobot_Snprintf(buf, size,
|
|
||||||
* " Status : %s\r\n"
|
|
||||||
* " Angle : %.2f deg\r\n"
|
|
||||||
* " Speed : %.1f RPM\r\n"
|
|
||||||
* " Current: %.3f A\r\n",
|
|
||||||
* m->online ? "Online" : "Offline",
|
|
||||||
* m->angle, m->speed, m->current);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // 注册 4 个电机
|
|
||||||
* MRobot_RegisterDevice("motor0", &motor[0], print_motor);
|
|
||||||
* MRobot_RegisterDevice("motor1", &motor[1], print_motor);
|
|
||||||
* MRobot_RegisterDevice("motor2", &motor[2], print_motor);
|
|
||||||
* MRobot_RegisterDevice("motor3", &motor[3], print_motor);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @example 自定义校准命令示例
|
|
||||||
* @code
|
|
||||||
* // 校准数据
|
|
||||||
* static float gyro_offset[3] = {0};
|
|
||||||
*
|
|
||||||
* // 命令回调: cali gyro / cali accel / cali save
|
|
||||||
* static long cmd_cali(char *buf, size_t size, const char *cmd) {
|
|
||||||
* const char *param = FreeRTOS_CLIGetParameter(cmd, 1, NULL);
|
|
||||||
*
|
|
||||||
* if (param == NULL) {
|
|
||||||
* return MRobot_Snprintf(buf, size, "Usage: cali <gyro|accel|save>\r\n");
|
|
||||||
* }
|
|
||||||
* if (strncmp(param, "gyro", 4) == 0) {
|
|
||||||
* // 采集 1000 次陀螺仪数据求平均
|
|
||||||
* MRobot_Snprintf(buf, size, "Calibrating gyro... keep IMU still!\r\n");
|
|
||||||
* // ... 校准逻辑 ...
|
|
||||||
* return 0;
|
|
||||||
* }
|
|
||||||
* if (strncmp(param, "save", 4) == 0) {
|
|
||||||
* // 保存到 Flash
|
|
||||||
* MRobot_Snprintf(buf, size, "Calibration saved to flash.\r\n");
|
|
||||||
* return 0;
|
|
||||||
* }
|
|
||||||
* return MRobot_Snprintf(buf, size, "Unknown: %s\r\n", param);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // 注册命令
|
|
||||||
* MRobot_RegisterCommand("cali", "cali <gyro|accel|save>: IMU calibration\r\n", cmd_cali, -1);
|
|
||||||
* @endcode
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Includes ----------------------------------------------------------------- */
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "bsp/uart.h"
|
|
||||||
|
|
||||||
/* Configuration ------------------------------------------------------------ */
|
|
||||||
/* 可在编译时通过 -D 选项覆盖这些默认值 */
|
|
||||||
|
|
||||||
#ifndef MROBOT_MAX_DEVICES
|
|
||||||
#define MROBOT_MAX_DEVICES 64 /* 最大设备数 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MROBOT_MAX_CUSTOM_COMMANDS
|
|
||||||
#define MROBOT_MAX_CUSTOM_COMMANDS 16 /* 最大自定义命令数 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MROBOT_CMD_BUFFER_SIZE
|
|
||||||
#define MROBOT_CMD_BUFFER_SIZE 128 /* 命令缓冲区大小 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MROBOT_OUTPUT_BUFFER_SIZE
|
|
||||||
#define MROBOT_OUTPUT_BUFFER_SIZE 512 /* 输出缓冲区大小 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MROBOT_DEVICE_NAME_LEN
|
|
||||||
#define MROBOT_DEVICE_NAME_LEN 32 /* 设备名最大长度 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MROBOT_PATH_MAX_LEN
|
|
||||||
#define MROBOT_PATH_MAX_LEN 64 /* 路径最大长度 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MROBOT_HTOP_REFRESH_MS
|
|
||||||
#define MROBOT_HTOP_REFRESH_MS 200 /* htop 刷新间隔 (ms) */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MROBOT_USER_NAME
|
|
||||||
#define MROBOT_USER_NAME "root" /* CLI 用户名 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MROBOT_HOST_NAME
|
|
||||||
#define MROBOT_HOST_NAME "MRobot" /* CLI 主机名 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Error codes -------------------------------------------------------------- */
|
|
||||||
typedef enum {
|
|
||||||
MROBOT_OK = 0, /* 成功 */
|
|
||||||
MROBOT_ERR_FULL = -1, /* 容量已满 */
|
|
||||||
MROBOT_ERR_NULL_PTR = -2, /* 空指针 */
|
|
||||||
MROBOT_ERR_INVALID_ARG = -3, /* 无效参数 */
|
|
||||||
MROBOT_ERR_NOT_FOUND = -4, /* 未找到 */
|
|
||||||
MROBOT_ERR_ALLOC = -5, /* 内存分配失败 */
|
|
||||||
MROBOT_ERR_BUSY = -6, /* 设备忙 */
|
|
||||||
MROBOT_ERR_NOT_INIT = -7, /* 未初始化 */
|
|
||||||
} MRobot_Error_t;
|
|
||||||
|
|
||||||
/* CLI 运行状态 */
|
|
||||||
typedef enum {
|
|
||||||
MROBOT_STATE_IDLE, /* 空闲状态,等待输入 */
|
|
||||||
MROBOT_STATE_HTOP, /* htop 模式 */
|
|
||||||
MROBOT_STATE_PROCESSING, /* 正在处理命令 */
|
|
||||||
} MRobot_State_t;
|
|
||||||
|
|
||||||
/* Callback types ----------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设备打印回调函数类型
|
|
||||||
* @param device_data 用户注册时传入的设备数据指针
|
|
||||||
* @param buffer 输出缓冲区
|
|
||||||
* @param buffer_size 缓冲区大小
|
|
||||||
* @return 实际写入的字节数
|
|
||||||
* @note 用户需要自行实现此函数来格式化设备数据
|
|
||||||
*/
|
|
||||||
typedef int (*MRobot_PrintCallback_t)(const void *device_data, char *buffer, size_t buffer_size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 命令处理回调函数类型(与 FreeRTOS CLI 兼容)
|
|
||||||
*/
|
|
||||||
typedef long (*MRobot_CommandCallback_t)(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
|
|
||||||
|
|
||||||
/* Device structure --------------------------------------------------------- */
|
|
||||||
typedef struct {
|
|
||||||
char name[MROBOT_DEVICE_NAME_LEN]; /* 设备名称 */
|
|
||||||
void *data; /* 用户设备数据指针 */
|
|
||||||
MRobot_PrintCallback_t print_cb; /* 用户打印回调函数 */
|
|
||||||
} MRobot_Device_t;
|
|
||||||
|
|
||||||
/* Public API --------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 初始化 MRobot CLI 系统
|
|
||||||
* @note 必须在 FreeRTOS 调度器启动后调用
|
|
||||||
*/
|
|
||||||
void MRobot_Init(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 反初始化 MRobot CLI 系统,释放资源
|
|
||||||
*/
|
|
||||||
void MRobot_DeInit(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取当前 CLI 状态
|
|
||||||
* @return MRobot_State_t 当前状态
|
|
||||||
*/
|
|
||||||
MRobot_State_t MRobot_GetState(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 注册设备到 MRobot 系统
|
|
||||||
* @param name 设备名称(会被截断到 MROBOT_DEVICE_NAME_LEN-1)
|
|
||||||
* @param data 设备数据指针(不能为 NULL)
|
|
||||||
* @param print_cb 打印回调函数(可为 NULL,但无法用 show 命令查看)
|
|
||||||
* @return MRobot_Error_t 错误码
|
|
||||||
*/
|
|
||||||
MRobot_Error_t MRobot_RegisterDevice(const char *name, void *data, MRobot_PrintCallback_t print_cb);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 注销设备
|
|
||||||
* @param name 设备名称
|
|
||||||
* @return MRobot_Error_t 错误码
|
|
||||||
*/
|
|
||||||
MRobot_Error_t MRobot_UnregisterDevice(const char *name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 注册自定义命令
|
|
||||||
* @param command 命令名称
|
|
||||||
* @param help_text 帮助文本
|
|
||||||
* @param callback 命令回调函数
|
|
||||||
* @param param_count 参数个数(-1 表示可变参数)
|
|
||||||
* @return MRobot_Error_t 错误码
|
|
||||||
*/
|
|
||||||
MRobot_Error_t MRobot_RegisterCommand(const char *command, const char *help_text,
|
|
||||||
MRobot_CommandCallback_t callback, int8_t param_count);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取已注册设备数量
|
|
||||||
* @return 设备数量
|
|
||||||
*/
|
|
||||||
uint8_t MRobot_GetDeviceCount(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 根据名称查找设备
|
|
||||||
* @param name 设备名称
|
|
||||||
* @return 设备指针,未找到返回 NULL
|
|
||||||
*/
|
|
||||||
const MRobot_Device_t *MRobot_FindDevice(const char *name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief MRobot 主循环,在 CLI 任务中周期性调用
|
|
||||||
* @note 建议调用周期 10ms
|
|
||||||
*/
|
|
||||||
void MRobot_Run(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 格式化输出到 CLI 终端(线程安全,支持浮点数)
|
|
||||||
* @param fmt 格式字符串
|
|
||||||
* @param ... 可变参数
|
|
||||||
* @return 实际输出的字符数,失败返回负数
|
|
||||||
*
|
|
||||||
* @note 支持的格式说明符:
|
|
||||||
* - %d, %i, %u, %x, %X, %ld, %lu, %lx : 整数
|
|
||||||
* - %s, %c : 字符串/字符
|
|
||||||
* - %f : 浮点数 (默认2位小数)
|
|
||||||
* - %.Nf : 浮点数 (N位小数, N=0-6)
|
|
||||||
* - %% : 百分号
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* MRobot_Printf("Euler: R=%.2f P=%.2f Y=%.2f\\r\\n", roll, pitch, yaw);
|
|
||||||
*/
|
|
||||||
int MRobot_Printf(const char *fmt, ...);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 格式化到缓冲区(用于回调函数,支持浮点数)
|
|
||||||
* @note 格式说明符同 MRobot_Printf
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* static int print_imu(const void *data, char *buf, size_t size) {
|
|
||||||
* const BMI088_t *imu = (const BMI088_t *)data;
|
|
||||||
* return MRobot_Snprintf(buf, size,
|
|
||||||
* " Accel: X=%.3f Y=%.3f Z=%.3f\\r\\n",
|
|
||||||
* imu->accl.x, imu->accl.y, imu->accl.z);
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
int MRobot_Snprintf(char *buf, size_t size, const char *fmt, ...);
|
|
||||||
|
|
||||||
/* Utility functions -------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 格式化浮点数为字符串(嵌入式环境不支持 %f)
|
|
||||||
* @param buf 输出缓冲区
|
|
||||||
* @param size 缓冲区大小
|
|
||||||
* @param val 要格式化的浮点数
|
|
||||||
* @param precision 小数位数 (0-6)
|
|
||||||
* @return 写入的字符数
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* char buf[16];
|
|
||||||
* MRobot_FormatFloat(buf, sizeof(buf), 3.14159f, 2); // "3.14"
|
|
||||||
* MRobot_FormatFloat(buf, sizeof(buf), -0.001f, 4); // "-0.0010"
|
|
||||||
*/
|
|
||||||
int MRobot_FormatFloat(char *buf, size_t size, float val, int precision);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,700 +0,0 @@
|
|||||||
#MicroXplorer Configuration settings - do not modify
|
|
||||||
ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_4
|
|
||||||
ADC1.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_19
|
|
||||||
ADC1.ClockPrescaler=ADC_CLOCK_ASYNC_DIV64
|
|
||||||
ADC1.ContinuousConvMode=ENABLE
|
|
||||||
ADC1.ConversionDataManagement=ADC_CONVERSIONDATA_DMA_CIRCULAR
|
|
||||||
ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,OffsetSignedSaturation-0\#ChannelRegularConversion,NbrOfConversionFlag,master,ClockPrescaler,ContinuousConvMode,ConversionDataManagement,Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,OffsetNumber-1\#ChannelRegularConversion,OffsetSignedSaturation-1\#ChannelRegularConversion,NbrOfConversion
|
|
||||||
ADC1.NbrOfConversion=2
|
|
||||||
ADC1.NbrOfConversionFlag=1
|
|
||||||
ADC1.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE
|
|
||||||
ADC1.OffsetNumber-1\#ChannelRegularConversion=ADC_OFFSET_NONE
|
|
||||||
ADC1.OffsetSignedSaturation-0\#ChannelRegularConversion=DISABLE
|
|
||||||
ADC1.OffsetSignedSaturation-1\#ChannelRegularConversion=DISABLE
|
|
||||||
ADC1.Rank-0\#ChannelRegularConversion=1
|
|
||||||
ADC1.Rank-1\#ChannelRegularConversion=2
|
|
||||||
ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_32CYCLES_5
|
|
||||||
ADC1.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_32CYCLES_5
|
|
||||||
ADC1.master=1
|
|
||||||
CAD.formats=
|
|
||||||
CAD.pinconfig=
|
|
||||||
CAD.provider=
|
|
||||||
CORTEX_M7.BaseAddress-Cortex_Memory_Protection_Unit_Region0_Settings=0x24000000
|
|
||||||
CORTEX_M7.CPU_DCache=Disabled
|
|
||||||
CORTEX_M7.CPU_ICache=Disabled
|
|
||||||
CORTEX_M7.Enable-Cortex_Memory_Protection_Unit_Region0_Settings=MPU_REGION_ENABLE
|
|
||||||
CORTEX_M7.IPParameters=CPU_DCache,CPU_ICache,MPU_Control,Enable-Cortex_Memory_Protection_Unit_Region0_Settings,BaseAddress-Cortex_Memory_Protection_Unit_Region0_Settings,Size-Cortex_Memory_Protection_Unit_Region0_Settings,TypeExtField-Cortex_Memory_Protection_Unit_Region0_Settings,IsCacheable-Cortex_Memory_Protection_Unit_Region0_Settings,IsBufferable-Cortex_Memory_Protection_Unit_Region0_Settings
|
|
||||||
CORTEX_M7.IsBufferable-Cortex_Memory_Protection_Unit_Region0_Settings=MPU_ACCESS_BUFFERABLE
|
|
||||||
CORTEX_M7.IsCacheable-Cortex_Memory_Protection_Unit_Region0_Settings=MPU_ACCESS_CACHEABLE
|
|
||||||
CORTEX_M7.MPU_Control=__NULL
|
|
||||||
CORTEX_M7.Size-Cortex_Memory_Protection_Unit_Region0_Settings=MPU_REGION_SIZE_512B
|
|
||||||
CORTEX_M7.TypeExtField-Cortex_Memory_Protection_Unit_Region0_Settings=MPU_TEX_LEVEL1
|
|
||||||
Dma.ADC1.0.Direction=DMA_PERIPH_TO_MEMORY
|
|
||||||
Dma.ADC1.0.EventEnable=DISABLE
|
|
||||||
Dma.ADC1.0.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.ADC1.0.Instance=DMA1_Stream0
|
|
||||||
Dma.ADC1.0.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
|
|
||||||
Dma.ADC1.0.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.ADC1.0.Mode=DMA_CIRCULAR
|
|
||||||
Dma.ADC1.0.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
|
|
||||||
Dma.ADC1.0.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.ADC1.0.Polarity=HAL_DMAMUX_REQ_GEN_RISING
|
|
||||||
Dma.ADC1.0.Priority=DMA_PRIORITY_LOW
|
|
||||||
Dma.ADC1.0.RequestNumber=1
|
|
||||||
Dma.ADC1.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
|
|
||||||
Dma.ADC1.0.SignalID=NONE
|
|
||||||
Dma.ADC1.0.SyncEnable=DISABLE
|
|
||||||
Dma.ADC1.0.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
|
|
||||||
Dma.ADC1.0.SyncRequestNumber=1
|
|
||||||
Dma.ADC1.0.SyncSignalID=NONE
|
|
||||||
Dma.Request0=ADC1
|
|
||||||
Dma.Request1=SPI2_RX
|
|
||||||
Dma.Request2=SPI2_TX
|
|
||||||
Dma.Request3=UART5_RX
|
|
||||||
Dma.RequestsNb=4
|
|
||||||
Dma.SPI2_RX.1.Direction=DMA_PERIPH_TO_MEMORY
|
|
||||||
Dma.SPI2_RX.1.EventEnable=DISABLE
|
|
||||||
Dma.SPI2_RX.1.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.SPI2_RX.1.Instance=DMA1_Stream1
|
|
||||||
Dma.SPI2_RX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.SPI2_RX.1.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.SPI2_RX.1.Mode=DMA_NORMAL
|
|
||||||
Dma.SPI2_RX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.SPI2_RX.1.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.SPI2_RX.1.Polarity=HAL_DMAMUX_REQ_GEN_RISING
|
|
||||||
Dma.SPI2_RX.1.Priority=DMA_PRIORITY_LOW
|
|
||||||
Dma.SPI2_RX.1.RequestNumber=1
|
|
||||||
Dma.SPI2_RX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
|
|
||||||
Dma.SPI2_RX.1.SignalID=NONE
|
|
||||||
Dma.SPI2_RX.1.SyncEnable=DISABLE
|
|
||||||
Dma.SPI2_RX.1.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
|
|
||||||
Dma.SPI2_RX.1.SyncRequestNumber=1
|
|
||||||
Dma.SPI2_RX.1.SyncSignalID=NONE
|
|
||||||
Dma.SPI2_TX.2.Direction=DMA_MEMORY_TO_PERIPH
|
|
||||||
Dma.SPI2_TX.2.EventEnable=DISABLE
|
|
||||||
Dma.SPI2_TX.2.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.SPI2_TX.2.Instance=DMA1_Stream2
|
|
||||||
Dma.SPI2_TX.2.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.SPI2_TX.2.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.SPI2_TX.2.Mode=DMA_NORMAL
|
|
||||||
Dma.SPI2_TX.2.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.SPI2_TX.2.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.SPI2_TX.2.Polarity=HAL_DMAMUX_REQ_GEN_RISING
|
|
||||||
Dma.SPI2_TX.2.Priority=DMA_PRIORITY_LOW
|
|
||||||
Dma.SPI2_TX.2.RequestNumber=1
|
|
||||||
Dma.SPI2_TX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
|
|
||||||
Dma.SPI2_TX.2.SignalID=NONE
|
|
||||||
Dma.SPI2_TX.2.SyncEnable=DISABLE
|
|
||||||
Dma.SPI2_TX.2.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
|
|
||||||
Dma.SPI2_TX.2.SyncRequestNumber=1
|
|
||||||
Dma.SPI2_TX.2.SyncSignalID=NONE
|
|
||||||
Dma.UART5_RX.3.Direction=DMA_PERIPH_TO_MEMORY
|
|
||||||
Dma.UART5_RX.3.EventEnable=DISABLE
|
|
||||||
Dma.UART5_RX.3.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.UART5_RX.3.Instance=DMA1_Stream3
|
|
||||||
Dma.UART5_RX.3.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.UART5_RX.3.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.UART5_RX.3.Mode=DMA_NORMAL
|
|
||||||
Dma.UART5_RX.3.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.UART5_RX.3.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.UART5_RX.3.Polarity=HAL_DMAMUX_REQ_GEN_RISING
|
|
||||||
Dma.UART5_RX.3.Priority=DMA_PRIORITY_LOW
|
|
||||||
Dma.UART5_RX.3.RequestNumber=1
|
|
||||||
Dma.UART5_RX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
|
|
||||||
Dma.UART5_RX.3.SignalID=NONE
|
|
||||||
Dma.UART5_RX.3.SyncEnable=DISABLE
|
|
||||||
Dma.UART5_RX.3.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
|
|
||||||
Dma.UART5_RX.3.SyncRequestNumber=1
|
|
||||||
Dma.UART5_RX.3.SyncSignalID=NONE
|
|
||||||
FDCAN1.AutoRetransmission=ENABLE
|
|
||||||
FDCAN1.CalculateBaudRateNominal=1000000
|
|
||||||
FDCAN1.CalculateTimeBitNominal=1000
|
|
||||||
FDCAN1.CalculateTimeQuantumNominal=200.0
|
|
||||||
FDCAN1.IPParameters=CalculateTimeQuantumNominal,CalculateTimeBitNominal,CalculateBaudRateNominal,RxFifo0ElmtsNbr,TxFifoQueueElmtsNbr,NominalPrescaler,StdFiltersNbr,NominalTimeSeg1,AutoRetransmission
|
|
||||||
FDCAN1.NominalPrescaler=24
|
|
||||||
FDCAN1.NominalTimeSeg1=3
|
|
||||||
FDCAN1.RxFifo0ElmtsNbr=32
|
|
||||||
FDCAN1.StdFiltersNbr=1
|
|
||||||
FDCAN1.TxFifoQueueElmtsNbr=32
|
|
||||||
FDCAN2.AutoRetransmission=ENABLE
|
|
||||||
FDCAN2.CalculateBaudRateNominal=1000000
|
|
||||||
FDCAN2.CalculateTimeBitNominal=1000
|
|
||||||
FDCAN2.CalculateTimeQuantumNominal=200.0
|
|
||||||
FDCAN2.IPParameters=CalculateTimeQuantumNominal,CalculateTimeBitNominal,CalculateBaudRateNominal,MessageRAMOffset,RxFifo0ElmtsNbr,TxFifoQueueElmtsNbr,NominalPrescaler,StdFiltersNbr,NominalTimeSeg1,AutoRetransmission,RxFifo1ElmtsNbr
|
|
||||||
FDCAN2.MessageRAMOffset=0x406
|
|
||||||
FDCAN2.NominalPrescaler=24
|
|
||||||
FDCAN2.NominalTimeSeg1=3
|
|
||||||
FDCAN2.RxFifo0ElmtsNbr=32
|
|
||||||
FDCAN2.RxFifo1ElmtsNbr=32
|
|
||||||
FDCAN2.StdFiltersNbr=1
|
|
||||||
FDCAN2.TxFifoQueueElmtsNbr=32
|
|
||||||
FDCAN3.AutoRetransmission=ENABLE
|
|
||||||
FDCAN3.CalculateBaudRateNominal=1000000
|
|
||||||
FDCAN3.CalculateTimeBitNominal=1000
|
|
||||||
FDCAN3.CalculateTimeQuantumNominal=200.0
|
|
||||||
FDCAN3.ExtFiltersNbr=1
|
|
||||||
FDCAN3.IPParameters=CalculateTimeQuantumNominal,CalculateTimeBitNominal,CalculateBaudRateNominal,MessageRAMOffset,RxFifo0ElmtsNbr,TxFifoQueueElmtsNbr,NominalPrescaler,StdFiltersNbr,NominalTimeSeg1,AutoRetransmission,RxFifo1ElmtsNbr,ExtFiltersNbr
|
|
||||||
FDCAN3.MessageRAMOffset=0x812
|
|
||||||
FDCAN3.NominalPrescaler=24
|
|
||||||
FDCAN3.NominalTimeSeg1=3
|
|
||||||
FDCAN3.RxFifo0ElmtsNbr=32
|
|
||||||
FDCAN3.RxFifo1ElmtsNbr=32
|
|
||||||
FDCAN3.StdFiltersNbr=1
|
|
||||||
FDCAN3.TxFifoQueueElmtsNbr=32
|
|
||||||
FREERTOS.IPParameters=Tasks01,configTOTAL_HEAP_SIZE
|
|
||||||
FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
|
||||||
FREERTOS.configTOTAL_HEAP_SIZE=0x10000
|
|
||||||
File.Version=6
|
|
||||||
GPIO.groupedBy=Group By Peripherals
|
|
||||||
KeepUserPlacement=false
|
|
||||||
MMTAppRegionsCount=0
|
|
||||||
MMTConfigApplied=false
|
|
||||||
Mcu.CPN=STM32H723VGT6
|
|
||||||
Mcu.Family=STM32H7
|
|
||||||
Mcu.IP0=ADC1
|
|
||||||
Mcu.IP1=CORTEX_M7
|
|
||||||
Mcu.IP10=OCTOSPI1
|
|
||||||
Mcu.IP11=RCC
|
|
||||||
Mcu.IP12=SPI1
|
|
||||||
Mcu.IP13=SPI2
|
|
||||||
Mcu.IP14=SYS
|
|
||||||
Mcu.IP15=TIM1
|
|
||||||
Mcu.IP16=TIM2
|
|
||||||
Mcu.IP17=TIM3
|
|
||||||
Mcu.IP18=TIM12
|
|
||||||
Mcu.IP19=UART5
|
|
||||||
Mcu.IP2=DEBUG
|
|
||||||
Mcu.IP20=UART7
|
|
||||||
Mcu.IP21=USART1
|
|
||||||
Mcu.IP22=USART2
|
|
||||||
Mcu.IP23=USART3
|
|
||||||
Mcu.IP24=USART10
|
|
||||||
Mcu.IP25=USB_OTG_HS
|
|
||||||
Mcu.IP3=DMA
|
|
||||||
Mcu.IP4=FDCAN1
|
|
||||||
Mcu.IP5=FDCAN2
|
|
||||||
Mcu.IP6=FDCAN3
|
|
||||||
Mcu.IP7=FREERTOS
|
|
||||||
Mcu.IP8=MEMORYMAP
|
|
||||||
Mcu.IP9=NVIC
|
|
||||||
Mcu.IPNb=26
|
|
||||||
Mcu.Name=STM32H723VGTx
|
|
||||||
Mcu.Package=LQFP100
|
|
||||||
Mcu.Pin0=PE2
|
|
||||||
Mcu.Pin1=PE3
|
|
||||||
Mcu.Pin10=PC3_C
|
|
||||||
Mcu.Pin11=PA0
|
|
||||||
Mcu.Pin12=PA1
|
|
||||||
Mcu.Pin13=PA2
|
|
||||||
Mcu.Pin14=PA3
|
|
||||||
Mcu.Pin15=PA5
|
|
||||||
Mcu.Pin16=PA7
|
|
||||||
Mcu.Pin17=PC4
|
|
||||||
Mcu.Pin18=PC5
|
|
||||||
Mcu.Pin19=PB0
|
|
||||||
Mcu.Pin2=PC13
|
|
||||||
Mcu.Pin20=PB1
|
|
||||||
Mcu.Pin21=PB2
|
|
||||||
Mcu.Pin22=PE7
|
|
||||||
Mcu.Pin23=PE8
|
|
||||||
Mcu.Pin24=PE9
|
|
||||||
Mcu.Pin25=PE10
|
|
||||||
Mcu.Pin26=PE11
|
|
||||||
Mcu.Pin27=PE12
|
|
||||||
Mcu.Pin28=PE13
|
|
||||||
Mcu.Pin29=PE15
|
|
||||||
Mcu.Pin3=PC14-OSC32_IN
|
|
||||||
Mcu.Pin30=PB10
|
|
||||||
Mcu.Pin31=PB11
|
|
||||||
Mcu.Pin32=PB12
|
|
||||||
Mcu.Pin33=PB13
|
|
||||||
Mcu.Pin34=PB14
|
|
||||||
Mcu.Pin35=PB15
|
|
||||||
Mcu.Pin36=PD8
|
|
||||||
Mcu.Pin37=PD9
|
|
||||||
Mcu.Pin38=PD10
|
|
||||||
Mcu.Pin39=PD11
|
|
||||||
Mcu.Pin4=PC15-OSC32_OUT
|
|
||||||
Mcu.Pin40=PD12
|
|
||||||
Mcu.Pin41=PD13
|
|
||||||
Mcu.Pin42=PA8
|
|
||||||
Mcu.Pin43=PA9
|
|
||||||
Mcu.Pin44=PA10
|
|
||||||
Mcu.Pin45=PA11
|
|
||||||
Mcu.Pin46=PA12
|
|
||||||
Mcu.Pin47=PA13(JTMS/SWDIO)
|
|
||||||
Mcu.Pin48=PA14(JTCK/SWCLK)
|
|
||||||
Mcu.Pin49=PA15(JTDI)
|
|
||||||
Mcu.Pin5=PH0-OSC_IN
|
|
||||||
Mcu.Pin50=PC12
|
|
||||||
Mcu.Pin51=PD0
|
|
||||||
Mcu.Pin52=PD1
|
|
||||||
Mcu.Pin53=PD2
|
|
||||||
Mcu.Pin54=PD4
|
|
||||||
Mcu.Pin55=PD5
|
|
||||||
Mcu.Pin56=PD6
|
|
||||||
Mcu.Pin57=PD7
|
|
||||||
Mcu.Pin58=PB3(JTDO/TRACESWO)
|
|
||||||
Mcu.Pin59=PB5
|
|
||||||
Mcu.Pin6=PH1-OSC_OUT
|
|
||||||
Mcu.Pin60=PB6
|
|
||||||
Mcu.Pin61=VP_FREERTOS_VS_CMSIS_V2
|
|
||||||
Mcu.Pin62=VP_OCTOSPI1_VS_octo
|
|
||||||
Mcu.Pin63=VP_SYS_VS_tim23
|
|
||||||
Mcu.Pin64=VP_MEMORYMAP_VS_MEMORYMAP
|
|
||||||
Mcu.Pin7=PC0
|
|
||||||
Mcu.Pin8=PC1
|
|
||||||
Mcu.Pin9=PC2_C
|
|
||||||
Mcu.PinsNb=65
|
|
||||||
Mcu.ThirdPartyNb=0
|
|
||||||
Mcu.UserConstants=
|
|
||||||
Mcu.UserName=STM32H723VGTx
|
|
||||||
MxCube.Version=6.15.0
|
|
||||||
MxDb.Version=DB.6.0.150
|
|
||||||
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.DMA1_Stream0_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA1_Stream1_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA1_Stream2_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA1_Stream3_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.EXTI15_10_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.FDCAN1_IT0_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.FDCAN1_IT1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.FDCAN2_IT0_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.FDCAN2_IT1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.FDCAN3_IT0_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.FDCAN3_IT1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.ForceEnableDMAVector=true
|
|
||||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
|
|
||||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
|
||||||
NVIC.SPI2_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
|
|
||||||
NVIC.SavedPendsvIrqHandlerGenerated=true
|
|
||||||
NVIC.SavedSvcallIrqHandlerGenerated=true
|
|
||||||
NVIC.SavedSystickIrqHandlerGenerated=true
|
|
||||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
|
|
||||||
NVIC.TIM23_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true
|
|
||||||
NVIC.TimeBase=TIM23_IRQn
|
|
||||||
NVIC.TimeBaseIP=TIM23
|
|
||||||
NVIC.UART5_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.UART7_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.USART10_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.USART1_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.USART2_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.USART3_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
PA0.Locked=true
|
|
||||||
PA0.Signal=S_TIM2_CH1_ETR
|
|
||||||
PA1.Locked=true
|
|
||||||
PA1.Mode=OCTOSPI1_IOL_Port1L
|
|
||||||
PA1.Signal=OCTOSPIM_P1_IO3
|
|
||||||
PA10.Locked=true
|
|
||||||
PA10.Mode=Asynchronous
|
|
||||||
PA10.Signal=USART1_RX
|
|
||||||
PA11.Mode=Device_Only_FS
|
|
||||||
PA11.Signal=USB_OTG_HS_DM
|
|
||||||
PA12.Mode=Device_Only_FS
|
|
||||||
PA12.Signal=USB_OTG_HS_DP
|
|
||||||
PA13(JTMS/SWDIO).Locked=true
|
|
||||||
PA13(JTMS/SWDIO).Mode=Serial_Wire
|
|
||||||
PA13(JTMS/SWDIO).Signal=DEBUG_JTMS-SWDIO
|
|
||||||
PA14(JTCK/SWCLK).Locked=true
|
|
||||||
PA14(JTCK/SWCLK).Mode=Serial_Wire
|
|
||||||
PA14(JTCK/SWCLK).Signal=DEBUG_JTCK-SWCLK
|
|
||||||
PA15(JTDI).Locked=true
|
|
||||||
PA15(JTDI).Signal=GPIO_Input
|
|
||||||
PA2.Locked=true
|
|
||||||
PA2.Signal=S_TIM2_CH3
|
|
||||||
PA3.Locked=true
|
|
||||||
PA3.Mode=OCTOSPI1_IOL_Port1L
|
|
||||||
PA3.Signal=OCTOSPIM_P1_IO2
|
|
||||||
PA5.Locked=true
|
|
||||||
PA5.Signal=ADCx_INP19
|
|
||||||
PA7.GPIOParameters=GPIO_Label
|
|
||||||
PA7.GPIO_Label=WS2812
|
|
||||||
PA7.Locked=true
|
|
||||||
PA7.Signal=S_TIM3_CH2
|
|
||||||
PA8.Locked=true
|
|
||||||
PA8.Mode=Clock-out-1
|
|
||||||
PA8.Signal=RCC_MCO_1
|
|
||||||
PA9.Locked=true
|
|
||||||
PA9.Mode=Asynchronous
|
|
||||||
PA9.Signal=USART1_TX
|
|
||||||
PB0.Locked=true
|
|
||||||
PB0.Mode=OCTOSPI1_IOL_Port1L
|
|
||||||
PB0.Signal=OCTOSPIM_P1_IO1
|
|
||||||
PB1.GPIOParameters=GPIO_Label
|
|
||||||
PB1.GPIO_Label=IMU_HEAT
|
|
||||||
PB1.Locked=true
|
|
||||||
PB1.Signal=S_TIM3_CH4
|
|
||||||
PB10.GPIOParameters=GPIO_Label
|
|
||||||
PB10.GPIO_Label=LCD_BLK
|
|
||||||
PB10.Locked=true
|
|
||||||
PB10.Signal=GPIO_Output
|
|
||||||
PB11.GPIOParameters=GPIO_Label
|
|
||||||
PB11.GPIO_Label=LCD_RES
|
|
||||||
PB11.Locked=true
|
|
||||||
PB11.Signal=GPIO_Output
|
|
||||||
PB12.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
|
||||||
PB12.GPIO_Label=DCMI_REST
|
|
||||||
PB12.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PB12.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PB12.Locked=true
|
|
||||||
PB12.PinState=GPIO_PIN_SET
|
|
||||||
PB12.Signal=GPIO_Output
|
|
||||||
PB13.GPIOParameters=GPIO_Speed
|
|
||||||
PB13.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PB13.Locked=true
|
|
||||||
PB13.Mode=Full_Duplex_Master
|
|
||||||
PB13.Signal=SPI2_SCK
|
|
||||||
PB14.Mode=Hardware Flow Control (RS485)
|
|
||||||
PB14.Signal=USART3_DE
|
|
||||||
PB15.GPIOParameters=GPIO_Label
|
|
||||||
PB15.GPIO_Label=BUZZER
|
|
||||||
PB15.Locked=true
|
|
||||||
PB15.Signal=S_TIM12_CH2
|
|
||||||
PB2.Locked=true
|
|
||||||
PB2.Mode=O1_P1_CLK
|
|
||||||
PB2.Signal=OCTOSPIM_P1_CLK
|
|
||||||
PB3(JTDO/TRACESWO).GPIOParameters=GPIO_Speed
|
|
||||||
PB3(JTDO/TRACESWO).GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PB3(JTDO/TRACESWO).Mode=TX_Only_Simplex_Unidirect_Master
|
|
||||||
PB3(JTDO/TRACESWO).Signal=SPI1_SCK
|
|
||||||
PB5.Locked=true
|
|
||||||
PB5.Mode=FDCAN_Activate
|
|
||||||
PB5.Signal=FDCAN2_RX
|
|
||||||
PB6.Locked=true
|
|
||||||
PB6.Mode=FDCAN_Activate
|
|
||||||
PB6.Signal=FDCAN2_TX
|
|
||||||
PC0.GPIOParameters=GPIO_Speed,PinState,GPIO_Label
|
|
||||||
PC0.GPIO_Label=ACCL_CS
|
|
||||||
PC0.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PC0.Locked=true
|
|
||||||
PC0.PinState=GPIO_PIN_SET
|
|
||||||
PC0.Signal=GPIO_Output
|
|
||||||
PC1.GPIOParameters=GPIO_Speed
|
|
||||||
PC1.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PC1.Mode=Full_Duplex_Master
|
|
||||||
PC1.Signal=SPI2_MOSI
|
|
||||||
PC12.Mode=Asynchronous
|
|
||||||
PC12.Signal=UART5_TX
|
|
||||||
PC13.GPIOParameters=PinState,GPIO_Label
|
|
||||||
PC13.GPIO_Label=POWER_24V_2
|
|
||||||
PC13.Locked=true
|
|
||||||
PC13.PinState=GPIO_PIN_SET
|
|
||||||
PC13.Signal=GPIO_Output
|
|
||||||
PC14-OSC32_IN.GPIOParameters=PinState,GPIO_Label
|
|
||||||
PC14-OSC32_IN.GPIO_Label=POWER_24V_1
|
|
||||||
PC14-OSC32_IN.Locked=true
|
|
||||||
PC14-OSC32_IN.PinState=GPIO_PIN_SET
|
|
||||||
PC14-OSC32_IN.Signal=GPIO_Output
|
|
||||||
PC15-OSC32_OUT.GPIOParameters=PinState,GPIO_Label
|
|
||||||
PC15-OSC32_OUT.GPIO_Label=POWER_5V
|
|
||||||
PC15-OSC32_OUT.Locked=true
|
|
||||||
PC15-OSC32_OUT.PinState=GPIO_PIN_SET
|
|
||||||
PC15-OSC32_OUT.Signal=GPIO_Output
|
|
||||||
PC2_C.GPIOParameters=GPIO_Speed
|
|
||||||
PC2_C.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PC2_C.Mode=Full_Duplex_Master
|
|
||||||
PC2_C.Signal=SPI2_MISO
|
|
||||||
PC3_C.GPIOParameters=GPIO_Speed,PinState,GPIO_Label
|
|
||||||
PC3_C.GPIO_Label=GYRO_CS
|
|
||||||
PC3_C.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PC3_C.Locked=true
|
|
||||||
PC3_C.PinState=GPIO_PIN_SET
|
|
||||||
PC3_C.Signal=GPIO_Output
|
|
||||||
PC4.Locked=true
|
|
||||||
PC4.Signal=ADCx_INP4
|
|
||||||
PC5.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
|
||||||
PC5.GPIO_Label=DCMI_PWDN
|
|
||||||
PC5.GPIO_PuPd=GPIO_NOPULL
|
|
||||||
PC5.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PC5.Locked=true
|
|
||||||
PC5.PinState=GPIO_PIN_SET
|
|
||||||
PC5.Signal=GPIO_Output
|
|
||||||
PD0.Mode=FDCAN_Activate
|
|
||||||
PD0.Signal=FDCAN1_RX
|
|
||||||
PD1.Locked=true
|
|
||||||
PD1.Mode=FDCAN_Activate
|
|
||||||
PD1.Signal=FDCAN1_TX
|
|
||||||
PD10.GPIOParameters=GPIO_Label
|
|
||||||
PD10.GPIO_Label=LCD_DC
|
|
||||||
PD10.Locked=true
|
|
||||||
PD10.Signal=GPIO_Output
|
|
||||||
PD11.Locked=true
|
|
||||||
PD11.Mode=OCTOSPI1_IOL_Port1L
|
|
||||||
PD11.Signal=OCTOSPIM_P1_IO0
|
|
||||||
PD12.Mode=FDCAN_Activate
|
|
||||||
PD12.Signal=FDCAN3_RX
|
|
||||||
PD13.Locked=true
|
|
||||||
PD13.Mode=FDCAN_Activate
|
|
||||||
PD13.Signal=FDCAN3_TX
|
|
||||||
PD2.Mode=Asynchronous
|
|
||||||
PD2.Signal=UART5_RX
|
|
||||||
PD4.Locked=true
|
|
||||||
PD4.Mode=Hardware Flow Control (RS485)
|
|
||||||
PD4.Signal=USART2_DE
|
|
||||||
PD5.Locked=true
|
|
||||||
PD5.Mode=Asynchronous
|
|
||||||
PD5.Signal=USART2_TX
|
|
||||||
PD6.Locked=true
|
|
||||||
PD6.Mode=Asynchronous
|
|
||||||
PD6.Signal=USART2_RX
|
|
||||||
PD7.GPIOParameters=GPIO_Speed
|
|
||||||
PD7.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PD7.Locked=true
|
|
||||||
PD7.Mode=TX_Only_Simplex_Unidirect_Master
|
|
||||||
PD7.Signal=SPI1_MOSI
|
|
||||||
PD8.Mode=Asynchronous
|
|
||||||
PD8.Signal=USART3_TX
|
|
||||||
PD9.Mode=Asynchronous
|
|
||||||
PD9.Signal=USART3_RX
|
|
||||||
PE10.GPIOParameters=GPIO_Label
|
|
||||||
PE10.GPIO_Label=ACCL_INT
|
|
||||||
PE10.Locked=true
|
|
||||||
PE10.Signal=GPXTI10
|
|
||||||
PE11.Locked=true
|
|
||||||
PE11.Mode=OCTOSPI1_Port1_NCS
|
|
||||||
PE11.Signal=OCTOSPIM_P1_NCS
|
|
||||||
PE12.GPIOParameters=GPIO_Label
|
|
||||||
PE12.GPIO_Label=GYRO_INT
|
|
||||||
PE12.Locked=true
|
|
||||||
PE12.Signal=GPXTI12
|
|
||||||
PE13.Signal=S_TIM1_CH3
|
|
||||||
PE15.GPIOParameters=GPIO_Label
|
|
||||||
PE15.GPIO_Label=LCD_CS
|
|
||||||
PE15.Locked=true
|
|
||||||
PE15.Signal=GPIO_Output
|
|
||||||
PE2.Mode=Asynchronous
|
|
||||||
PE2.Signal=USART10_RX
|
|
||||||
PE3.Mode=Asynchronous
|
|
||||||
PE3.Signal=USART10_TX
|
|
||||||
PE7.Mode=Asynchronous
|
|
||||||
PE7.Signal=UART7_RX
|
|
||||||
PE8.Mode=Asynchronous
|
|
||||||
PE8.Signal=UART7_TX
|
|
||||||
PE9.Locked=true
|
|
||||||
PE9.Signal=S_TIM1_CH1
|
|
||||||
PH0-OSC_IN.Mode=HSE-External-Oscillator
|
|
||||||
PH0-OSC_IN.Signal=RCC_OSC_IN
|
|
||||||
PH1-OSC_OUT.Mode=HSE-External-Oscillator
|
|
||||||
PH1-OSC_OUT.Signal=RCC_OSC_OUT
|
|
||||||
PinOutPanel.RotationAngle=0
|
|
||||||
ProjectManager.AskForMigrate=true
|
|
||||||
ProjectManager.BackupPrevious=false
|
|
||||||
ProjectManager.CompilerLinker=GCC
|
|
||||||
ProjectManager.CompilerOptimize=6
|
|
||||||
ProjectManager.ComputerToolchain=false
|
|
||||||
ProjectManager.CoupleFile=true
|
|
||||||
ProjectManager.CustomerFirmwarePackage=
|
|
||||||
ProjectManager.DefaultFWLocation=true
|
|
||||||
ProjectManager.DeletePrevious=true
|
|
||||||
ProjectManager.DeviceId=STM32H723VGTx
|
|
||||||
ProjectManager.FirmwarePackage=STM32Cube FW_H7 V1.12.1
|
|
||||||
ProjectManager.FreePins=false
|
|
||||||
ProjectManager.HalAssertFull=false
|
|
||||||
ProjectManager.HeapSize=0x1000
|
|
||||||
ProjectManager.KeepUserCode=true
|
|
||||||
ProjectManager.LastFirmware=true
|
|
||||||
ProjectManager.LibraryCopy=0
|
|
||||||
ProjectManager.MainLocation=Core/Src
|
|
||||||
ProjectManager.NoMain=false
|
|
||||||
ProjectManager.PreviousToolchain=
|
|
||||||
ProjectManager.ProjectBuild=false
|
|
||||||
ProjectManager.ProjectFileName=CtrBoard-H7_ALL.ioc
|
|
||||||
ProjectManager.ProjectName=CtrBoard-H7_ALL
|
|
||||||
ProjectManager.ProjectStructure=
|
|
||||||
ProjectManager.RegisterCallBack=
|
|
||||||
ProjectManager.StackSize=0x2000
|
|
||||||
ProjectManager.TargetToolchain=MDK-ARM V5.32
|
|
||||||
ProjectManager.ToolChainLocation=
|
|
||||||
ProjectManager.UAScriptAfterPath=
|
|
||||||
ProjectManager.UAScriptBeforePath=
|
|
||||||
ProjectManager.UnderRoot=false
|
|
||||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_ADC1_Init-ADC1-false-HAL-true,5-MX_TIM12_Init-TIM12-false-HAL-true,6-MX_SPI1_Init-SPI1-false-HAL-true,7-MX_SPI2_Init-SPI2-false-HAL-true,8-MX_TIM3_Init-TIM3-false-HAL-true,9-MX_USART1_UART_Init-USART1-false-HAL-true,10-MX_USART2_UART_Init-USART2-false-HAL-true,11-MX_USART3_UART_Init-USART3-false-HAL-true,12-MX_UART7_Init-UART7-false-HAL-true,13-MX_USART10_UART_Init-USART10-false-HAL-true,14-MX_FDCAN1_Init-FDCAN1-false-HAL-true,15-MX_FDCAN2_Init-FDCAN2-false-HAL-true,16-MX_FDCAN3_Init-FDCAN3-false-HAL-true,17-MX_TIM1_Init-TIM1-false-HAL-true,18-MX_TIM2_Init-TIM2-false-HAL-true,19-MX_OCTOSPI1_Init-OCTOSPI1-false-HAL-true,20-MX_USB_OTG_HS_PCD_Init-USB_OTG_HS-false-HAL-true,21-MX_UART5_Init-UART5-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true
|
|
||||||
RCC.ADCFreq_Value=96000000
|
|
||||||
RCC.AHB12Freq_Value=240000000
|
|
||||||
RCC.AHB4Freq_Value=240000000
|
|
||||||
RCC.APB1Freq_Value=120000000
|
|
||||||
RCC.APB2Freq_Value=120000000
|
|
||||||
RCC.APB3Freq_Value=120000000
|
|
||||||
RCC.APB4Freq_Value=120000000
|
|
||||||
RCC.AXIClockFreq_Value=240000000
|
|
||||||
RCC.CECFreq_Value=32000
|
|
||||||
RCC.CKPERFreq_Value=64000000
|
|
||||||
RCC.CortexFreq_Value=480000000
|
|
||||||
RCC.CpuClockFreq_Value=480000000
|
|
||||||
RCC.D1CPREFreq_Value=480000000
|
|
||||||
RCC.D1PPRE=RCC_APB3_DIV2
|
|
||||||
RCC.D2PPRE1=RCC_APB1_DIV2
|
|
||||||
RCC.D2PPRE2=RCC_APB2_DIV2
|
|
||||||
RCC.D3PPRE=RCC_APB4_DIV2
|
|
||||||
RCC.DFSDMACLkFreq_Value=120000000
|
|
||||||
RCC.DFSDMFreq_Value=120000000
|
|
||||||
RCC.DIVM1=2
|
|
||||||
RCC.DIVM2=2
|
|
||||||
RCC.DIVN1=40
|
|
||||||
RCC.DIVN2=16
|
|
||||||
RCC.DIVP1=1
|
|
||||||
RCC.DIVP1Freq_Value=480000000
|
|
||||||
RCC.DIVP2Freq_Value=96000000
|
|
||||||
RCC.DIVP3Freq_Value=48375000
|
|
||||||
RCC.DIVQ1=4
|
|
||||||
RCC.DIVQ1Freq_Value=120000000
|
|
||||||
RCC.DIVQ2Freq_Value=96000000
|
|
||||||
RCC.DIVQ3Freq_Value=48375000
|
|
||||||
RCC.DIVR1Freq_Value=240000000
|
|
||||||
RCC.DIVR2Freq_Value=96000000
|
|
||||||
RCC.DIVR3Freq_Value=48375000
|
|
||||||
RCC.EnbaleCSS=false
|
|
||||||
RCC.FDCANFreq_Value=120000000
|
|
||||||
RCC.FMCFreq_Value=240000000
|
|
||||||
RCC.FamilyName=M
|
|
||||||
RCC.HCLK3ClockFreq_Value=240000000
|
|
||||||
RCC.HCLKFreq_Value=240000000
|
|
||||||
RCC.HPRE=RCC_HCLK_DIV2
|
|
||||||
RCC.HSE_VALUE=24000000
|
|
||||||
RCC.I2C123Freq_Value=120000000
|
|
||||||
RCC.I2C4Freq_Value=120000000
|
|
||||||
RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,D1PPRE,D2PPRE1,D2PPRE2,D3PPRE,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVM2,DIVN1,DIVN2,DIVP1,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3Freq_Value,DIVQ1,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2Freq_Value,DIVR3Freq_Value,EnbaleCSS,FDCANFreq_Value,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,HPRE,HSE_VALUE,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL2FRACN,PLL2_VCI_Range-AdvancedSettings,PLL2_VCO_SEL-AdvancedSettings,PLL3FRACN,PLL3_VCO_SEL-AdvancedSettings,PLLFRACN,PLLSourceVirtual,QSPIFreq_Value,RNGFreq_Value,RTCFreq_Value,SAI1Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123Freq_Value,SPI45Freq_Value,SPI6CLockSelection,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBCLockSelection,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value
|
|
||||||
RCC.LPTIM1Freq_Value=120000000
|
|
||||||
RCC.LPTIM2Freq_Value=120000000
|
|
||||||
RCC.LPTIM345Freq_Value=120000000
|
|
||||||
RCC.LPUART1Freq_Value=120000000
|
|
||||||
RCC.LTDCFreq_Value=48375000
|
|
||||||
RCC.MCO1PinFreq_Value=64000000
|
|
||||||
RCC.MCO2PinFreq_Value=480000000
|
|
||||||
RCC.PLL2FRACN=0
|
|
||||||
RCC.PLL2_VCI_Range-AdvancedSettings=RCC_PLL2VCIRANGE_0
|
|
||||||
RCC.PLL2_VCO_SEL-AdvancedSettings=RCC_PLL2VCOWIDE
|
|
||||||
RCC.PLL3FRACN=0
|
|
||||||
RCC.PLL3_VCO_SEL-AdvancedSettings=RCC_PLL3VCOMEDIUM
|
|
||||||
RCC.PLLFRACN=0
|
|
||||||
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
|
|
||||||
RCC.QSPIFreq_Value=240000000
|
|
||||||
RCC.RNGFreq_Value=48000000
|
|
||||||
RCC.RTCFreq_Value=32000
|
|
||||||
RCC.SAI1Freq_Value=120000000
|
|
||||||
RCC.SAI4AFreq_Value=120000000
|
|
||||||
RCC.SAI4BFreq_Value=120000000
|
|
||||||
RCC.SDMMCFreq_Value=120000000
|
|
||||||
RCC.SPDIFRXFreq_Value=120000000
|
|
||||||
RCC.SPI123Freq_Value=120000000
|
|
||||||
RCC.SPI45Freq_Value=120000000
|
|
||||||
RCC.SPI6CLockSelection=RCC_SPI6CLKSOURCE_HSE
|
|
||||||
RCC.SPI6Freq_Value=24000000
|
|
||||||
RCC.SWPMI1Freq_Value=120000000
|
|
||||||
RCC.SYSCLKFreq_VALUE=480000000
|
|
||||||
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
|
||||||
RCC.Tim1OutputFreq_Value=240000000
|
|
||||||
RCC.Tim2OutputFreq_Value=240000000
|
|
||||||
RCC.TraceFreq_Value=240000000
|
|
||||||
RCC.USART16Freq_Value=120000000
|
|
||||||
RCC.USART234578Freq_Value=120000000
|
|
||||||
RCC.USBCLockSelection=RCC_USBCLKSOURCE_HSI48
|
|
||||||
RCC.USBFreq_Value=48000000
|
|
||||||
RCC.VCO1OutputFreq_Value=480000000
|
|
||||||
RCC.VCO2OutputFreq_Value=192000000
|
|
||||||
RCC.VCO3OutputFreq_Value=96750000
|
|
||||||
RCC.VCOInput1Freq_Value=12000000
|
|
||||||
RCC.VCOInput2Freq_Value=12000000
|
|
||||||
RCC.VCOInput3Freq_Value=750000
|
|
||||||
SH.ADCx_INP19.0=ADC1_INP19,IN19-Single-Ended
|
|
||||||
SH.ADCx_INP19.ConfNb=1
|
|
||||||
SH.ADCx_INP4.0=ADC1_INP4,IN4-Single-Ended
|
|
||||||
SH.ADCx_INP4.ConfNb=1
|
|
||||||
SH.GPXTI10.0=GPIO_EXTI10
|
|
||||||
SH.GPXTI10.ConfNb=1
|
|
||||||
SH.GPXTI12.0=GPIO_EXTI12
|
|
||||||
SH.GPXTI12.ConfNb=1
|
|
||||||
SH.S_TIM12_CH2.0=TIM12_CH2,PWM Generation2 CH2
|
|
||||||
SH.S_TIM12_CH2.ConfNb=1
|
|
||||||
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
|
|
||||||
SH.S_TIM1_CH1.ConfNb=1
|
|
||||||
SH.S_TIM1_CH3.0=TIM1_CH3,PWM Generation3 CH3
|
|
||||||
SH.S_TIM1_CH3.ConfNb=1
|
|
||||||
SH.S_TIM2_CH1_ETR.0=TIM2_CH1,PWM Generation1 CH1
|
|
||||||
SH.S_TIM2_CH1_ETR.ConfNb=1
|
|
||||||
SH.S_TIM2_CH3.0=TIM2_CH3,PWM Generation3 CH3
|
|
||||||
SH.S_TIM2_CH3.ConfNb=1
|
|
||||||
SH.S_TIM3_CH2.0=TIM3_CH2,PWM Generation2 CH2
|
|
||||||
SH.S_TIM3_CH2.ConfNb=1
|
|
||||||
SH.S_TIM3_CH4.0=TIM3_CH4,PWM Generation4 CH4
|
|
||||||
SH.S_TIM3_CH4.ConfNb=1
|
|
||||||
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4
|
|
||||||
SPI1.CLKPolarity=SPI_POLARITY_HIGH
|
|
||||||
SPI1.CalculateBaudRate=30.0 MBits/s
|
|
||||||
SPI1.DataSize=SPI_DATASIZE_8BIT
|
|
||||||
SPI1.Direction=SPI_DIRECTION_2LINES_TXONLY
|
|
||||||
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler,CLKPolarity
|
|
||||||
SPI1.Mode=SPI_MODE_MASTER
|
|
||||||
SPI1.VirtualType=VM_MASTER
|
|
||||||
SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_32
|
|
||||||
SPI2.CLKPhase=SPI_PHASE_2EDGE
|
|
||||||
SPI2.CLKPolarity=SPI_POLARITY_HIGH
|
|
||||||
SPI2.CalculateBaudRate=3.75 MBits/s
|
|
||||||
SPI2.DataSize=SPI_DATASIZE_8BIT
|
|
||||||
SPI2.Direction=SPI_DIRECTION_2LINES
|
|
||||||
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler,CLKPolarity,CLKPhase
|
|
||||||
SPI2.Mode=SPI_MODE_MASTER
|
|
||||||
SPI2.VirtualType=VM_MASTER
|
|
||||||
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
|
||||||
TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
|
||||||
TIM1.IPParameters=Channel-PWM Generation3 CH3,Channel-PWM Generation1 CH1,Period,Pulse-PWM Generation1 CH1,Pulse-PWM Generation3 CH3,Prescaler
|
|
||||||
TIM1.Period=10000
|
|
||||||
TIM1.Prescaler=24
|
|
||||||
TIM1.Pulse-PWM\ Generation1\ CH1=5000
|
|
||||||
TIM1.Pulse-PWM\ Generation3\ CH3=5000
|
|
||||||
TIM12.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
|
||||||
TIM12.IPParameters=Channel-PWM Generation2 CH2,Prescaler,Period
|
|
||||||
TIM12.Period=2000-1
|
|
||||||
TIM12.Prescaler=24-1
|
|
||||||
TIM2.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
|
||||||
TIM2.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
|
||||||
TIM2.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation3 CH3,Period,Pulse-PWM Generation1 CH1,Pulse-PWM Generation3 CH3,Prescaler
|
|
||||||
TIM2.Period=10000
|
|
||||||
TIM2.Prescaler=24
|
|
||||||
TIM2.Pulse-PWM\ Generation1\ CH1=5000
|
|
||||||
TIM2.Pulse-PWM\ Generation3\ CH3=5000
|
|
||||||
TIM3.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
|
|
||||||
TIM3.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
|
||||||
TIM3.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4
|
|
||||||
TIM3.IPParameters=Channel-PWM Generation4 CH4,Prescaler,Period,AutoReloadPreload,Channel-PWM Generation2 CH2
|
|
||||||
TIM3.Period=10000-1
|
|
||||||
TIM3.Prescaler=24-1
|
|
||||||
UART5.BaudRate=100000
|
|
||||||
UART5.IPParameters=Mode,WordLength,Parity,BaudRate
|
|
||||||
UART5.Mode=MODE_RX
|
|
||||||
UART5.Parity=PARITY_EVEN
|
|
||||||
UART5.WordLength=WORDLENGTH_9B
|
|
||||||
UART7.BaudRate=921600
|
|
||||||
UART7.IPParameters=BaudRate
|
|
||||||
USART1.BaudRate=921600
|
|
||||||
USART1.IPParameters=VirtualMode-Asynchronous,BaudRate
|
|
||||||
USART1.VirtualMode-Asynchronous=VM_ASYNC
|
|
||||||
USART10.BaudRate=921600
|
|
||||||
USART10.IPParameters=VirtualMode,BaudRate
|
|
||||||
USART10.VirtualMode=VM_ASYNC
|
|
||||||
USART2.BaudRate=921600
|
|
||||||
USART2.IPParameters=VirtualMode-Asynchronous,VirtualMode-Hardware Flow Control (RS485),BaudRate
|
|
||||||
USART2.VirtualMode-Asynchronous=VM_ASYNC
|
|
||||||
USART2.VirtualMode-Hardware\ Flow\ Control\ (RS485)=VM_ASYNC
|
|
||||||
USART3.BaudRate=921600
|
|
||||||
USART3.IPParameters=VirtualMode-Asynchronous,VirtualMode-Hardware Flow Control (RS485),BaudRate
|
|
||||||
USART3.VirtualMode-Asynchronous=VM_ASYNC
|
|
||||||
USART3.VirtualMode-Hardware\ Flow\ Control\ (RS485)=VM_ASYNC
|
|
||||||
USB_OTG_HS.IPParameters=VirtualMode-Device_Only_FS
|
|
||||||
USB_OTG_HS.VirtualMode-Device_Only_FS=Device_Only_FS
|
|
||||||
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
|
|
||||||
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
|
|
||||||
VP_MEMORYMAP_VS_MEMORYMAP.Mode=CurAppReg
|
|
||||||
VP_MEMORYMAP_VS_MEMORYMAP.Signal=MEMORYMAP_VS_MEMORYMAP
|
|
||||||
VP_OCTOSPI1_VS_octo.Mode=octo_mode
|
|
||||||
VP_OCTOSPI1_VS_octo.Signal=OCTOSPI1_VS_octo
|
|
||||||
VP_SYS_VS_tim23.Mode=TIM23
|
|
||||||
VP_SYS_VS_tim23.Signal=SYS_VS_tim23
|
|
||||||
board=custom
|
|
||||||
rtos.0.ip=FREERTOS
|
|
||||||
@ -1,743 +0,0 @@
|
|||||||
#MicroXplorer Configuration settings - do not modify
|
|
||||||
ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_TEMPSENSOR
|
|
||||||
ADC1.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV6
|
|
||||||
ADC1.IPParameters=Rank-0\#ChannelRegularConversion,master,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,ClockPrescaler
|
|
||||||
ADC1.NbrOfConversionFlag=1
|
|
||||||
ADC1.Rank-0\#ChannelRegularConversion=1
|
|
||||||
ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
|
||||||
ADC1.master=1
|
|
||||||
ADC3.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_8
|
|
||||||
ADC3.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV6
|
|
||||||
ADC3.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,ClockPrescaler
|
|
||||||
ADC3.NbrOfConversionFlag=1
|
|
||||||
ADC3.Rank-0\#ChannelRegularConversion=1
|
|
||||||
ADC3.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
|
||||||
CAD.formats=
|
|
||||||
CAD.pinconfig=
|
|
||||||
CAD.provider=
|
|
||||||
CAN1.ABOM=DISABLE
|
|
||||||
CAN1.BS1=CAN_BS1_6TQ
|
|
||||||
CAN1.BS2=CAN_BS2_7TQ
|
|
||||||
CAN1.CalculateBaudRate=1000000
|
|
||||||
CAN1.CalculateTimeBit=1000
|
|
||||||
CAN1.CalculateTimeQuantum=71.42857142857143
|
|
||||||
CAN1.IPParameters=CalculateTimeQuantum,BS1,BS2,Prescaler,TXFP,ABOM,CalculateTimeBit,CalculateBaudRate,NART
|
|
||||||
CAN1.NART=ENABLE
|
|
||||||
CAN1.Prescaler=3
|
|
||||||
CAN1.TXFP=ENABLE
|
|
||||||
CAN2.BS1=CAN_BS1_6TQ
|
|
||||||
CAN2.BS2=CAN_BS2_7TQ
|
|
||||||
CAN2.CalculateBaudRate=1000000
|
|
||||||
CAN2.CalculateTimeBit=1000
|
|
||||||
CAN2.CalculateTimeQuantum=71.42857142857143
|
|
||||||
CAN2.IPParameters=CalculateTimeQuantum,BS1,BS2,Prescaler,TXFP,CalculateTimeBit,CalculateBaudRate,NART
|
|
||||||
CAN2.NART=ENABLE
|
|
||||||
CAN2.Prescaler=3
|
|
||||||
CAN2.TXFP=ENABLE
|
|
||||||
Dma.I2C2_TX.2.Direction=DMA_MEMORY_TO_PERIPH
|
|
||||||
Dma.I2C2_TX.2.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.I2C2_TX.2.Instance=DMA1_Stream7
|
|
||||||
Dma.I2C2_TX.2.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.I2C2_TX.2.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.I2C2_TX.2.Mode=DMA_NORMAL
|
|
||||||
Dma.I2C2_TX.2.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.I2C2_TX.2.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.I2C2_TX.2.Priority=DMA_PRIORITY_HIGH
|
|
||||||
Dma.I2C2_TX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
Dma.I2C3_RX.7.Direction=DMA_PERIPH_TO_MEMORY
|
|
||||||
Dma.I2C3_RX.7.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.I2C3_RX.7.Instance=DMA1_Stream2
|
|
||||||
Dma.I2C3_RX.7.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.I2C3_RX.7.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.I2C3_RX.7.Mode=DMA_NORMAL
|
|
||||||
Dma.I2C3_RX.7.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.I2C3_RX.7.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.I2C3_RX.7.Priority=DMA_PRIORITY_LOW
|
|
||||||
Dma.I2C3_RX.7.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
Dma.Request0=SPI1_RX
|
|
||||||
Dma.Request1=SPI1_TX
|
|
||||||
Dma.Request2=I2C2_TX
|
|
||||||
Dma.Request3=USART3_RX
|
|
||||||
Dma.Request4=USART6_RX
|
|
||||||
Dma.Request5=USART6_TX
|
|
||||||
Dma.Request6=USART1_TX
|
|
||||||
Dma.Request7=I2C3_RX
|
|
||||||
Dma.Request8=USART1_RX
|
|
||||||
Dma.RequestsNb=9
|
|
||||||
Dma.SPI1_RX.0.Direction=DMA_PERIPH_TO_MEMORY
|
|
||||||
Dma.SPI1_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.SPI1_RX.0.Instance=DMA2_Stream2
|
|
||||||
Dma.SPI1_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.SPI1_RX.0.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.SPI1_RX.0.Mode=DMA_NORMAL
|
|
||||||
Dma.SPI1_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.SPI1_RX.0.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.SPI1_RX.0.Priority=DMA_PRIORITY_VERY_HIGH
|
|
||||||
Dma.SPI1_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
Dma.SPI1_TX.1.Direction=DMA_MEMORY_TO_PERIPH
|
|
||||||
Dma.SPI1_TX.1.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.SPI1_TX.1.Instance=DMA2_Stream3
|
|
||||||
Dma.SPI1_TX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.SPI1_TX.1.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.SPI1_TX.1.Mode=DMA_NORMAL
|
|
||||||
Dma.SPI1_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.SPI1_TX.1.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.SPI1_TX.1.Priority=DMA_PRIORITY_HIGH
|
|
||||||
Dma.SPI1_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
Dma.USART1_RX.8.Direction=DMA_PERIPH_TO_MEMORY
|
|
||||||
Dma.USART1_RX.8.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.USART1_RX.8.Instance=DMA2_Stream5
|
|
||||||
Dma.USART1_RX.8.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.USART1_RX.8.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.USART1_RX.8.Mode=DMA_NORMAL
|
|
||||||
Dma.USART1_RX.8.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.USART1_RX.8.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.USART1_RX.8.Priority=DMA_PRIORITY_MEDIUM
|
|
||||||
Dma.USART1_RX.8.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
Dma.USART1_TX.6.Direction=DMA_MEMORY_TO_PERIPH
|
|
||||||
Dma.USART1_TX.6.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.USART1_TX.6.Instance=DMA2_Stream7
|
|
||||||
Dma.USART1_TX.6.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.USART1_TX.6.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.USART1_TX.6.Mode=DMA_NORMAL
|
|
||||||
Dma.USART1_TX.6.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.USART1_TX.6.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.USART1_TX.6.Priority=DMA_PRIORITY_MEDIUM
|
|
||||||
Dma.USART1_TX.6.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
Dma.USART3_RX.3.Direction=DMA_PERIPH_TO_MEMORY
|
|
||||||
Dma.USART3_RX.3.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.USART3_RX.3.Instance=DMA1_Stream1
|
|
||||||
Dma.USART3_RX.3.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.USART3_RX.3.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.USART3_RX.3.Mode=DMA_NORMAL
|
|
||||||
Dma.USART3_RX.3.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.USART3_RX.3.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.USART3_RX.3.Priority=DMA_PRIORITY_HIGH
|
|
||||||
Dma.USART3_RX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
Dma.USART6_RX.4.Direction=DMA_PERIPH_TO_MEMORY
|
|
||||||
Dma.USART6_RX.4.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.USART6_RX.4.Instance=DMA2_Stream1
|
|
||||||
Dma.USART6_RX.4.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.USART6_RX.4.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.USART6_RX.4.Mode=DMA_NORMAL
|
|
||||||
Dma.USART6_RX.4.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.USART6_RX.4.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.USART6_RX.4.Priority=DMA_PRIORITY_MEDIUM
|
|
||||||
Dma.USART6_RX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
Dma.USART6_TX.5.Direction=DMA_MEMORY_TO_PERIPH
|
|
||||||
Dma.USART6_TX.5.FIFOMode=DMA_FIFOMODE_DISABLE
|
|
||||||
Dma.USART6_TX.5.Instance=DMA2_Stream6
|
|
||||||
Dma.USART6_TX.5.MemDataAlignment=DMA_MDATAALIGN_BYTE
|
|
||||||
Dma.USART6_TX.5.MemInc=DMA_MINC_ENABLE
|
|
||||||
Dma.USART6_TX.5.Mode=DMA_NORMAL
|
|
||||||
Dma.USART6_TX.5.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
|
|
||||||
Dma.USART6_TX.5.PeriphInc=DMA_PINC_DISABLE
|
|
||||||
Dma.USART6_TX.5.Priority=DMA_PRIORITY_MEDIUM
|
|
||||||
Dma.USART6_TX.5.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
|
||||||
FREERTOS.FootprintOK=true
|
|
||||||
FREERTOS.INCLUDE_pcTaskGetTaskName=1
|
|
||||||
FREERTOS.INCLUDE_uxTaskGetStackHighWaterMark2=1
|
|
||||||
FREERTOS.INCLUDE_vTaskCleanUpResources=1
|
|
||||||
FREERTOS.INCLUDE_xEventGroupSetBitFromISR=1
|
|
||||||
FREERTOS.INCLUDE_xSemaphoreGetMutexHolder=1
|
|
||||||
FREERTOS.INCLUDE_xTaskAbortDelay=1
|
|
||||||
FREERTOS.INCLUDE_xTaskGetCurrentTaskHandle=1
|
|
||||||
FREERTOS.INCLUDE_xTaskGetHandle=1
|
|
||||||
FREERTOS.IPParameters=Tasks01,FootprintOK,configENABLE_FPU,configENABLE_BACKWARD_COMPATIBILITY,configRECORD_STACK_HIGH_ADDRESS,configCHECK_FOR_STACK_OVERFLOW,configGENERATE_RUN_TIME_STATS,configUSE_STATS_FORMATTING_FUNCTIONS,configTOTAL_HEAP_SIZE,INCLUDE_xTaskGetCurrentTaskHandle,INCLUDE_xTaskGetHandle,INCLUDE_uxTaskGetStackHighWaterMark2,INCLUDE_xEventGroupSetBitFromISR,INCLUDE_xTaskAbortDelay,INCLUDE_pcTaskGetTaskName,INCLUDE_xSemaphoreGetMutexHolder,INCLUDE_vTaskCleanUpResources,configUSE_APPLICATION_TASK_TAG
|
|
||||||
FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
|
||||||
FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2
|
|
||||||
FREERTOS.configENABLE_BACKWARD_COMPATIBILITY=0
|
|
||||||
FREERTOS.configENABLE_FPU=1
|
|
||||||
FREERTOS.configGENERATE_RUN_TIME_STATS=1
|
|
||||||
FREERTOS.configRECORD_STACK_HIGH_ADDRESS=1
|
|
||||||
FREERTOS.configTOTAL_HEAP_SIZE=0x10000
|
|
||||||
FREERTOS.configUSE_APPLICATION_TASK_TAG=0
|
|
||||||
FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=1
|
|
||||||
File.Version=6
|
|
||||||
GPIO.groupedBy=Group By Peripherals
|
|
||||||
I2C1.I2C_Mode=I2C_Fast
|
|
||||||
I2C1.IPParameters=I2C_Mode
|
|
||||||
I2C2.I2C_Mode=I2C_Fast
|
|
||||||
I2C2.IPParameters=I2C_Mode
|
|
||||||
I2C3.I2C_Mode=I2C_Fast
|
|
||||||
I2C3.IPParameters=I2C_Mode
|
|
||||||
KeepUserPlacement=false
|
|
||||||
Mcu.CPN=STM32F407IGH6
|
|
||||||
Mcu.Family=STM32F4
|
|
||||||
Mcu.IP0=ADC1
|
|
||||||
Mcu.IP1=ADC3
|
|
||||||
Mcu.IP10=NVIC
|
|
||||||
Mcu.IP11=RCC
|
|
||||||
Mcu.IP12=RNG
|
|
||||||
Mcu.IP13=SPI1
|
|
||||||
Mcu.IP14=SPI2
|
|
||||||
Mcu.IP15=SYS
|
|
||||||
Mcu.IP16=TIM1
|
|
||||||
Mcu.IP17=TIM3
|
|
||||||
Mcu.IP18=TIM4
|
|
||||||
Mcu.IP19=TIM5
|
|
||||||
Mcu.IP2=CAN1
|
|
||||||
Mcu.IP20=TIM7
|
|
||||||
Mcu.IP21=TIM8
|
|
||||||
Mcu.IP22=TIM10
|
|
||||||
Mcu.IP23=USART1
|
|
||||||
Mcu.IP24=USART3
|
|
||||||
Mcu.IP25=USART6
|
|
||||||
Mcu.IP26=USB_DEVICE
|
|
||||||
Mcu.IP27=USB_OTG_FS
|
|
||||||
Mcu.IP3=CAN2
|
|
||||||
Mcu.IP4=CRC
|
|
||||||
Mcu.IP5=DMA
|
|
||||||
Mcu.IP6=FREERTOS
|
|
||||||
Mcu.IP7=I2C1
|
|
||||||
Mcu.IP8=I2C2
|
|
||||||
Mcu.IP9=I2C3
|
|
||||||
Mcu.IPNb=28
|
|
||||||
Mcu.Name=STM32F407I(E-G)Hx
|
|
||||||
Mcu.Package=UFBGA176
|
|
||||||
Mcu.Pin0=PB8
|
|
||||||
Mcu.Pin1=PB5
|
|
||||||
Mcu.Pin10=PD0
|
|
||||||
Mcu.Pin11=PC11
|
|
||||||
Mcu.Pin12=PC10
|
|
||||||
Mcu.Pin13=PA12
|
|
||||||
Mcu.Pin14=PI6
|
|
||||||
Mcu.Pin15=PG9
|
|
||||||
Mcu.Pin16=PD1
|
|
||||||
Mcu.Pin17=PA11
|
|
||||||
Mcu.Pin18=PF0
|
|
||||||
Mcu.Pin19=PA9
|
|
||||||
Mcu.Pin2=PG14
|
|
||||||
Mcu.Pin20=PC9
|
|
||||||
Mcu.Pin21=PA8
|
|
||||||
Mcu.Pin22=PH0-OSC_IN
|
|
||||||
Mcu.Pin23=PC8
|
|
||||||
Mcu.Pin24=PH1-OSC_OUT
|
|
||||||
Mcu.Pin25=PF1
|
|
||||||
Mcu.Pin26=PC6
|
|
||||||
Mcu.Pin27=PG6
|
|
||||||
Mcu.Pin28=PF6
|
|
||||||
Mcu.Pin29=PH12
|
|
||||||
Mcu.Pin3=PB4
|
|
||||||
Mcu.Pin30=PG3
|
|
||||||
Mcu.Pin31=PF10
|
|
||||||
Mcu.Pin32=PH11
|
|
||||||
Mcu.Pin33=PH10
|
|
||||||
Mcu.Pin34=PC0
|
|
||||||
Mcu.Pin35=PC1
|
|
||||||
Mcu.Pin36=PC2
|
|
||||||
Mcu.Pin37=PD14
|
|
||||||
Mcu.Pin38=PA0-WKUP
|
|
||||||
Mcu.Pin39=PA4
|
|
||||||
Mcu.Pin4=PB3
|
|
||||||
Mcu.Pin40=PC4
|
|
||||||
Mcu.Pin41=PE13
|
|
||||||
Mcu.Pin42=PC5
|
|
||||||
Mcu.Pin43=PE9
|
|
||||||
Mcu.Pin44=PE11
|
|
||||||
Mcu.Pin45=PE14
|
|
||||||
Mcu.Pin46=PB12
|
|
||||||
Mcu.Pin47=PB13
|
|
||||||
Mcu.Pin48=PA7
|
|
||||||
Mcu.Pin49=PB0
|
|
||||||
Mcu.Pin5=PA14
|
|
||||||
Mcu.Pin50=PB14
|
|
||||||
Mcu.Pin51=PB15
|
|
||||||
Mcu.Pin52=VP_ADC1_TempSens_Input
|
|
||||||
Mcu.Pin53=VP_ADC1_Vref_Input
|
|
||||||
Mcu.Pin54=VP_CRC_VS_CRC
|
|
||||||
Mcu.Pin55=VP_FREERTOS_VS_CMSIS_V2
|
|
||||||
Mcu.Pin56=VP_RNG_VS_RNG
|
|
||||||
Mcu.Pin57=VP_SYS_VS_Systick
|
|
||||||
Mcu.Pin58=VP_TIM1_VS_ClockSourceINT
|
|
||||||
Mcu.Pin59=VP_TIM3_VS_ClockSourceINT
|
|
||||||
Mcu.Pin6=PA13
|
|
||||||
Mcu.Pin60=VP_TIM4_VS_ClockSourceINT
|
|
||||||
Mcu.Pin61=VP_TIM5_VS_ClockSourceINT
|
|
||||||
Mcu.Pin62=VP_TIM7_VS_ClockSourceINT
|
|
||||||
Mcu.Pin63=VP_TIM8_VS_ClockSourceINT
|
|
||||||
Mcu.Pin64=VP_TIM10_VS_ClockSourceINT
|
|
||||||
Mcu.Pin65=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
|
|
||||||
Mcu.Pin7=PB9
|
|
||||||
Mcu.Pin8=PB7
|
|
||||||
Mcu.Pin9=PB6
|
|
||||||
Mcu.PinsNb=66
|
|
||||||
Mcu.ThirdPartyNb=0
|
|
||||||
Mcu.UserConstants=
|
|
||||||
Mcu.UserName=STM32F407IGHx
|
|
||||||
MxCube.Version=6.15.0
|
|
||||||
MxDb.Version=DB.6.0.150
|
|
||||||
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.CAN1_RX0_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.CAN1_RX1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.CAN1_TX_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.CAN2_RX0_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.CAN2_RX1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.CAN2_TX_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.DMA1_Stream1_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA1_Stream2_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA1_Stream7_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA2_Stream1_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA2_Stream2_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA2_Stream3_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA2_Stream5_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA2_Stream6_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DMA2_Stream7_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.EXTI0_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.EXTI3_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.EXTI4_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.EXTI9_5_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.ForceEnableDMAVector=true
|
|
||||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
|
||||||
NVIC.OTG_FS_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
|
|
||||||
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
|
|
||||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
|
||||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
|
|
||||||
NVIC.SavedPendsvIrqHandlerGenerated=true
|
|
||||||
NVIC.SavedSvcallIrqHandlerGenerated=true
|
|
||||||
NVIC.SavedSystickIrqHandlerGenerated=true
|
|
||||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:true\:false\:true\:false
|
|
||||||
NVIC.TIM1_BRK_TIM9_IRQn=true\:5\:0\:false\:false\:true\:false\:false\:true\:true
|
|
||||||
NVIC.TIM7_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.USART1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.USART6_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
|
||||||
NVIC.UsageFault_IRQn=true\:0\:0\:true\:false\:true\:false\:false\:false\:false
|
|
||||||
PA0-WKUP.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
|
|
||||||
PA0-WKUP.GPIO_Label=USER_KEY
|
|
||||||
PA0-WKUP.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING
|
|
||||||
PA0-WKUP.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PA0-WKUP.Locked=true
|
|
||||||
PA0-WKUP.Signal=GPXTI0
|
|
||||||
PA11.Mode=Device_Only
|
|
||||||
PA11.Signal=USB_OTG_FS_DM
|
|
||||||
PA12.Mode=Device_Only
|
|
||||||
PA12.Signal=USB_OTG_FS_DP
|
|
||||||
PA13.Mode=Serial_Wire
|
|
||||||
PA13.Signal=SYS_JTMS-SWDIO
|
|
||||||
PA14.Mode=Serial_Wire
|
|
||||||
PA14.Signal=SYS_JTCK-SWCLK
|
|
||||||
PA4.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
|
||||||
PA4.GPIO_Label=ACCL_CS
|
|
||||||
PA4.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PA4.GPIO_Speed=GPIO_SPEED_FREQ_MEDIUM
|
|
||||||
PA4.Locked=true
|
|
||||||
PA4.PinState=GPIO_PIN_SET
|
|
||||||
PA4.Signal=GPIO_Output
|
|
||||||
PA7.GPIOParameters=GPIO_PuPd
|
|
||||||
PA7.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PA7.Locked=true
|
|
||||||
PA7.Mode=Full_Duplex_Master
|
|
||||||
PA7.Signal=SPI1_MOSI
|
|
||||||
PA8.GPIOParameters=GPIO_Pu
|
|
||||||
PA8.GPIO_Pu=GPIO_PULLUP
|
|
||||||
PA8.Locked=true
|
|
||||||
PA8.Mode=I2C
|
|
||||||
PA8.Signal=I2C3_SCL
|
|
||||||
PA9.Locked=true
|
|
||||||
PA9.Mode=Asynchronous
|
|
||||||
PA9.Signal=USART1_TX
|
|
||||||
PB0.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
|
||||||
PB0.GPIO_Label=GYRO_CS
|
|
||||||
PB0.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PB0.GPIO_Speed=GPIO_SPEED_FREQ_MEDIUM
|
|
||||||
PB0.Locked=true
|
|
||||||
PB0.PinState=GPIO_PIN_SET
|
|
||||||
PB0.Signal=GPIO_Output
|
|
||||||
PB12.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
|
||||||
PB12.GPIO_Label=SPI2_CS
|
|
||||||
PB12.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PB12.GPIO_Speed=GPIO_SPEED_FREQ_MEDIUM
|
|
||||||
PB12.Locked=true
|
|
||||||
PB12.PinState=GPIO_PIN_SET
|
|
||||||
PB12.Signal=GPIO_Output
|
|
||||||
PB13.GPIOParameters=GPIO_PuPd
|
|
||||||
PB13.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PB13.Locked=true
|
|
||||||
PB13.Mode=Full_Duplex_Master
|
|
||||||
PB13.Signal=SPI2_SCK
|
|
||||||
PB14.GPIOParameters=GPIO_PuPd
|
|
||||||
PB14.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PB14.Locked=true
|
|
||||||
PB14.Mode=Full_Duplex_Master
|
|
||||||
PB14.Signal=SPI2_MISO
|
|
||||||
PB15.GPIOParameters=GPIO_PuPd
|
|
||||||
PB15.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PB15.Locked=true
|
|
||||||
PB15.Mode=Full_Duplex_Master
|
|
||||||
PB15.Signal=SPI2_MOSI
|
|
||||||
PB3.GPIOParameters=GPIO_PuPd
|
|
||||||
PB3.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PB3.Locked=true
|
|
||||||
PB3.Mode=Full_Duplex_Master
|
|
||||||
PB3.Signal=SPI1_SCK
|
|
||||||
PB4.GPIOParameters=GPIO_PuPd
|
|
||||||
PB4.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PB4.Locked=true
|
|
||||||
PB4.Mode=Full_Duplex_Master
|
|
||||||
PB4.Signal=SPI1_MISO
|
|
||||||
PB5.Locked=true
|
|
||||||
PB5.Mode=CAN_Activate
|
|
||||||
PB5.Signal=CAN2_RX
|
|
||||||
PB6.Locked=true
|
|
||||||
PB6.Mode=CAN_Activate
|
|
||||||
PB6.Signal=CAN2_TX
|
|
||||||
PB7.Locked=true
|
|
||||||
PB7.Mode=Asynchronous
|
|
||||||
PB7.Signal=USART1_RX
|
|
||||||
PB8.GPIOParameters=GPIO_Pu
|
|
||||||
PB8.GPIO_Pu=GPIO_PULLUP
|
|
||||||
PB8.Locked=true
|
|
||||||
PB8.Mode=I2C
|
|
||||||
PB8.Signal=I2C1_SCL
|
|
||||||
PB9.GPIOParameters=GPIO_Pu
|
|
||||||
PB9.GPIO_Pu=GPIO_PULLUP
|
|
||||||
PB9.Locked=true
|
|
||||||
PB9.Mode=I2C
|
|
||||||
PB9.Signal=I2C1_SDA
|
|
||||||
PC0.GPIOParameters=GPIO_Label
|
|
||||||
PC0.GPIO_Label=HW0
|
|
||||||
PC0.Locked=true
|
|
||||||
PC0.Signal=GPIO_Input
|
|
||||||
PC1.GPIOParameters=GPIO_Label
|
|
||||||
PC1.GPIO_Label=HW1
|
|
||||||
PC1.Locked=true
|
|
||||||
PC1.Signal=GPIO_Input
|
|
||||||
PC10.Locked=true
|
|
||||||
PC10.Mode=Asynchronous
|
|
||||||
PC10.Signal=USART3_TX
|
|
||||||
PC11.Locked=true
|
|
||||||
PC11.Mode=Asynchronous
|
|
||||||
PC11.Signal=USART3_RX
|
|
||||||
PC2.GPIOParameters=GPIO_Label
|
|
||||||
PC2.GPIO_Label=HW2
|
|
||||||
PC2.Locked=true
|
|
||||||
PC2.Signal=GPIO_Input
|
|
||||||
PC4.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
|
|
||||||
PC4.GPIO_Label=ACCL_INT
|
|
||||||
PC4.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING
|
|
||||||
PC4.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PC4.Locked=true
|
|
||||||
PC4.Signal=GPXTI4
|
|
||||||
PC5.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
|
|
||||||
PC5.GPIO_Label=GYRO_INT
|
|
||||||
PC5.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING
|
|
||||||
PC5.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PC5.Locked=true
|
|
||||||
PC5.Signal=GPXTI5
|
|
||||||
PC6.GPIOParameters=GPIO_Speed,GPIO_PuPd
|
|
||||||
PC6.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PC6.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PC6.Locked=true
|
|
||||||
PC6.Signal=S_TIM8_CH1
|
|
||||||
PC8.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
|
||||||
PC8.GPIO_Label=LASER
|
|
||||||
PC8.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PC8.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PC8.Locked=true
|
|
||||||
PC8.Signal=S_TIM3_CH3
|
|
||||||
PC9.GPIOParameters=GPIO_Pu
|
|
||||||
PC9.GPIO_Pu=GPIO_PULLUP
|
|
||||||
PC9.Locked=true
|
|
||||||
PC9.Mode=I2C
|
|
||||||
PC9.Signal=I2C3_SDA
|
|
||||||
PD0.Locked=true
|
|
||||||
PD0.Mode=CAN_Activate
|
|
||||||
PD0.Signal=CAN1_RX
|
|
||||||
PD1.Locked=true
|
|
||||||
PD1.Mode=CAN_Activate
|
|
||||||
PD1.Signal=CAN1_TX
|
|
||||||
PD14.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
|
||||||
PD14.GPIO_Label=BUZZER
|
|
||||||
PD14.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PD14.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
|
||||||
PD14.Locked=true
|
|
||||||
PD14.Signal=S_TIM4_CH3
|
|
||||||
PE11.GPIOParameters=GPIO_Speed,GPIO_PuPd
|
|
||||||
PE11.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PE11.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PE11.Locked=true
|
|
||||||
PE11.Signal=S_TIM1_CH2
|
|
||||||
PE13.GPIOParameters=GPIO_Speed,GPIO_PuPd
|
|
||||||
PE13.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PE13.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PE13.Locked=true
|
|
||||||
PE13.Signal=S_TIM1_CH3
|
|
||||||
PE14.GPIOParameters=GPIO_Speed,GPIO_PuPd
|
|
||||||
PE14.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PE14.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PE14.Locked=true
|
|
||||||
PE14.Signal=S_TIM1_CH4
|
|
||||||
PE9.GPIOParameters=GPIO_Speed,GPIO_PuPd
|
|
||||||
PE9.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PE9.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PE9.Locked=true
|
|
||||||
PE9.Signal=S_TIM1_CH1
|
|
||||||
PF0.GPIOParameters=GPIO_Pu
|
|
||||||
PF0.GPIO_Pu=GPIO_PULLUP
|
|
||||||
PF0.Locked=true
|
|
||||||
PF0.Mode=I2C
|
|
||||||
PF0.Signal=I2C2_SDA
|
|
||||||
PF1.GPIOParameters=GPIO_Pu
|
|
||||||
PF1.GPIO_Pu=GPIO_PULLUP
|
|
||||||
PF1.Locked=true
|
|
||||||
PF1.Mode=I2C
|
|
||||||
PF1.Signal=I2C2_SCL
|
|
||||||
PF10.GPIOParameters=GPIO_Label
|
|
||||||
PF10.GPIO_Label=ADC_BAT
|
|
||||||
PF10.Locked=true
|
|
||||||
PF10.Mode=IN8
|
|
||||||
PF10.Signal=ADC3_IN8
|
|
||||||
PF6.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
|
||||||
PF6.GPIO_Label=IMU_HEAT_PWM
|
|
||||||
PF6.GPIO_PuPd=GPIO_PULLDOWN
|
|
||||||
PF6.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PF6.Locked=true
|
|
||||||
PF6.Signal=S_TIM10_CH1
|
|
||||||
PG14.Locked=true
|
|
||||||
PG14.Mode=Asynchronous
|
|
||||||
PG14.Signal=USART6_TX
|
|
||||||
PG3.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
|
|
||||||
PG3.GPIO_Label=CMPS_INT
|
|
||||||
PG3.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING
|
|
||||||
PG3.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PG3.Locked=true
|
|
||||||
PG3.Signal=GPXTI3
|
|
||||||
PG6.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
|
||||||
PG6.GPIO_Label=CMPS_RST
|
|
||||||
PG6.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PG6.GPIO_Speed=GPIO_SPEED_FREQ_MEDIUM
|
|
||||||
PG6.Locked=true
|
|
||||||
PG6.PinState=GPIO_PIN_RESET
|
|
||||||
PG6.Signal=GPIO_Output
|
|
||||||
PG9.Locked=true
|
|
||||||
PG9.Mode=Asynchronous
|
|
||||||
PG9.Signal=USART6_RX
|
|
||||||
PH0-OSC_IN.Mode=HSE-External-Oscillator
|
|
||||||
PH0-OSC_IN.Signal=RCC_OSC_IN
|
|
||||||
PH1-OSC_OUT.Mode=HSE-External-Oscillator
|
|
||||||
PH1-OSC_OUT.Signal=RCC_OSC_OUT
|
|
||||||
PH10.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
|
||||||
PH10.GPIO_Label=LED_B
|
|
||||||
PH10.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PH10.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PH10.Locked=true
|
|
||||||
PH10.Signal=S_TIM5_CH1
|
|
||||||
PH11.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
|
||||||
PH11.GPIO_Label=LED_G
|
|
||||||
PH11.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PH11.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PH11.Locked=true
|
|
||||||
PH11.Signal=S_TIM5_CH2
|
|
||||||
PH12.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
|
||||||
PH12.GPIO_Label=LED_R
|
|
||||||
PH12.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PH12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PH12.Locked=true
|
|
||||||
PH12.Signal=S_TIM5_CH3
|
|
||||||
PI6.GPIOParameters=GPIO_Speed,GPIO_PuPd
|
|
||||||
PI6.GPIO_PuPd=GPIO_PULLUP
|
|
||||||
PI6.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
|
||||||
PI6.Signal=S_TIM8_CH2
|
|
||||||
PinOutPanel.CurrentBGAView=Top
|
|
||||||
PinOutPanel.RotationAngle=0
|
|
||||||
ProjectManager.AskForMigrate=true
|
|
||||||
ProjectManager.BackupPrevious=false
|
|
||||||
ProjectManager.CompilerLinker=GCC
|
|
||||||
ProjectManager.CompilerOptimize=6
|
|
||||||
ProjectManager.ComputerToolchain=false
|
|
||||||
ProjectManager.CoupleFile=true
|
|
||||||
ProjectManager.CustomerFirmwarePackage=
|
|
||||||
ProjectManager.DefaultFWLocation=true
|
|
||||||
ProjectManager.DeletePrevious=true
|
|
||||||
ProjectManager.DeviceId=STM32F407IGHx
|
|
||||||
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.28.3
|
|
||||||
ProjectManager.FreePins=false
|
|
||||||
ProjectManager.HalAssertFull=true
|
|
||||||
ProjectManager.HeapSize=0x1000
|
|
||||||
ProjectManager.KeepUserCode=true
|
|
||||||
ProjectManager.LastFirmware=true
|
|
||||||
ProjectManager.LibraryCopy=0
|
|
||||||
ProjectManager.MainLocation=Core/Src
|
|
||||||
ProjectManager.NoMain=false
|
|
||||||
ProjectManager.PreviousToolchain=
|
|
||||||
ProjectManager.ProjectBuild=false
|
|
||||||
ProjectManager.ProjectFileName=DevC.ioc
|
|
||||||
ProjectManager.ProjectName=DevC
|
|
||||||
ProjectManager.ProjectStructure=
|
|
||||||
ProjectManager.RegisterCallBack=
|
|
||||||
ProjectManager.StackSize=0x1000
|
|
||||||
ProjectManager.TargetToolchain=CMake
|
|
||||||
ProjectManager.ToolChainLocation=
|
|
||||||
ProjectManager.UAScriptAfterPath=
|
|
||||||
ProjectManager.UAScriptBeforePath=
|
|
||||||
ProjectManager.UnderRoot=false
|
|
||||||
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-MX_DMA_Init-DMA-false-HAL-true,3-SystemClock_Config-RCC-false-HAL-false,4-MX_ADC1_Init-ADC1-false-HAL-true,5-MX_ADC3_Init-ADC3-false-HAL-true,6-MX_CAN1_Init-CAN1-false-HAL-true,7-MX_CAN2_Init-CAN2-false-HAL-true,8-MX_I2C1_Init-I2C1-false-HAL-true,9-MX_SPI1_Init-SPI1-false-HAL-true,10-MX_TIM4_Init-TIM4-false-HAL-true,11-MX_TIM5_Init-TIM5-false-HAL-true,12-MX_USART3_UART_Init-USART3-false-HAL-true,13-MX_TIM8_Init-TIM8-false-HAL-true,14-MX_CRC_Init-CRC-false-HAL-true,15-MX_RNG_Init-RNG-false-HAL-true,16-MX_I2C2_Init-I2C2-false-HAL-true,17-MX_I2C3_Init-I2C3-false-HAL-true,18-MX_SPI2_Init-SPI2-false-HAL-true,19-MX_TIM1_Init-TIM1-false-HAL-true,20-MX_TIM3_Init-TIM3-false-HAL-true,21-MX_TIM10_Init-TIM10-false-HAL-true,22-MX_USART1_UART_Init-USART1-false-HAL-true,23-MX_USART6_UART_Init-USART6-false-HAL-true,24-MX_TIM7_Init-TIM7-false-HAL-true,25-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false
|
|
||||||
RCC.48MHZClocksFreq_Value=48000000
|
|
||||||
RCC.AHBFreq_Value=168000000
|
|
||||||
RCC.APB1CLKDivider=RCC_HCLK_DIV4
|
|
||||||
RCC.APB1Freq_Value=42000000
|
|
||||||
RCC.APB1TimFreq_Value=84000000
|
|
||||||
RCC.APB2CLKDivider=RCC_HCLK_DIV2
|
|
||||||
RCC.APB2Freq_Value=84000000
|
|
||||||
RCC.APB2TimFreq_Value=168000000
|
|
||||||
RCC.CortexFreq_Value=168000000
|
|
||||||
RCC.EthernetFreq_Value=168000000
|
|
||||||
RCC.FCLKCortexFreq_Value=168000000
|
|
||||||
RCC.FamilyName=M
|
|
||||||
RCC.HCLKFreq_Value=168000000
|
|
||||||
RCC.HSE_VALUE=12000000
|
|
||||||
RCC.HSI_VALUE=16000000
|
|
||||||
RCC.I2SClocksFreq_Value=192000000
|
|
||||||
RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2SClocksFreq_Value,LSE_VALUE,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLM,PLLN,PLLQ,PLLQCLKFreq_Value,RCC_RTC_Clock_Source,RCC_RTC_Clock_SourceVirtual,RCC_RTC_Clock_Source_FROM_HSE,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VcooutputI2S
|
|
||||||
RCC.LSE_VALUE=32768
|
|
||||||
RCC.LSI_VALUE=32000
|
|
||||||
RCC.MCO2PinFreq_Value=168000000
|
|
||||||
RCC.PLLCLKFreq_Value=168000000
|
|
||||||
RCC.PLLM=6
|
|
||||||
RCC.PLLN=168
|
|
||||||
RCC.PLLQ=7
|
|
||||||
RCC.PLLQCLKFreq_Value=48000000
|
|
||||||
RCC.RCC_RTC_Clock_Source=RCC_RTCCLKSOURCE_LSI
|
|
||||||
RCC.RCC_RTC_Clock_SourceVirtual=RCC_RTCCLKSOURCE_HSE_DIV30
|
|
||||||
RCC.RCC_RTC_Clock_Source_FROM_HSE=RCC_RTCCLKSOURCE_HSE_DIV30
|
|
||||||
RCC.RTCFreq_Value=32000
|
|
||||||
RCC.RTCHSEDivFreq_Value=400000
|
|
||||||
RCC.SYSCLKFreq_VALUE=168000000
|
|
||||||
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
|
||||||
RCC.VCOI2SOutputFreq_Value=384000000
|
|
||||||
RCC.VCOInputFreq_Value=2000000
|
|
||||||
RCC.VCOOutputFreq_Value=336000000
|
|
||||||
RCC.VcooutputI2S=192000000
|
|
||||||
SH.GPXTI0.0=GPIO_EXTI0
|
|
||||||
SH.GPXTI0.ConfNb=1
|
|
||||||
SH.GPXTI3.0=GPIO_EXTI3
|
|
||||||
SH.GPXTI3.ConfNb=1
|
|
||||||
SH.GPXTI4.0=GPIO_EXTI4
|
|
||||||
SH.GPXTI4.ConfNb=1
|
|
||||||
SH.GPXTI5.0=GPIO_EXTI5
|
|
||||||
SH.GPXTI5.ConfNb=1
|
|
||||||
SH.S_TIM10_CH1.0=TIM10_CH1,PWM Generation1 CH1
|
|
||||||
SH.S_TIM10_CH1.ConfNb=1
|
|
||||||
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
|
|
||||||
SH.S_TIM1_CH1.ConfNb=1
|
|
||||||
SH.S_TIM1_CH2.0=TIM1_CH2,PWM Generation2 CH2
|
|
||||||
SH.S_TIM1_CH2.ConfNb=1
|
|
||||||
SH.S_TIM1_CH3.0=TIM1_CH3,PWM Generation3 CH3
|
|
||||||
SH.S_TIM1_CH3.ConfNb=1
|
|
||||||
SH.S_TIM1_CH4.0=TIM1_CH4,PWM Generation4 CH4
|
|
||||||
SH.S_TIM1_CH4.ConfNb=1
|
|
||||||
SH.S_TIM3_CH3.0=TIM3_CH3,PWM Generation3 CH3
|
|
||||||
SH.S_TIM3_CH3.ConfNb=1
|
|
||||||
SH.S_TIM4_CH3.0=TIM4_CH3,PWM Generation3 CH3
|
|
||||||
SH.S_TIM4_CH3.ConfNb=1
|
|
||||||
SH.S_TIM5_CH1.0=TIM5_CH1,PWM Generation1 CH1
|
|
||||||
SH.S_TIM5_CH1.ConfNb=1
|
|
||||||
SH.S_TIM5_CH2.0=TIM5_CH2,PWM Generation2 CH2
|
|
||||||
SH.S_TIM5_CH2.ConfNb=1
|
|
||||||
SH.S_TIM5_CH3.0=TIM5_CH3,PWM Generation3 CH3
|
|
||||||
SH.S_TIM5_CH3.ConfNb=1
|
|
||||||
SH.S_TIM8_CH1.0=TIM8_CH1,PWM Generation1 CH1
|
|
||||||
SH.S_TIM8_CH1.ConfNb=1
|
|
||||||
SH.S_TIM8_CH2.0=TIM8_CH2,PWM Generation2 CH2
|
|
||||||
SH.S_TIM8_CH2.ConfNb=1
|
|
||||||
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16
|
|
||||||
SPI1.CLKPhase=SPI_PHASE_2EDGE
|
|
||||||
SPI1.CLKPolarity=SPI_POLARITY_HIGH
|
|
||||||
SPI1.CalculateBaudRate=5.25 MBits/s
|
|
||||||
SPI1.Direction=SPI_DIRECTION_2LINES
|
|
||||||
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler,CLKPolarity,CLKPhase
|
|
||||||
SPI1.Mode=SPI_MODE_MASTER
|
|
||||||
SPI1.VirtualType=VM_MASTER
|
|
||||||
SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_64
|
|
||||||
SPI2.CLKPhase=SPI_PHASE_1EDGE
|
|
||||||
SPI2.CLKPolarity=SPI_POLARITY_LOW
|
|
||||||
SPI2.CalculateBaudRate=656.25 KBits/s
|
|
||||||
SPI2.Direction=SPI_DIRECTION_2LINES
|
|
||||||
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler,CLKPolarity,CLKPhase
|
|
||||||
SPI2.Mode=SPI_MODE_MASTER
|
|
||||||
SPI2.VirtualType=VM_MASTER
|
|
||||||
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
|
||||||
TIM1.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
|
||||||
TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
|
||||||
TIM1.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4
|
|
||||||
TIM1.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4,Period,Prescaler,Pulse-PWM Generation1 CH1,Pulse-PWM Generation2 CH2,Pulse-PWM Generation3 CH3,Pulse-PWM Generation4 CH4
|
|
||||||
TIM1.Period=19999
|
|
||||||
TIM1.Prescaler=167
|
|
||||||
TIM1.Pulse-PWM\ Generation1\ CH1=0
|
|
||||||
TIM1.Pulse-PWM\ Generation2\ CH2=0
|
|
||||||
TIM1.Pulse-PWM\ Generation3\ CH3=0
|
|
||||||
TIM1.Pulse-PWM\ Generation4\ CH4=1000
|
|
||||||
TIM10.Channel=TIM_CHANNEL_1
|
|
||||||
TIM10.IPParameters=Channel,Period
|
|
||||||
TIM10.Period=4999
|
|
||||||
TIM3.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
|
||||||
TIM3.IPParameters=Channel-PWM Generation3 CH3,Period
|
|
||||||
TIM3.Period=65535
|
|
||||||
TIM4.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
|
||||||
TIM4.IPParameters=Channel-PWM Generation3 CH3,Prescaler,Period
|
|
||||||
TIM4.Period=65535
|
|
||||||
TIM4.Prescaler=167
|
|
||||||
TIM5.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
|
||||||
TIM5.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
|
||||||
TIM5.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
|
||||||
TIM5.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Prescaler,Period
|
|
||||||
TIM5.Period=65535
|
|
||||||
TIM5.Prescaler=0
|
|
||||||
TIM7.IPParameters=Period,Prescaler
|
|
||||||
TIM7.Period=9
|
|
||||||
TIM7.Prescaler=83
|
|
||||||
TIM8.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
|
||||||
TIM8.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
|
||||||
TIM8.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Prescaler,Period,Pulse-PWM Generation1 CH1,Pulse-PWM Generation2 CH2
|
|
||||||
TIM8.Period=19999
|
|
||||||
TIM8.Prescaler=167
|
|
||||||
TIM8.Pulse-PWM\ Generation1\ CH1=1000
|
|
||||||
TIM8.Pulse-PWM\ Generation2\ CH2=1000
|
|
||||||
USART1.IPParameters=VirtualMode
|
|
||||||
USART1.VirtualMode=VM_ASYNC
|
|
||||||
USART3.BaudRate=100000
|
|
||||||
USART3.IPParameters=VirtualMode,BaudRate,Parity,Mode
|
|
||||||
USART3.Mode=MODE_RX
|
|
||||||
USART3.Parity=PARITY_EVEN
|
|
||||||
USART3.VirtualMode=VM_ASYNC
|
|
||||||
USART6.IPParameters=VirtualMode
|
|
||||||
USART6.VirtualMode=VM_ASYNC
|
|
||||||
USB_DEVICE.CLASS_NAME_FS=CDC
|
|
||||||
USB_DEVICE.IPParameters=VirtualMode-CDC_FS,VirtualModeFS,CLASS_NAME_FS
|
|
||||||
USB_DEVICE.VirtualMode-CDC_FS=Cdc
|
|
||||||
USB_DEVICE.VirtualModeFS=Cdc_FS
|
|
||||||
USB_OTG_FS.IPParameters=VirtualMode
|
|
||||||
USB_OTG_FS.VirtualMode=Device_Only
|
|
||||||
VP_ADC1_TempSens_Input.Mode=IN-TempSens
|
|
||||||
VP_ADC1_TempSens_Input.Signal=ADC1_TempSens_Input
|
|
||||||
VP_ADC1_Vref_Input.Mode=IN-Vrefint
|
|
||||||
VP_ADC1_Vref_Input.Signal=ADC1_Vref_Input
|
|
||||||
VP_CRC_VS_CRC.Mode=CRC_Activate
|
|
||||||
VP_CRC_VS_CRC.Signal=CRC_VS_CRC
|
|
||||||
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
|
|
||||||
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
|
|
||||||
VP_RNG_VS_RNG.Mode=RNG_Activate
|
|
||||||
VP_RNG_VS_RNG.Signal=RNG_VS_RNG
|
|
||||||
VP_SYS_VS_Systick.Mode=SysTick
|
|
||||||
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
|
|
||||||
VP_TIM10_VS_ClockSourceINT.Mode=Enable_Timer
|
|
||||||
VP_TIM10_VS_ClockSourceINT.Signal=TIM10_VS_ClockSourceINT
|
|
||||||
VP_TIM1_VS_ClockSourceINT.Mode=Internal
|
|
||||||
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
|
||||||
VP_TIM3_VS_ClockSourceINT.Mode=Internal
|
|
||||||
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
|
|
||||||
VP_TIM4_VS_ClockSourceINT.Mode=Internal
|
|
||||||
VP_TIM4_VS_ClockSourceINT.Signal=TIM4_VS_ClockSourceINT
|
|
||||||
VP_TIM5_VS_ClockSourceINT.Mode=Internal
|
|
||||||
VP_TIM5_VS_ClockSourceINT.Signal=TIM5_VS_ClockSourceINT
|
|
||||||
VP_TIM7_VS_ClockSourceINT.Mode=Enable_Timer
|
|
||||||
VP_TIM7_VS_ClockSourceINT.Signal=TIM7_VS_ClockSourceINT
|
|
||||||
VP_TIM8_VS_ClockSourceINT.Mode=Internal
|
|
||||||
VP_TIM8_VS_ClockSourceINT.Signal=TIM8_VS_ClockSourceINT
|
|
||||||
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS
|
|
||||||
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS
|
|
||||||
board=custom
|
|
||||||
rtos.0.ip=FREERTOS
|
|
||||||
@ -197,7 +197,7 @@ int8_t CMD_Arbitrate(CMD_t *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 自动仲裁:优先级 PC > RC > NUC */
|
/* 自动仲裁:优先级 PC > RC > NUC */
|
||||||
CMD_InputSource_t candidates[] = {CMD_SRC_RC, CMD_SRC_PC, CMD_SRC_NUC};
|
CMD_InputSource_t candidates[] = {CMD_SRC_PC, CMD_SRC_RC, CMD_SRC_NUC};
|
||||||
const int num_candidates = sizeof(candidates) / sizeof(candidates[0]);
|
const int num_candidates = sizeof(candidates) / sizeof(candidates[0]);
|
||||||
|
|
||||||
/* 如果当前输入源仍然在线且有效,保持使用 */
|
/* 如果当前输入源仍然在线且有效,保持使用 */
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
// static CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0};
|
// static CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0};
|
||||||
CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0};
|
CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0};
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
/* DR16 适配器实现 */
|
/* DR16 抽象实现 */
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
#if CMD_RC_DEVICE_TYPE == 0
|
#if CMD_RC_DEVICE_TYPE == 0
|
||||||
|
|
||||||
@ -27,19 +27,19 @@ int8_t CMD_DR16_RC_GetInput(void *data, CMD_RawInput_t *output) {
|
|||||||
output->online[CMD_SRC_RC] = dr16->header.online;
|
output->online[CMD_SRC_RC] = dr16->header.online;
|
||||||
|
|
||||||
/* 遥控器摇杆映射 */
|
/* 遥控器摇杆映射 */
|
||||||
output->rc.joy_left.x = dr16->data.ch_l_x;
|
output->rc.joy_left.x = dr16->data.rc.ch_l_x;
|
||||||
output->rc.joy_left.y = dr16->data.ch_l_y;
|
output->rc.joy_left.y = dr16->data.rc.ch_l_y;
|
||||||
output->rc.joy_right.x = dr16->data.ch_r_x;
|
output->rc.joy_right.x = dr16->data.rc.ch_r_x;
|
||||||
output->rc.joy_right.y = dr16->data.ch_r_y;
|
output->rc.joy_right.y = dr16->data.rc.ch_r_y;
|
||||||
|
|
||||||
/* 拨杆映射 */
|
/* 拨杆映射 */
|
||||||
switch (dr16->data.sw_l) {
|
switch (dr16->data.rc.sw_l) {
|
||||||
case DR16_SW_UP: output->rc.sw[0] = CMD_SW_UP; break;
|
case DR16_SW_UP: output->rc.sw[0] = CMD_SW_UP; break;
|
||||||
case DR16_SW_MID: output->rc.sw[0] = CMD_SW_MID; break;
|
case DR16_SW_MID: output->rc.sw[0] = CMD_SW_MID; break;
|
||||||
case DR16_SW_DOWN: output->rc.sw[0] = CMD_SW_DOWN; break;
|
case DR16_SW_DOWN: output->rc.sw[0] = CMD_SW_DOWN; break;
|
||||||
default: output->rc.sw[0] = CMD_SW_ERR; break;
|
default: output->rc.sw[0] = CMD_SW_ERR; break;
|
||||||
}
|
}
|
||||||
switch (dr16->data.sw_r) {
|
switch (dr16->data.rc.sw_r) {
|
||||||
case DR16_SW_UP: output->rc.sw[1] = CMD_SW_UP; break;
|
case DR16_SW_UP: output->rc.sw[1] = CMD_SW_UP; break;
|
||||||
case DR16_SW_MID: output->rc.sw[1] = CMD_SW_MID; break;
|
case DR16_SW_MID: output->rc.sw[1] = CMD_SW_MID; break;
|
||||||
case DR16_SW_DOWN: output->rc.sw[1] = CMD_SW_DOWN; break;
|
case DR16_SW_DOWN: output->rc.sw[1] = CMD_SW_DOWN; break;
|
||||||
@ -47,7 +47,7 @@ int8_t CMD_DR16_RC_GetInput(void *data, CMD_RawInput_t *output) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 拨轮映射 */
|
/* 拨轮映射 */
|
||||||
output->rc.dial = dr16->data.ch_res;
|
output->rc.dial = dr16->data.rc.ch_res;
|
||||||
|
|
||||||
return CMD_OK;
|
return CMD_OK;
|
||||||
}
|
}
|
||||||
@ -60,10 +60,10 @@ int8_t CMD_DR16_PC_GetInput(void *data, CMD_RawInput_t *output) {
|
|||||||
output->online[CMD_SRC_PC] = dr16->header.online;
|
output->online[CMD_SRC_PC] = dr16->header.online;
|
||||||
|
|
||||||
/* PC端鼠标映射 */
|
/* PC端鼠标映射 */
|
||||||
output->pc.mouse.x = dr16->data.mouse.x;
|
output->pc.mouse.x = dr16->data.pc.mouse.x;
|
||||||
output->pc.mouse.y = dr16->data.mouse.y;
|
output->pc.mouse.y = dr16->data.pc.mouse.y;
|
||||||
output->pc.mouse.l_click = dr16->data.mouse.l_click;
|
output->pc.mouse.l_click = dr16->data.pc.mouse.l_click;
|
||||||
output->pc.mouse.r_click = dr16->data.mouse.r_click;
|
output->pc.mouse.r_click = dr16->data.pc.mouse.r_click;
|
||||||
|
|
||||||
/* 键盘映射 */
|
/* 键盘映射 */
|
||||||
output->pc.keyboard.bitmap = dr16->raw_data.key;
|
output->pc.keyboard.bitmap = dr16->raw_data.key;
|
||||||
@ -83,7 +83,7 @@ CMD_DEFINE_ADAPTER(DR16_PC, cmd_dr16, CMD_SRC_PC, CMD_DR16_Init, CMD_DR16_PC_Get
|
|||||||
#endif /* CMD_RC_DEVICE_TYPE == 0 */
|
#endif /* CMD_RC_DEVICE_TYPE == 0 */
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
/* AT9S 适配器实现 (示例框架) */
|
/* AT9S 抽象实现 (示例框架) */
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
#if CMD_RC_DEVICE_TYPE == 1
|
#if CMD_RC_DEVICE_TYPE == 1
|
||||||
|
|
||||||
@ -100,10 +100,10 @@ int8_t CMD_AT9S_GetInput(void *data, CMD_RawInput_t *output) {
|
|||||||
output->online[CMD_SRC_RC] = at9s->header.online;
|
output->online[CMD_SRC_RC] = at9s->header.online;
|
||||||
|
|
||||||
/* TODO: 按照AT9S的数据格式进行映射 */
|
/* TODO: 按照AT9S的数据格式进行映射 */
|
||||||
output->joy_left.x = at9s->data.ch_l_x;
|
output->joy_left.x = at9s->data.rc.ch_l_x;
|
||||||
output->joy_left.y = at9s->data.ch_l_y;
|
output->joy_left.y = at9s->data.rc.ch_l_y;
|
||||||
output->joy_right.x = at9s->data.ch_r_x;
|
output->joy_right.x = at9s->data.rc.ch_r_x;
|
||||||
output->joy_right.y = at9s->data.ch_r_y;
|
output->joy_right.y = at9s->data.rc.ch_r_y;
|
||||||
|
|
||||||
/* 拨杆映射需要根据AT9S的实际定义 */
|
/* 拨杆映射需要根据AT9S的实际定义 */
|
||||||
|
|
||||||
@ -142,6 +142,10 @@ int8_t CMD_Adapter_InitAll(void) {
|
|||||||
CMD_Adapter_Register(&g_adapter_AT9S);
|
CMD_Adapter_Register(&g_adapter_AT9S);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* 注册NUC适配器 */
|
||||||
|
|
||||||
|
/* 注册REF适配器 */
|
||||||
|
|
||||||
/* 初始化所有已注册的适配器 */
|
/* 初始化所有已注册的适配器 */
|
||||||
for (int i = 0; i < CMD_SRC_NUM; i++) {
|
for (int i = 0; i < CMD_SRC_NUM; i++) {
|
||||||
if (g_adapters[i] != NULL && g_adapters[i]->init != NULL) {
|
if (g_adapters[i] != NULL && g_adapters[i]->init != NULL) {
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
/* config示例 */
|
/* 配置示例 */
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
|
||||||
/* 默认配置 */
|
/* 默认配置 */
|
||||||
@ -37,58 +37,35 @@
|
|||||||
// /* CMD上下文 */
|
// /* CMD上下文 */
|
||||||
// static CMD_t g_cmd_ctx;
|
// static CMD_t g_cmd_ctx;
|
||||||
|
|
||||||
/* ========================================================================== */
|
|
||||||
/* 队列创建示例 */
|
|
||||||
/* ========================================================================== */
|
|
||||||
// #if CMD_RCTypeTable_Index == 0
|
|
||||||
// task_runtime.msgq.cmd.rc= osMessageQueueNew(3u, sizeof(DR16_t), NULL);
|
|
||||||
// #elif CMD_RCTypeTable_Index == 1
|
|
||||||
// task_runtime.msgq.cmd.rc= osMessageQueueNew(3u, sizeof(AT9S_t), NULL);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
/* 任务示例 */
|
/* 任务示例 */
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
|
||||||
// #if CMD_RCTypeTable_Index == 0
|
/*
|
||||||
// DR16_t cmd_dr16;
|
* 初始化示例
|
||||||
// #elif CMD_RCTypeTable_Index == 1
|
*/
|
||||||
// AT9S_t cmd_at9s;
|
// void Example_CMD_Init(void) {
|
||||||
// #endif
|
// CMD_Init(&g_cmd_ctx, &g_cmd_config);
|
||||||
// Shoot_CMD_t *cmd_for_shoot;
|
// }
|
||||||
// Chassis_CMD_t *cmd_for_chassis;
|
|
||||||
// Gimbal_CMD_t *cmd_for_gimbal;
|
|
||||||
|
|
||||||
// static CMD_t cmd;
|
// /*
|
||||||
|
// * 任务循环示例
|
||||||
// void Task_cmd() {
|
// */
|
||||||
|
// void Example_CMD_Task(void) {
|
||||||
// CMD_Init(&cmd, &Config_GetRobotParam()->cmd_param);
|
// /* 一键更新 */
|
||||||
|
// CMD_Update(&g_cmd_ctx);
|
||||||
// while (1) {
|
|
||||||
// #if CMD_RCTypeTable_Index == 0
|
|
||||||
// osMessageQueueGet(task_runtime.msgq.cmd.rc, &cmd_dr16, NULL, 0);
|
|
||||||
// #elif CMD_RCTypeTable_Index == 1
|
|
||||||
// osMessageQueueGet(task_runtime.msgq.cmd.rc, &cmd_at9s, NULL, 0);
|
|
||||||
// #endif
|
|
||||||
// CMD_Update(&cmd);
|
|
||||||
|
|
||||||
// /* 获取命令发送到各模块 */
|
// /* 获取命令发送到各模块 */
|
||||||
// cmd_for_chassis = CMD_GetChassisCmd(&cmd);
|
// Chassis_CMD_t *chassis_cmd = CMD_GetChassisCmd(&g_cmd_ctx);
|
||||||
// cmd_for_gimbal = CMD_GetGimbalCmd(&cmd);
|
// Gimbal_CMD_t *gimbal_cmd = CMD_GetGimbalCmd(&g_cmd_ctx);
|
||||||
// cmd_for_shoot = CMD_GetShootCmd(&cmd);
|
// Shoot_CMD_t *shoot_cmd = CMD_GetShootCmd(&g_cmd_ctx);
|
||||||
// osMessageQueueReset(task_runtime.msgq.gimbal.cmd);
|
|
||||||
// osMessageQueuePut(task_runtime.msgq.gimbal.cmd, cmd_for_gimbal, 0, 0);
|
// /* 使用命令... */
|
||||||
// osMessageQueueReset(task_runtime.msgq.shoot.cmd);
|
// (void)chassis_cmd;
|
||||||
// osMessageQueuePut(task_runtime.msgq.shoot.cmd, cmd_for_shoot, 0, 0);
|
// (void)gimbal_cmd;
|
||||||
// osMessageQueueReset(task_runtime.msgq.chassis.cmd);
|
// (void)shoot_cmd;
|
||||||
// osMessageQueuePut(task_runtime.msgq.chassis.cmd, cmd_for_chassis, 0, 0);
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
/* 架构说明 */
|
/* 架构说明 */
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
|||||||
@ -18,9 +18,6 @@
|
|||||||
/* USER STRUCT END */
|
/* USER STRUCT END */
|
||||||
|
|
||||||
/* Private function --------------------------------------------------------- */
|
/* Private function --------------------------------------------------------- */
|
||||||
/* USER PRIVATE CODE BEGIN */
|
|
||||||
|
|
||||||
/* USER PRIVATE CODE END */
|
|
||||||
/* Exported functions ------------------------------------------------------- */
|
/* Exported functions ------------------------------------------------------- */
|
||||||
void {{task_function}}(void *argument) {
|
void {{task_function}}(void *argument) {
|
||||||
(void)argument; /* 未使用argument,消除警告 */
|
(void)argument; /* 未使用argument,消除警告 */
|
||||||
|
|||||||
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
atti_esti Task
|
|
||||||
带有pwm温控的纯陀螺仪(BMI088)姿态解算任务(无磁力计,赛场环境一般不适用)。
|
|
||||||
控制IMU加热到指定温度防止温漂,收集IMU数据给AHRS算法。
|
|
||||||
收集BMI088的数据,解算后得到四元数,转换为欧拉角之后放到消息队列中,
|
|
||||||
等待其他任务取用。
|
|
||||||
陀螺仪使用前需要校准,校准结果保存在bmi088_cali结构体中,需要自行实现。
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Includes ----------------------------------------------------------------- */
|
|
||||||
#include "task/user_task.h"
|
|
||||||
/* USER INCLUDE BEGIN */
|
|
||||||
|
|
||||||
#include "bsp/mm.h"
|
|
||||||
#include "bsp/pwm.h"
|
|
||||||
#include "component/ahrs.h"
|
|
||||||
#include "component/pid.h"
|
|
||||||
#include "device/bmi088.h"
|
|
||||||
/* USER INCLUDE END */
|
|
||||||
|
|
||||||
/* Private typedef ---------------------------------------------------------- */
|
|
||||||
/* Private define ----------------------------------------------------------- */
|
|
||||||
/* Private macro ------------------------------------------------------------ */
|
|
||||||
/* Private variables -------------------------------------------------------- */
|
|
||||||
/* USER STRUCT BEGIN */
|
|
||||||
BMI088_t bmi088;
|
|
||||||
AHRS_t gimbal_ahrs;
|
|
||||||
AHRS_Magn_t magn;
|
|
||||||
AHRS_Eulr_t eulr_to_send;
|
|
||||||
KPID_t imu_temp_ctrl_pid;
|
|
||||||
|
|
||||||
/*默认校准参数*/
|
|
||||||
BMI088_Cali_t cali_bmi088 = {
|
|
||||||
.gyro_offset = {0.0f, 0.0f, 0.0f},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const KPID_Params_t imu_temp_ctrl_pid_param = {
|
|
||||||
.k = 0.15f,
|
|
||||||
.p = 1.0f,
|
|
||||||
.i = 0.0f,
|
|
||||||
.d = 0.0f,
|
|
||||||
.i_limit = 1.0f,
|
|
||||||
.out_limit = 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* USER STRUCT END */
|
|
||||||
|
|
||||||
/* Private function --------------------------------------------------------- */
|
|
||||||
/* Exported functions ------------------------------------------------------- */
|
|
||||||
void Task_atti_esti(void *argument) {
|
|
||||||
(void)argument; /* 未使用argument,消除警告 */
|
|
||||||
|
|
||||||
|
|
||||||
osDelay(ATTI_ESTI_INIT_DELAY); /* 延时一段时间再开启任务 */
|
|
||||||
|
|
||||||
/* USER CODE INIT BEGIN */
|
|
||||||
BMI088_Init(&bmi088, &cali_bmi088);
|
|
||||||
AHRS_Init(&gimbal_ahrs, &magn, BMI088_GetUpdateFreq(&bmi088));
|
|
||||||
PID_Init(&imu_temp_ctrl_pid, KPID_MODE_NO_D,
|
|
||||||
1.0f / BMI088_GetUpdateFreq(&bmi088), &imu_temp_ctrl_pid_param);
|
|
||||||
BSP_PWM_Start(BSP_PWM_IMU_HEAT);
|
|
||||||
|
|
||||||
/* USER CODE INIT END */
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
/* USER CODE BEGIN */
|
|
||||||
BMI088_WaitNew();
|
|
||||||
BMI088_AcclStartDmaRecv();
|
|
||||||
BMI088_AcclWaitDmaCplt();
|
|
||||||
|
|
||||||
BMI088_GyroStartDmaRecv();
|
|
||||||
BMI088_GyroWaitDmaCplt();
|
|
||||||
|
|
||||||
/* 锁住RTOS内核防止数据解析过程中断,造成错误 */
|
|
||||||
osKernelLock();
|
|
||||||
/* 接收完所有数据后,把数据从原始字节加工成方便计算的数据 */
|
|
||||||
BMI088_ParseAccl(&bmi088);
|
|
||||||
BMI088_ParseGyro(&bmi088);
|
|
||||||
|
|
||||||
/* 根据设备接收到的数据进行姿态解析 */
|
|
||||||
AHRS_Update(&gimbal_ahrs, &bmi088.accl, &bmi088.gyro, &magn);
|
|
||||||
|
|
||||||
/* 根据解析出来的四元数计算欧拉角 */
|
|
||||||
AHRS_GetEulr(&eulr_to_send, &gimbal_ahrs);
|
|
||||||
osKernelUnlock();
|
|
||||||
|
|
||||||
/* 在此处用消息队列传递imu数据 */
|
|
||||||
/* osMessageQueuePut( ... ); */
|
|
||||||
|
|
||||||
/* 控制IMU加热器 */
|
|
||||||
BSP_PWM_SetComp(BSP_PWM_IMU_HEAT, PID_Calc(&imu_temp_ctrl_pid, 40.5f,
|
|
||||||
bmi088.temp, 0.0f, 0.0f));
|
|
||||||
/* USER CODE END */
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
cli Task
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Includes ----------------------------------------------------------------- */
|
|
||||||
#include "task/user_task.h"
|
|
||||||
/* USER INCLUDE BEGIN */
|
|
||||||
#include "device/mrobot.h"
|
|
||||||
/* USER INCLUDE END */
|
|
||||||
|
|
||||||
/* Private typedef ---------------------------------------------------------- */
|
|
||||||
/* Private define ----------------------------------------------------------- */
|
|
||||||
/* Private macro ------------------------------------------------------------ */
|
|
||||||
/* Private variables -------------------------------------------------------- */
|
|
||||||
/* USER STRUCT BEGIN */
|
|
||||||
|
|
||||||
/* USER STRUCT END */
|
|
||||||
|
|
||||||
/* Private function --------------------------------------------------------- */
|
|
||||||
/* USER PRIVATE CODE BEGIN */
|
|
||||||
/**
|
|
||||||
* @brief hello 命令回调
|
|
||||||
* @note 命令回调必须返回 0 (pdFALSE) 表示完成,返回非0会继续调用
|
|
||||||
*/
|
|
||||||
static long Cli_Hello(char *buffer, size_t size, const char *cmd) {
|
|
||||||
(void)cmd; /* 未使用cmd,消除警告 */
|
|
||||||
MRobot_Snprintf(buffer, size, "Ciallo~(∠・ω< )⌒★\r\n");
|
|
||||||
return 0; /* 返回0表示命令执行完成 */
|
|
||||||
}
|
|
||||||
/* USER PRIVATE CODE END */
|
|
||||||
/* Exported functions ------------------------------------------------------- */
|
|
||||||
void Task_cli(void *argument) {
|
|
||||||
(void)argument; /* 未使用argument,消除警告 */
|
|
||||||
|
|
||||||
|
|
||||||
osDelay(CLI_INIT_DELAY); /* 延时一段时间再开启任务 */
|
|
||||||
|
|
||||||
/* USER CODE INIT BEGIN */
|
|
||||||
/* 初始化 MRobot CLI 系统 */
|
|
||||||
MRobot_Init();
|
|
||||||
MRobot_RegisterCommand("hello", " --hello: 打印问候语\r\n", Cli_Hello, -1);
|
|
||||||
/* USER CODE INIT END */
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
/* USER CODE BEGIN */
|
|
||||||
/* 运行 MRobot 主循环 */
|
|
||||||
MRobot_Run();
|
|
||||||
/* USER CODE END */
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
atti_esti:
|
|
||||||
name: "atti_esti"
|
|
||||||
frequency: 1000
|
|
||||||
delay: 0
|
|
||||||
stack: 512
|
|
||||||
freq_control: false
|
|
||||||
description: |
|
|
||||||
带有PWM温控的纯陀螺仪(BMI088)姿态解算任务
|
|
||||||
功能特点:
|
|
||||||
- 控制IMU加热到指定温度防止温漂
|
|
||||||
- 收集BMI088数据给AHRS算法进行姿态解算
|
|
||||||
- 解算后得到四元数,转换为欧拉角放到消息队列
|
|
||||||
- 使用PID控制IMU温度到40.5°C
|
|
||||||
- 运行频率1000Hz,提供高精度姿态信息
|
|
||||||
注意事项:
|
|
||||||
- 陀螺仪使用前需要校准,校准结果保存在bmi088_cali结构体中
|
|
||||||
- 无磁力计版本,适用于干净的电磁环境
|
|
||||||
- 需要配置PWM通道用于IMU加热控制
|
|
||||||
cli:
|
|
||||||
name: "cli"
|
|
||||||
frequency: 500
|
|
||||||
delay: 0
|
|
||||||
stack: 1024
|
|
||||||
freq_control: false
|
|
||||||
description: |
|
|
||||||
命令行接口任务
|
|
||||||
通过串口实现的虚拟终端,配合putty食用更佳
|
|
||||||
需要freertos_cli组件支持,还有mrobot设备驱动
|
|
||||||
Loading…
Reference in New Issue
Block a user