【STM32-MBD】(9)Simulink 模型开发之上位机显示波形

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)

    • [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 工程。

  1. 打开 STM32CubeMX。

  2. 选择 New Project(或Ctrl-N快捷键)新建工程,进入 New Project 界面。

    选择 STM32G431RB 作为目标 MCU(参考开发板的 MCU 型号)新建 CubeMX 工程,将工程保存为 "STM32G431_MBD08.ioc"。

  3. 自动转入 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 配置

  1. 启用并配置 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 串口配置

  1. 配置 虚拟串口 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 项目配置

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

  2. 点击菜单栏 "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)" 勾选项全部取消,对所有外设初始化函数调用取消选择可见性(静态)。

  1. 完成以上配置后,使用快捷键 "CTL+S" 或点击 File--Save Project,保存 CubeMX 项目文件。
    注意:在 STM32CubeMX 中配置完成后,不要点击 "GENERATE CODE" 生成代码,而是直接保存项目文件 "STM32G431_MBD07.ioc"。

3.1 创建仿真模型

在 CubeMX 项目文件所在的路径(例如:"D:\SimulinkProjects\STM32G431_MBD08")下新建 Simulink 仿真模型,注意 *仿真模型 .slx 与 CubeMX 项目 .ioc 要保存在同一个目录下。

  1. 运行 MATLAB 软件,打开 Simulink。点击 "空白模型" 创建新的 Simulink 模型,保存到本项目路径下:STM32G431_MBD08.slx

  2. 创建一个 Function-Call Subsystem 模块。

    (1)点击菜单栏的 "库浏览器" 打开库浏览器,展开 "Simulink/Ports &Subsystems"。选择 "Function-Call Subsystem" 模块,将其拖动到右侧的仿真模型。

    (2)或者,简单地,在仿真模型空白处鼠标双击,弹出"搜索模块"菜单,在搜索栏输入 "function...",从搜索结果列表选择 "Function-Call Subsystem" 模块,即在模型中创建该模块。

  1. 点击 "Function-Call Generator" 模块,设置采样时间为 0.1。

  2. 双击进入 "Function-Call Subsystem" 模块。创建 ADC模块、MATLAB function 模块 和 Uart/Usart Write 模块。

  1. 根据 CubeMX 项目中的配置,配置 ADC 模块参数:
bash 复制代码
ADC module: ADC1
Conversion group: Regular
Trigger mode: Trigger and read
Number of conversions: 2
  1. 配置 "UART/USART Write" 模块:

    (1)设置为 LPUART1 端口。

    (2)勾选 "指定待写入数据长度(Specify length of input data to write)"选项,添加一个输入数据长度端口,即可设定需要写入至 UART/USART 端口的输入数据长度。

  2. 添加一个 constant 模块,将其设为 "8",表示串口发送长度采用 JustFloat(1通道)帧 = 4B 温度 + 4B 帧尾 = 8 字节。

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

  2. 完成搭建仿真模型,保存为文件 STM32G431_MBD08.slx。注意仿真模型 .slx 与 CubeMX 项目 .ioc 要保存在相同的路径下。

3.3 STM32 代码生成与运行

  1. 用 USB连接线连接 PC 与 NUCLEO-G431RB 开发板。

  2. 在 Simulink 打开仿真模型 STM32G431_MBD07.slx。

  3. 在 "硬件(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
  1. Simulink 通过调用 STM32CubeProgrammer 将编译的目标文件加载到 STM32 开发板。

  2. 打开 VOFA+ 软件:

    (1)点击 "数据引擎" 下拉菜单,选择 "JustFloat" 协议。

    (2)点击 "数据接口" 下拉菜单,选择 "串口"。

    (3)点击 "端口号" 下拉菜单,选中 STM STLink Virtual COM Port。

    (4)将配置参数设为与 STM32CubeMX 中 "Connectivity -- LPUART1" 的配置一致。

bash 复制代码
波特率:115200
数据位:8 Bits
校验位:None
停止位:1
  1. 点击 VOFA+ 左上角的 "连接" 按钮,在数据显示区就将显示 HEX 格式的数据,并在上方图形区域显示 温度曲线。

实验运行后可以观察到:

  • 温度曲线连续、平滑;
  • 图中温度值约 30~35℃,数值与片上温度传感器的物理预期一致;
  • 用手指按住 MCU 芯片区域 10~20 秒,红色曲线上升至 30℃ 左右;松开手指后 温度缓慢下降并恢复到正常值;
  • 系统运行稳定,无丢帧、无明显抖动。

这表明:

  • 串口通信链路正确;
  • 数据打包与字节序无误;
  • Simulink → STM32 → VOFA+ 的完整链路已成功打通。

4. 任务分频实验

上述模型虽然实现了上位机显示波形,但每个采样周期都会进行通信,通信资源占用太高且容易不稳定。我们希望实现 任务分频 ,建立 "快采样、慢上传" 的数据链路。

4.1 总体方案

  1. 实验目的:
  • 建立"快采样、慢上传"的典型嵌入式数据链路:
    • MCU 以较高频率采集/计算(100Hz)以获得更平滑、更稳定的内部变量;
    • 以较低频率上传(10Hz)降低串口带宽占用、减少上位机显示抖动与丢帧风险。
  • 掌握在 Simulink MBD 中实现 任务分频/周期门控(rate gating) 的方法。
  1. 实验要求:
  • 采样和通信频率:

    • 模型基准步长(Fixed-step size)= 0.01s,即 100Hz
    • 以 100Hz 执行温度采样和计算,便于执行其它任务
    • 以 10Hz 执行串口发送
  • 数据格式:VOFA+ JustFloat

  1. 技术方案:

本案例基于 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 时执行。

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)
  1. 顶层模型结构(Root)

    顶层模型包含两个模块:

    • Function-Call Generator
      用于产生周期性的函数调用触发信号,触发周期设置为 0.01 s(100 ms)。
    • Function-Call Subsystem
      接收函数调用触发信号,用于明确任务的执行时序,在每次触发时执行一次处理逻辑。
  2. 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)
  • 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 分到后续控制/滤波/报警等模块
  • 2.3 10Hz 发送门控信号生成(100Hz 内部计数)

    • MATLAB Function:rate_gate_10hz
      输出:send_flag(boolean/uint8)
      逻辑:每累计 10 次 tick(0.01×10=0.1s)输出一次 true
  • 2.4 条件触发发送(10Hz)

    • If Block
      输入:send_flag
      表达式:u1 ~= 0
      action 输出:
      true action → Send_Subsystem.ActionPort
      else action → Else_Subsystem.ActionPort
  1. 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)
  1. 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)。

  1. 基准步长(Fixed-step size)= 0.01s
    每步计算温度相关量:Tc(℃)、Vts(V)
    串口上传频率:10Hz(0.1s/帧)
  2. 按 VOFA+ JustFloat 协议发送两通道:
    CH1 = Tc(float32)
    CH2 = Vts(float32)
    帧尾 = 0x7F800000 小端:00 00 80 7F
  3. 协议与帧格式
    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 即可实现。

  1. 保持不变的部分

    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
  2. 需要修改的部分

    (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

相关推荐
无垠的广袤2 小时前
【FPB-RA6E2 开发板】Zephyr 物联网温湿度计
单片机·嵌入式硬件·物联网·瑞萨·传感器·dht11
lemoncat82 小时前
开源小工具推荐:立创3D模型快速下载
嵌入式硬件·pcb设计·pcb
兆龙电子单片机设计2 小时前
【STM32项目开源】STM32单片机智能家居语音控制系统
stm32·单片机·物联网·开源·毕业设计·智能家居
d111111111d2 小时前
STM32的ADC是什么,其转换精度通常有那些选项?
笔记·stm32·单片机·嵌入式硬件·学习
小刘爱玩单片机2 小时前
【stm32简单外设篇】- 红外避障 / 红外循迹模块
c语言·stm32·单片机·嵌入式硬件
恒锐丰小吕2 小时前
屹晶微 EG2130 带关断控制的高压半桥栅极驱动芯片技术解析
嵌入式硬件·硬件工程
森旺电子3 小时前
STM32内核中断和外设中断
stm32·单片机·嵌入式硬件·freertos
v先v关v住v获v取3 小时前
圆形通风管道灰尘清理机器人设计14张cad+三维图+设计说明书
科技·单片机·51单片机
一路往蓝-Anbo3 小时前
【第23期】资源保护:关中断 vs 互斥量 (Mutex)
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网