STM32-MBD(1)Matlab2022/2023 安装 STM32 硬件支持包
STM32-MBD(1b)Matlab2025b 安装 STM32 硬件支持包
STM32-MBD(2)Simulink 模型部署入门:点灯
STM32-MBD(3)Simulink 模型部署之状态机:闪灯
STM32-MBD(4)Simulink 模型部署之状态机:开关控制
STM32-MBD(5)Simulink 模型开发之外部中断:开关控制
STM32-MBD(6)Simulink 模型开发之多路 PWM 输出
STM32-MBD(7)Simulink 模型开发之 ADC 转换
STM32-MBD(8)Simulink 模型开发之串口通信
STM32-MBD(9)Simulink 模型开发之上位机显示波形
STM32-MBD(10)基于 STM32 的处理器在环仿真(PIL)
【STM32-MBD】(9)Simulink 模型开发之上位机显示波形
-
- [1. 项目简介](#1. 项目简介)
-
- [1.1 项目内容](#1.1 项目内容)
- [1.2 软硬件条件](#1.2 软硬件条件)
- [2. 用 STM32CubeMX 创建工程](#2. 用 STM32CubeMX 创建工程)
-
- [2.1 基础配置](#2.1 基础配置)
- [2.2 ADC 配置](#2.2 ADC 配置)
- [2.3 串口配置](#2.3 串口配置)
- [2.4 项目配置](#2.4 项目配置)
- [3. Simulink 仿真模型](#3. Simulink 仿真模型)
-
- [3.1 创建仿真模型](#3.1 创建仿真模型)
- [3.2 关联 Simulink 模型与 CubeMX 工程](#3.2 关联 Simulink 模型与 CubeMX 工程)
- [3.3 STM32 代码生成与运行](#3.3 STM32 代码生成与运行)
- [4. 任务分频实验](#4. 任务分频实验)
-
- [4.1 总体方案](#4.1 总体方案)
- [4.2 Simulink 模型结构说明](#4.2 Simulink 模型结构说明)
- [5. 串口发送多路 ADC 信号实验](#5. 串口发送多路 ADC 信号实验)
在基于 STM32 的嵌入式系统开发中,串口通信是最基础、也是最常用的功能之一。传统做法通常需要在 main.c 中编写中断或 DMA 回调函数来完成串口接收与发送,代码耦合度较高,不利于快速验证和教学演示。
1. 项目简介
1.1 项目内容
在本系列【STM32-MBD】前面的文章中,我们已经完成了以下工作:
- 使用 STM32CubeMX 完成 STM32G431 外设配置(ADC、LPUART、DMA);
- 在 STM32G431 上实现了片上温度传感器的数据采集;
- 使用 Simulink 构建基于模型的嵌入式系统(Model-Based Design, MBD);
- 通过 Simulink 自动生成代码并部署到 NUCLEO-G431RB 开发板。
本案例 NUCLEO-G431RB 开发板,运用 Simulink + STM32CubeMX 的模型化设计(Model-Based Design, MBD)方法,采集 STM32G431 片上温度,通过串口向 PC 发送温度数据,并在 VOFA+ 上实时显示温度曲线。全流程采用 Simulink 模型驱动,不手写应用层 C 代码。
整体技术路线如下:
STM32G431 ADC → Simulink 模型(温度计算)→ MATLAB Function(JustFloat 数据帧封装)→ UART Write(串口发送)→ PC 串口接收 → VOFA+(JustFloat 模式)
1.2 软硬件条件
关于所需的软硬件条件和安装过程,详见 【STM32-MBD】(1)安装 Simulink STM32 硬件支持包。
强烈建议安装相关软件时使用推荐版本。
请严格按照文中介绍的步骤安装和配置软件。
必需的硬件:
- STM32 开发板(如:NUCLEO-G431RB 开发板,也可以选择其它 STM32 开发板,但需要安装对应的固件包)。
- Micro-micro USB 数据线,或 USB Type-A 至 Micro-B 连接线缆,用于将STM32 Nucleo 板连接到 PC。
必需的软件:
-
STM32 开发工具(建议首先严格使用推荐版本跑通本文项目)
- STM32CubeMX (推荐使用 V6.4.0)
- STM32CubeProgrammer (推荐使用 V2.6.0)
- STM32CubeIDE(或 Keil,MDK-ARM 等 IDE 工具)
- STM32Cube_FW_G4 固件包(推荐采用 V1.5.0)
如果使用其它 STM32 MCU,则需选择对应的固件包。例如使用 STM32F4 时则要选择STM32Cube_FW_F4_V1.26.0 固件包。
-
MATLAB/Simulink(本文使用 MATLAB R2022b,可以采用更新版本)
- Simulink Coder:从 Simulink 模型、Stateflow 图和 MATLAB 函数生成并执行 C 和 C++ 代码,用于实时和非实时应用,包括仿真加速、快速原型构建和硬件在环测试
- STM32 嵌入式硬件支持包,Embedded Coder Support Package for STMicroelectronics STM32 Processors,STM32 处理器的嵌入式硬件支持包
-
VOFA+ 上位机(串口通信软件)
2. 用 STM32CubeMX 创建工程
2.1 基础配置
本例直接使用 STM32CubeMX 创建新的 STM32 工程。也可以从 Simulink 创建 STM32CubeMX 工程。
-
打开 STM32CubeMX。
-
选择 New Project(或Ctrl-N快捷键)新建工程,进入 New Project 界面。
选择 STM32G431RB 作为目标 MCU(参考开发板的 MCU 型号)新建 CubeMX 工程,将工程保存为 "STM32G431_MBD08.ioc"。
-
自动转入 CubeMX 的 Pinout Configuration 视图,进行管脚配置:
(1)选择 "System Core -- SYS" 设置调试器类型,将 Debug 模式设为 "Serial Wire"。
(2)选择 "System Core -- SYS" 设置基础时钟源,将 Timebase Source 设为 "TIM2"------非常重要!
注意:Timebase Source 默认为 "SysTick",但在 STM32支持包中 "SysTick" 已经用作框架的基础时间功能,因此必须修改为 非"SysTick" 的其它定时器。否则在编译项目时会报错------非常重要!。

(3)选择 "System Core -- RCC" 配置时钟模式,设置高速晶振为外部时钟,将 High Speed Clock (HSE) 设为 "Crystal/Ceramic Resonator"。

(4)可选地,选择 "System Core -- GPIO" 配置 GPIO。
- 搜索 PA5 管脚(在 NUCLEO 开发板中 连接LD2 灯),将其设置为 GPIO_Output。
- 搜索 PC13 管脚(在 NUCLEO 开发板中 连接蓝色用户按键 User Button),将其设置为 GPIO_EXTI13。

2.2 ADC 配置
- 启用并配置 ADC 通道 :
选择 PA0 为 ADC1-IN1 的采样通道引脚,配置为模拟模式。
(1)选择 "引脚配置(Pinout & Configuration)",从左侧下拉列表中选择 "Analog -- ADC1" ,使用 IN1(PA0) 作为模拟输入通道,将 IN1 设置为 "IN1 Singel-ended"。在 Pinout view 视图中,将 PA0 引脚配置为 "ADC1_IN1"(通常会自动配置)。
(2)开启独立通道 IN1,设置为 "IN1 Single-ended"。
(3)开启 温度传感器通道 和 内部电压基准(Vrefint)通道。

(4)配置 ADC 工作模式和参数。
bash
ADCs_Common_Settings
Mode: Independent mode
ADC_Settings
Resolution: ADC 12-bit resolution
Data Alignment: Right alignment(右对齐)
Gain Compensation: 默认为 0
Scan Conversion Mode:Enable
End of Conversion Selection:End of sequence of conversion
Continuous Conversion Mode: Disable
DMA Continuous Requests: Enabled
Number of Conversion: 2
Rank 1:
Channel: Channel Temperature Sensor
Smapling Time: 92.5 Cycles
Offset Number: No offset
Rank 2:
Channel: Channel Vrefint
Smapling Time: 92.5 Cycles
Offset Number: No offset
(5)添加 DMA 通道:
在 ADC1 的 DMA Settings 中添加一个 DMA 通道;
bash
Add DMA Request:ADC1
Mode:Circular
Data Width:Half Word(16-bit)

2.3 串口配置
- 配置 虚拟串口 LPUART1:
(1)在 Nucleo-G431RB开发板上,默认 LPUART1(PA2/PA3)接到 ST-LINK 的虚拟串口。将 PA2 管脚设置为 LPUART1_TX,将 PA3 管脚设置为 LPUART1_RX。

(2)选择 "Connectivity -- LPUART1" 配置 LPUART1,设置模式(Mode)为 "Asynchronous",在 LPUART1 参数里面设置:
bash
- Baud Rate:115200 Bits/s
- Word Length:8 Bits
- Parity:None
- Stop Bits:1
- Data Direction:Receive and Transmit(收发都开)
(3)选择 "Connectivity -- LPUART1-DMA Settings" 配置 DMA 传输,在 DMA Request 中添加:LPUART1_RX 和 LPUART1_TX 。

2.4 项目配置
-
在 Clock Configuration 视图进行时钟配置,如下图所示。
本实验对于时钟时钟设置没有太多要求,只要设置正确即可。本例中使用外部 160MHz晶振,具体设置如下图所示,只供参考。

-
点击菜单栏 "Project Manager" 进入工程配置界面,如下图所示。
(1)在 Project Name 输入项目名称 "STM32G431_MBD08"。
(2)在 Toolchain/IDE 选择 IDE 工具为 "STM32CubeIDE"(也可以根据需要选择其它 IDE 工具 )。

(3)在 "Project Manager" 继续向下拉,"在 MCU and Firmware Package" 栏中,取消选中 "Use latest available version",根据所安装的 G4 固件版本,选择 "STM32Cube FW_G4 V1.6.0";
(4)如果固件包不是安装在默认路径,则要取消选中 "Use Default Firmware Location",通过 Browse 选择固件包的安装路径。

(5)在 Code Generator 中,勾选 "Generate peripheral initialization as a pair of '.c/.h' files per peripheral",让每个外设生成独立的'.c/.h'文件。

(6)在 Advanced Settings 中,**将 "Driver Selector" 全部设置为 "LL"(默认为 "HAL"),为外设选择低级 (LL) 驱动------非常重要!** 否则编译会报错。
(7)在 Advanced Settings 中,将 "Generated Function Calls" 的 "Visibility(Static)" 勾选项全部取消,对所有外设初始化函数调用取消选择可见性(静态)。
- 完成以上配置后,使用快捷键 "CTL+S" 或点击 File--Save Project,保存 CubeMX 项目文件。
注意:在 STM32CubeMX 中配置完成后,不要点击 "GENERATE CODE" 生成代码,而是直接保存项目文件 "STM32G431_MBD07.ioc"。
3. Simulink 仿真模型
3.1 创建仿真模型
在 CubeMX 项目文件所在的路径(例如:"D:\SimulinkProjects\STM32G431_MBD08")下新建 Simulink 仿真模型,注意 *仿真模型 .slx 与 CubeMX 项目 .ioc 要保存在同一个目录下。
-
运行 MATLAB 软件,打开 Simulink。点击 "空白模型" 创建新的 Simulink 模型,保存到本项目路径下:
STM32G431_MBD08.slx。 -
创建一个 Function-Call Subsystem 模块。
(1)点击菜单栏的 "库浏览器" 打开库浏览器,展开 "Simulink/Ports &Subsystems"。选择 "Function-Call Subsystem" 模块,将其拖动到右侧的仿真模型。
(2)或者,简单地,在仿真模型空白处鼠标双击,弹出"搜索模块"菜单,在搜索栏输入 "function...",从搜索结果列表选择 "Function-Call Subsystem" 模块,即在模型中创建该模块。

-
点击 "Function-Call Generator" 模块,设置采样时间为 0.1。
-
双击进入 "Function-Call Subsystem" 模块。创建 ADC模块、MATLAB function 模块 和 Uart/Usart Write 模块。

- 根据 CubeMX 项目中的配置,配置 ADC 模块参数:
bash
ADC module: ADC1
Conversion group: Regular
Trigger mode: Trigger and read
Number of conversions: 2
-
配置 "UART/USART Write" 模块:
(1)设置为 LPUART1 端口。
(2)勾选 "指定待写入数据长度(Specify length of input data to write)"选项,添加一个输入数据长度端口,即可设定需要写入至 UART/USART 端口的输入数据长度。
-
添加一个 constant 模块,将其设为 "8",表示串口发送长度采用 JustFloat(1通道)帧 = 4B 温度 + 4B 帧尾 = 8 字节。
-
编写 Matlab Function 模块程序,计算温度值并按 VOFA+ JustFloat 协议打包数据帧。
(1)根据 STM32G431 数据手册中的公式,编写函数计算 片上温度 Tc(degC) 和 内部电压基准 Vts(V)。片上温度传感器的输出电压 V T S V_{TS} VTS 随温度变化,近似满足线性关系:
T = V T S − V 30 A v g S l o p e + 30 T = \frac{V_{TS}-V_{30}}{A_{vg}Slope} + 30 T=AvgSlopeVTS−V30+30
其中:
-
V30:30℃ 时的传感器电压(典型值 ≈ 0.76V)
-
AvgSlope:平均斜率(典型值 ≈ 2.5mV/℃)
(2) VOFA+ JustFloat 协议:
JustFloat 协议是一种小端浮点数组形式的字节流协议,通过纯十六进制浮点传输。JustrFloat 以小端的 0x7f80000,也即小端序字节表示 { 0x00, 0x00, 0x80, 0x7f } 作为帧结束标志。
典型的数据格式如下:ch_data为小端浮点数组,里面放着需要发送的CH_COUNT个通道;tail 为帧尾。
c
#define CH_COUNT <N>
struct Frame {
float ch_data[CH_COUNT];
unsigned char tail[4]{0x00, 0x00, 0x80, 0x7f};
};
在本例中,单通道温度数据 ch_data 采用 4字节,帧尾 tail 为 4字节,单通道温度数据的完整帧长度为 8 字节。
(3)编写函数 build_vofa_temp_frame_10hz(ts_raw, vref_raw) 代码如下:
c
function frame = build_vofa_temp_frame_10hz(ts_raw, vref_raw)
%#codegen
% 10Hz(基准步长0.1s)每步输出一帧:
% [Tc(float32, 4B little-endian), Tail(00 00 80 7F)]
% -------- Parameters (same as sf_TempSensor) --------
USE_VREFINT = 1; % 0: fixed VDDA, 1: estimate VDDA from VREFINT
VDDA_FIXED_V = 3.3; % used when USE_VREFINT=0
VREFINT_CAL_RAW = 1659; % 用 CubeProgrammer 读到的校准raw
V30_V = 0.76; % V at 30°C (typical)
AVG_SLOPE = 0.0025; % V/°C (2.5mV/°C)
% -------- Cast to double (same behavior as your verified function) --------
ts = double(ts_raw);
vr = double(vref_raw);
% -------- Compute VDDA --------
if (USE_VREFINT ~= 0) && (vr > 0)
% VDDA = 3.0V * VREFINT_CAL / VREFINT_RAW
VDDA_V = (3.0 * double(VREFINT_CAL_RAW)) / vr;
VDDA_V = min(max(VDDA_V, 2.0), 3.6); % Safety clamp
else
VDDA_V = VDDA_FIXED_V;
end
% -------- Raw -> Vts (V) --------
Vts = ts * (VDDA_V / 4096.0);
% -------- Typical temperature formula (degC) --------
Tc = (Vts - V30_V) / AVG_SLOPE + 30.0;
% -------- Pack Tc as float32 (VOFA+ JustFloat) --------
Tc_f32 = single(Tc); % VOFA+需要float32
u32 = typecast(Tc_f32, 'uint32'); % float32 bits
% -------- Output (fixed-size) --------
frame = uint8(zeros(1,8));
% little-endian bytes
frame(1) = uint8(bitand(u32, uint32(255)));
frame(2) = uint8(bitand(bitshift(u32, -8), uint32(255)));
frame(3) = uint8(bitand(bitshift(u32, -16), uint32(255)));
frame(4) = uint8(bitand(bitshift(u32, -24), uint32(255)));
% -------- Tail: 0x7F800000 (little-endian) --------
frame(5) = uint8(0x00);
frame(6) = uint8(0x00);
frame(7) = uint8(0x80);
frame(8) = uint8(0x7F);
end

3.2 关联 Simulink 模型与 CubeMX 工程
- 在 Simulink 菜单选择 "建模" - "模型设置" (也可以用 CTRL+E),打开"配置参数"对话框。
左侧边栏中选择"求解器",如下图所示。
(1)在右侧 "仿真时间" 设置为 "inf"。
(2)在 "求解器选择" 选项设置类型为 "定步长","固定步长(基础采样时间)" 设为 "0.1" (对应于 MCU 的 ADC 采样频率为 10Hz)。
(3)可选地,在 "任务和采样周期选项"下勾选:"将每个离散速率视为单独任务"和"自动处理数据传输的速率转换"。

-
在右侧 "硬件实现(Hardware board settings)" 配置 "Target hardware resources" ,关联 STM32CubeMX 工程文件。
(1)检查 PC 与 STM32G431 开发板连接正常。 在 "Hardware board" 选项的下拉框中选择 "STM32G4xx Based".
注意:必须确保 PC 与 STM32G431 开发板连接正常,才能进行硬件配置。
(2)点击 "Browse" 选择当前项目的目录,选择 CubeMX 创建的工程文件 "STM32G431_MBD08.ioc"。
选择硬件在环通信串口。
(3)点击 "Target hardware resources--Groups--Connectivity",将 "USART/UART" 设为 "LPUART1",将 "Serial port" 设为 电脑上的 COM 端口。具体端口号可以查看电脑"设备管理器"中的"端口(COM和LPT)"。 -
完成搭建仿真模型,保存为文件 STM32G431_MBD08.slx。注意仿真模型 .slx 与 CubeMX 项目 .ioc 要保存在相同的路径下。
3.3 STM32 代码生成与运行
-
用 USB连接线连接 PC 与 NUCLEO-G431RB 开发板。
-
在 Simulink 打开仿真模型 STM32G431_MBD07.slx。
-
在 "硬件(Hardware)" 窗口点击 "编译、部署和启动"(Ctrl+B 快捷键),就启动模型 STM32G431_MBD07 的编译过程,为模型生成代码,并加载到 NUCLEO-G431RB 开发板。
模型编译过程的主要信息显示在 "诊断查看器" 中,编译摘要如下。
c
### 正在启动 STM32G431_MBD08 的编译过程
### 正在为 '模型特定' 文件夹结构生成代码和工件
### 正在将代码生成到编译文件夹中: C:\MATLAB\SimMBD2025\STM32G431_MBD08\STM32G431_MBD08_ert_rtw
### Invoking Target Language Compiler on STM32G431_MBD08.rtw
### Using System Target File: C:\MATLAB\R2023b\rtw\c\ert\ert.tlc
...
### 使用工具链: GNU Tools for ARM Embedded Processors
### 'C:\MATLAB\SimMBD2025\STM32G431_MBD08\STM32G431_MBD08_ert_rtw\STM32G431_MBD08.mk' 是最新的
### 正在编译 'STM32G431_MBD08': "C:\MATLAB\R2023b\bin\win64\gmake" -f STM32G431_MBD08.mk all
...
Download verified successfully
### Successful completion of build procedure for: STM32G431_MBD08
### 'STM32G431_MBD08' 的 Simulink 缓存工件是在 'C:\MATLAB\SimMBD2025\STM32G431_MBD08\STM32G431_MBD08.slxc' 中创建的。
编译过程已成功完成
编译的顶层模型目标:
模型 操作 重新编译原因
=========================================
STM32G431_MBD08 代码已生成并完成编译。 生成的代码已过期。
编译了 1 个模型,共 1 个模型(0 个模型已经是最新的)
编译持续时间: 0h 0m 10.489s

-
Simulink 通过调用 STM32CubeProgrammer 将编译的目标文件加载到 STM32 开发板。
-
打开 VOFA+ 软件:
(1)点击 "数据引擎" 下拉菜单,选择 "JustFloat" 协议。
(2)点击 "数据接口" 下拉菜单,选择 "串口"。
(3)点击 "端口号" 下拉菜单,选中 STM STLink Virtual COM Port。
(4)将配置参数设为与 STM32CubeMX 中 "Connectivity -- LPUART1" 的配置一致。
bash
波特率:115200
数据位:8 Bits
校验位:None
停止位:1
- 点击 VOFA+ 左上角的 "连接" 按钮,在数据显示区就将显示 HEX 格式的数据,并在上方图形区域显示 温度曲线。

实验运行后可以观察到:
- 温度曲线连续、平滑;
- 图中温度值约 30~35℃,数值与片上温度传感器的物理预期一致;
- 用手指按住 MCU 芯片区域 10~20 秒,红色曲线上升至 30℃ 左右;松开手指后 温度缓慢下降并恢复到正常值;
- 系统运行稳定,无丢帧、无明显抖动。
这表明:
- 串口通信链路正确;
- 数据打包与字节序无误;
- Simulink → STM32 → VOFA+ 的完整链路已成功打通。
4. 任务分频实验
上述模型虽然实现了上位机显示波形,但每个采样周期都会进行通信,通信资源占用太高且容易不稳定。我们希望实现 任务分频 ,建立 "快采样、慢上传" 的数据链路。
4.1 总体方案
- 实验目的:
- 建立"快采样、慢上传"的典型嵌入式数据链路:
- MCU 以较高频率采集/计算(100Hz)以获得更平滑、更稳定的内部变量;
- 以较低频率上传(10Hz)降低串口带宽占用、减少上位机显示抖动与丢帧风险。
- 掌握在 Simulink MBD 中实现 任务分频/周期门控(rate gating) 的方法。
- 实验要求:
-
采样和通信频率:
- 模型基准步长(Fixed-step size)= 0.01s,即 100Hz
- 以 100Hz 执行温度采样和计算,便于执行其它任务
- 以 10Hz 执行串口发送
-
数据格式:VOFA+ JustFloat
- 技术方案:
本案例基于 Simulink + STM32CubeMX 的模型化设计(Model-Based Design, MBD)方法,以 NUCLEO-G431RB 开发板的 LPUART1(ST-LINK 虚拟串口) 为通信接口,构建一个 ADC 采样、计算和串口通信实验。
周期门控(rate gating):
- Function-Call Generator:采样时间设为 0.01
- 在 Function-Call Subsystem 内引入一个"发送门控信号 send_flag":
- 每执行 10 次(10×0.01=0.1s)产生一次 send_flag=true
- 用 If Action Subsystem 让 UART Write 只在 send_flag 为 true 时执行。
4.2 Simulink 模型结构说明
Simulink 模型结构如下图所示。
bash
Root
├─ Function-Call Generator (Ts=0.01)
└─ Function-Call Subsystem (every 0.01s)
├─ ADC1 → Demux2 → ts_raw, vref_raw
├─ temp_calc_vrefint(ts_raw, vref_raw) → Tc, Vts, VDDA_V [100Hz]
├─ rate_gate_10hz() → send_flag [100Hz]
└─ If(send_flag)
├─ Send_Subsystem (10Hz)
│ ├─ pack_justfloat_1ch(Tc) → frame(uint8[8])
│ └─ UART Write(Data=frame, Length=8)
└─ Else_Subsystem (empty)

-
顶层模型结构(Root)
顶层模型包含两个模块:
- Function-Call Generator
用于产生周期性的函数调用触发信号,触发周期设置为 0.01 s(100 ms)。 - Function-Call Subsystem
接收函数调用触发信号,用于明确任务的执行时序,在每次触发时执行一次处理逻辑。
- Function-Call Generator
-
Function-Call Subsystem 内部结构(每 0.01 s执行一次)
Function-Call Subsystem 内部包含以下模块:
-
2.1 ADC 采样(100Hz)
- ADC1(输出向量,长度2)
输出:adc_vec(例如 [tempsensor_raw, vrefint_raw]) - Demux (2)
输出1:ts_raw(uint16)
输出2:vref_raw(uint16)
- ADC1(输出向量,长度2)
-
2.2 温度计算(100Hz,供其它任务使用)
- MATLAB Function:temp_calc_vrefint
输入:ts_raw, vref_raw
输出:
Tc(single,℃) ✅ 主输出
Vts(single,V) (可选)
VDDA_V(single,V)(可选) - (可选)可以把 Tc/Vts/VDDA_V 分到后续控制/滤波/报警等模块
- MATLAB Function:temp_calc_vrefint
-
2.3 10Hz 发送门控信号生成(100Hz 内部计数)
- MATLAB Function:rate_gate_10hz
输出:send_flag(boolean/uint8)
逻辑:每累计 10 次 tick(0.01×10=0.1s)输出一次 true
- MATLAB Function:rate_gate_10hz
-
2.4 条件触发发送(10Hz)
- If Block
输入:send_flag
表达式:u1 ~= 0
action 输出:
true action → Send_Subsystem.ActionPort
else action → Else_Subsystem.ActionPort
- If Block
- Send_Subsystem(If Action Subsystem,以10Hz 执行)
-
3.1 JustFloat 帧打包(10Hz)
- Inport:Tc_in(从外部接入 Tc)
- MATLAB Function:pack_justfloat_1ch
输入:Tc_in(single)
输出:frame(uint8[1×8])
frame 内容:
前 4B:Tc(float32) 小端
后 4B:帧尾 00 00 80 7F(0x7F800000 小端)
-
3.2 串口发送(10Hz)
- UART Write
Data ← frame
Length ← Constant(8)(uint8)
- UART Write
- Else_Subsystem(If Action Subsystem,仅在非发送周期执行)
内部为空(Do Nothing)
模型求解器设置为:Fixed-step;基础采样时间(Fixed-step size)= 0.01 s。
在模型成功编译并部署到 NUCLEO-G431RB 开发板后:
实验结果表明:模型逻辑与预期一致;串口通信过程可靠。
5. 串口发送多路 ADC 信号实验
本节在现有"0.01s 采样/计算 + 0.1s 分频发送"任务分频实验基础上,扩展成 发送 2 路 ADC 信号(Tc、Vts)到 VOFA+ 并显示两条曲线的完整实验设计与落地步骤。整体思路不变:温度每步算(100Hz),打包+发送仅 10Hz;只是把 JustFloat 帧从 1通道(8B) 扩展到 2通道(12B)。
- 基准步长(Fixed-step size)= 0.01s
每步计算温度相关量:Tc(℃)、Vts(V)
串口上传频率:10Hz(0.1s/帧) - 按 VOFA+ JustFloat 协议发送两通道:
CH1 = Tc(float32)
CH2 = Vts(float32)
帧尾 = 0x7F800000 小端:00 00 80 7F - 协议与帧格式
CH1:float32(4字节,小端)= Tc
CH2:float32(4字节,小端)= Vts
Tail:0x7F800000(4字节,小端)= {00 00 80 7F}
完整的帧长度为 4*2+4 = 12(bytes)
模型结构
在上节的基础上,只要把 Send_Subsystem 中的打包函数从 1 通道升级为 2 通道,并把 Length 改为 12 即可实现。
-
保持不变的部分
Root:Function-Call Generator (Ts=0.01) → Function-Call Subsystem
Subsystem 内:
- ADC1 → Demux(ts_raw, vref_raw)
- temp_calc_vrefint 每步输出 Tc、Vts
- rate_gate_10hz 产生 send_flag
- If(send_flag) → Send_Subsystem / Else_Subsystem
-
需要修改的部分
(1)pack_justfloat_1ch(Tc) → 替换为 pack_justfloat_2ch(Tc, Vts)
(2)UART Write.Length:8 → 12

函数 pack_justfloat_2ch
c
function frame = pack_justfloat_2ch(Tc, Vts)
%#codegen
% Two-channel JustFloat frame:
% [Tc(float32,4B LE), Vts(float32,4B LE), Tail(00 00 80 7F)]
frame = uint8(zeros(1,12));
% ---- Pack CH1: Tc ----
u1 = typecast(single(Tc), 'uint32');
frame(1) = uint8(bitand(u1, uint32(255)));
frame(2) = uint8(bitand(bitshift(u1, -8), uint32(255)));
frame(3) = uint8(bitand(bitshift(u1, -16), uint32(255)));
frame(4) = uint8(bitand(bitshift(u1, -24), uint32(255)));
% ---- Pack CH2: Vts ----
u2 = typecast(single(Vts), 'uint32');
frame(5) = uint8(bitand(u2, uint32(255)));
frame(6) = uint8(bitand(bitshift(u2, -8), uint32(255)));
frame(7) = uint8(bitand(bitshift(u2, -16), uint32(255)));
frame(8) = uint8(bitand(bitshift(u2, -24), uint32(255)));
% ---- Tail: 0x7F800000 little-endian ----
frame(9) = uint8(0x00);
frame(10) = uint8(0x00);
frame(11) = uint8(0x80);
frame(12) = uint8(0x7F);
end


(本节完)
版权声明:
youcans@qq.com 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/155918280)
Copyright@youcans 2025
Crated:2025-12