本节摘要:代码生成把模型翻译成"由调度器驱动的函数集合":初始化函数做一次性装配,步进函数按采样节拍重复执行,参数与接口按可配置的命名与存储规则落地。本节拆开这份翻译的规则书——模型语义到 C 结构的对应关系、连续状态的离散化处理、外部数据的接口方式——并用电机模型的生成代码做逐段导读。读完本节,"看不懂生成的代码"应成为过去式。
用第 4 章的电机模型生成一份代码,打开主文件,骨架无外乎四部分。头文件区:数据类型的别名、模型数据结构的声明。初始化函数:给状态变量赋初值、装配参数——与你在参数脚本和积分器对话框里写的东西一一对应。步进函数:控制算法的主体,由周期性的定时任务调用。数据接口区:输入输出信号、可调参数的 extern 声明,供上层软件框架集成。
导读可以从步进函数里的小林的控制律开始。离散 PI 在 2.2 节写成了位置式差分,生成的代码里它就是三行算术:取误差、更新积分累加量、限幅输出。每个变量都能在模型里找到本体:积分累加量对应离散积分器的状态、限幅常量对应饱和模块的参数、节拍常量对应采样时间。读懂一段生成代码所需的知识,你在第 2 章就全部学完了——所谓"看不懂",多数是没建立"代码元素到模型元素"的对照表。
/* 电机模型生成代码导读(节选,简化排版)*/ /* 对应模型:motor_speed_loop 节拍:1 ms 定时任务调用 */ void motor_speed_loop_step(void) { /* 离散PI:位置式差分,对应 2.2 节路线二 */ local_err = rtb_ref - rtb_speed_fb; /* 转速误差 */ integ += Ki * local_err; /* 积分累加:离散积分器状态 */ duty = Kp * local_err + integ; /* 比例加积分 */ duty = SAT(duty, DUTY_MIN, DUTY_MAX); /* 饱和模块:限幅 */ PWM_OUT = duty; /* 输出端口:占空比 */ } /* 参数区:链接到字典定义(6.1 节),可外部修改 */ extern real_T Kp; /* 比例增益,来自字典 motor_project.sldd */ extern real_T Ki; /* 积分增益 */

规则一:时间变节拍。 模型的仿真时间在代码里不存在,取而代之的是由外部定时器驱动的任务调度——每个离散速率对应一个周期任务。3.1 节"离散状态采样点更新"的循环语义,在代码里就是"节拍中断里调用步进函数"。连续状态在生成前必须离散化:求解器配置里的变步长算法换成离散积分方法(欧拉、后向欧拉或梯形),这一步是"模型可生成"的前提,也是 3.2 节"探路定步长"检查的原因。
规则二:状态变静态存储。 积分器状态、单位延迟的历史值,生成后是函数外的静态变量——生命周期横跨所有节拍。这意味着两件事:多实例化(同一算法驱动多台电机)需要走模型引用的实例化配置;状态复位语义(切断态下清积分)要在模型里显式建模,别指望代码自己明白。
规则三:参数变接口。 参数的落地形态由存储类决定:默认常量化(编译期定死,省 RAM 但不可调)、extern 化(链接到字典或外部定义,整机可标定)、或按项目自定义存储类归位到指定存储段。6.1 节字典里的每一个定义,在此兑现为可标定接口——数据治理与代码集成的闭环在这一刻合龙。
生成的算法代码要长进软件框架里,接口配置是主要工作。信号命名按项目规范映射(模块里的 duty 到代码里的全局变量名),数据类型与目标平台的 ABI 对齐,入口函数与框架的任务调度挂钩。工程实践中的默契分工:算法组交付"模型加生成代码加接口说明",软件组提供"框架壳与驱动层",双方在接口头文件上冻结契约——接口变更走评审,就像 2.4 节的总线契约一样。
⚠️ 常见坑:在模型里"顺手"用了仿真专用模块(文件读写、示波器悬空、随机数),生成时要么报错要么被静默剔除。生成导向的模型有一条卫生要求:仿真观测设施放在测试 harness 里,模型本体只含部署语义。
拿到一份生成的代码包,先认全文件角色再深入细节:主头文件声明模型数据结构与入口函数,是外部框架集成的唯一契约面;主源文件放着初始化与步进函数——8.1 节导读的对象;数据文件集中参数与常量的定义(存储类决定它们的落位);还有一份接口说明性质的文件汇总所有 extern 声明,软件组集成时主要看它。读懂这个构成,"交付什么"的沟通就有了共同语言。
可读性有两处值得配置的开关。保留模块名注释:生成的每段代码前带上来源模块名与子系统路径,代码回到模型的反向索引就有了——排查"这行代码哪来的"从半小时变成十秒。命名规则:信号与参数按项目规范映射命名(字典里的定义直接带过去),生成代码里的变量名与模型里的名字一致时,代码评审会上算法组与软件组才有共同语言。这两项配置不改变任何行为,属于纯赚的可读性投资。
数据接口的组织方式也影响集成顺畅度。默认的散装全局变量适合小模型;模型大了以后把接口聚合为结构体(一个输入结构、一个输出结构、一个参数结构),框架侧的集成从"接十几根线"变成"挂三个结构",8.3 节 HIL 接口配置的工作量也随之减半——接口组织是模型侧一小时、集成侧一天的杠杆位。
代码看懂了,下一站让它"跑得省":存储、体积与执行效率的优化实战。