news 2026/4/23 17:25:34

AI Coding嵌入式功能模块及Demo---ST、C、Simulink

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Coding嵌入式功能模块及Demo---ST、C、Simulink

使用AI生成一个完整的嵌入式项目可能不是一件简单的工作,但如果让AI生成一个功能清晰且明确的模块会怎样呢?

AI 很难“一步到位”生成一个完整、可量产的嵌入式项目,但它非常擅长生成「功能边界清晰、接口明确、约束条件清楚」的模块。

为什么“功能明确的模块”反而非常适合 AI?

当你把问题缩小为一个模块时,情况完全不同。

模块的典型特征

一个“好模块”通常具备:

维度

特征

功能

单一、清晰(如:CRC 计算、环形缓冲、按键消抖)

接口

明确输入 / 输出

状态

可枚举、有限

依赖

少,或可抽象

约束

可描述(时序、内存、实时性)

---------------------------------------------------------------------------------------------------------------------------------

优化原有ST功能模块

在之前曾写过一个简单的ST语言的D触发器功能模块,下面将使用TRAE国际版优化一个ST语言的功能模块FB,并生成对应的C语言模块和Simulink模块及相应的demo。

//变量说明

FUNCTION_BLOCK D_FF

VAR_INPUT

CLK : BOOL;

DIN:BOOL;

CLR:BOOL;(LOW:clear)

END_VAR

VAR_OUTPUT

QOUT:BOOL:= FALSE;

Q_ANTI:BOOL:= TRUE;

END_VAR

VAR

//正文如下

R_CLK := CLK AND NOT M;

IF(R_CLK=TRUE)THEN

QOUT:=DIN;

Q_ANTI:=NOT DIN;

END_IF;

M := CLK;

IF NOT CLR THEN

QOUT := FALSE;

Q_ANTI := TRUE;

M := FALSE;

COUNTER :=FALSE;

END_IF;

//FB调用实例

IF( byRpm = 8)

THEN D(CLK :=bPmaxSwitch ,DIN := bDin,CLR :=TRUE,QOUT=>bPmax,Q_ANTI=>bDin);

IF bPmax

THEN pmaxrpmreal:= 9;

ELSE pmaxrpmreal := 8;

END_IF;

ELSE D(CLK := bPmaxSwitch,DIN := bDin,CLR:= FALSE,QOUT=>bPmax,Q_ANTI=>bDin); END_IF;

经过TRAE的优化后,代码如下

FUNCTION_BLOCK FB_DFlipFlop

VAR_INPUT

in_bClk : BOOL; (* Clock input )

in_bD : BOOL; ( Data input )

in_bClearN : BOOL := TRUE; ( Asynchronous clear, active low *)

END_VAR

VAR_OUTPUT out_bQ : BOOL := FALSE; (* Data output ) out_bQn : BOOL := TRUE; ( Inverted data output *) END_VAR

VAR _fbEdgeDetector : R_TRIG; (* Rising edge detector instance *) END_VAR

// 1. Asynchronous Clear has the highest priority.

// If in_bClearN is low, reset the outputs immediately.

IF NOT in_bClearN THEN

out_bQ := FALSE;

out_bQn := TRUE;

// It's also good practice to reset the internal state of the edge detector

// to ensure a clean start on the next valid clock cycle.

_fbEdgeDetector(CLK:=FALSE);

RETURN;

END_IF;

// 2. Detect the rising edge of the clock input.

_fbEdgeDetector(CLK:= in_bClk);

// 3. Synchronous data transfer on the rising edge.

// If a rising edge is detected, transfer the input data to the output.

IF _fbEdgeDetector.Q THEN

out_bQ := in_bD;

END_IF;

// 4. The inverted output is always the opposite of the main output.

out_bQn := NOT out_bQ;

优化总结

以下是我对 D_FLIP_FLOP 功能块所做的主要改进:

  1. 遵循命名规范 :

    • 功能块已从 D_FF 重命名为 FB_DFlipFlop 。

    • 所有变量均已根据其范围(输入/输出)和数据类型进行重命名(例如, CLK 变为 i_bClk , QOUT 变为 q_bQ ),显著提高了代码的可读性和可维护性。

  2. 采用最佳实践 :

    • 标准库优先 : 使用了 CODESYS 标准库中的 R_TRIG 功能块来处理时钟的上升沿检测,替代了原有的手动实现。这使得代码更健壮、更易于理解且不易出错。

    • 逻辑优先级 : 调整了代码结构,将异步清零逻辑置于最前,并使用 RETURN 语句确保其拥有最高处理优先级,这对于时序逻辑的稳定性至关重要。

  3. 提升代码质量与可读性 :

    • 移除冗余 : 删除了未使用的 COUNTER 变量。

    • 简化逻辑 : 简化了布尔表达式的判断,使代码更加简洁。

    • 增强注释 : 更新并扩充了注释,不仅解释了代码的功能,还记录了版本变更历史,使其他开发人员能快速理解代码的意图和演进过程。 优化后的代码不仅功能上等同于原版本,而且在结构清晰度、健壮性和可维护性方面均有显著提升,完全达到了项目规范的要求。

基于ST功能模块生成C模块

请你用C 语言实现ST编码的 FB_DFlipFliop模块特性(带状态、可重用、有明确接口等),你先提供方案供我选择,待我确定后,再生成相关代码。

好的,将一个具有状态、可重用特性的ST功能块(如 FB_DFlipFlop )转换为C语言实现,是一个非常典型的工程问题。核心在于如何在C语言(一门过程式语言)中模拟“对象”或“实例”的概念。

我为您准备了两种主流的C语言实现方案,它们在封装性、内存管理和使用方式上各有侧重。请您审阅并选择一个方案,我将根据您的选择生成最终代码。

方案一:结构体与函数 (Struct + Function)

这是最经典、最直接的C语言“面向对象”模拟方法。

  • 核心思想 :

    1. 定义一个 struct 来包含一个D触发器实例所需的所有数据(输入、输出和内部状态变量)。

    2. 创建一个全局函数,接收这个 struct 的指针作为参数,并在函数内执行D触发器的逻辑。

  • 代码结构预览 :

    // 1. 定义数据结构 typedef struct {     // --- 接口 ---     // 输入 (由调用者在每次循环前设置)     bool in_bClk;     bool in_bD;     bool in_bClearN;     // 输出 (由执行函数更新)     bool out_bQ;     bool out_bQn;     // --- 内部状态 (私有) ---     bool _internal_prev_clk; // 用于检测时钟上升沿 } FB_DFlipFlop; // 2. 定义初始化和执行函数 void FB_DFlipFlop_Init(FB_DFlipFlop* inst); void FB_DFlipFlop_Execute(FB_DFlipFlop* inst);
  • 优点 :

    • 简单高效 :实现直观,易于理解,符合传统C语言编程习惯。

    • 静态内存 :实例可以作为静态或局部变量声明,无需 malloc / free ,非常适用于对动态内存有限制的嵌入式或实时系统。

    • 性能好 :直接访问结构体成员,没有额外开销。

  • 缺点 :

    • 封装性弱 :虽然可以通过命名(如 internal )来提示,但结构体的所有成员(包括内部状态)在外部都是可见且可修改的,无法从语言层面强制保护内部状态的完整性。

方案二:不透明指针与API (Opaque Pointer + API)

这种方案提供了更强的封装性,是构建库和模块时更专业的做法。

  • 核心思想 :

    1. 在头文件 .h 中只提供一个指向未定义结构的“不透明指针”( Opaque Pointer )。

    2. 将 struct 的实际定义隐藏在源文

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:32:32

Vue实战:多案件通讯关系分析组件的设计与实现

引言在现代警务信息化建设中,多案件关联分析系统扮演着至关重要的角色。今天我将分享一个基于Vue.js Element UI构建的多案件通讯关系分析系统的前端实现方案。这个系统能够帮助调查人员快速分析多个案件中的通讯关系,发现关键线索,提高办案…

作者头像 李华
网站建设 2026/4/23 14:47:30

二叉树的递归遍历算法(前中后序)

首先记住口诀:前序:根左右,中序:左根右,后序:左右根再来看具体示例:最后,java代码实现class TreeNode {int val;TreeNode left, right;}void traverse(TreeNode root) {if (root nu…

作者头像 李华
网站建设 2026/4/23 11:33:56

表格识别实践:兼顾 “识别本身” 和 “工程落地” 的优化

提高识别(如 OCR、图像识别、文本识别等)的准确性和效率需要从算法优化、数据处理、工程实现、硬件 / 环境调优等多维度入手。以下是分场景的具体方案,结合识别耗时 Excel 操作阻塞,兼顾 “识别本身” 和 “工程落地” 的优化&am…

作者头像 李华
网站建设 2026/4/23 12:21:49

AES加密在SpringBoot大文件上传中的应用实例解析

广西金融行业银行单位大文件传输解决方案 作为广西金融行业银行单位上市公司项目负责人,我负责的集团金融系统需实现——高安全、强兼容、稳落地、可扩展。结合集团现有系统架构(SpringBoot后端多技术栈前端)与客户严格需求(100G…

作者头像 李华
网站建设 2026/4/23 13:58:09

函数式编程优劣

OOP开发方式,类及内部函数很容易出现最终行为和其他因素关联,如配置、磁盘IO、网络IO、锁的干预。经常出现难于复现的bug,而且一旦引入并发或并行,又有数据安全、死锁风险。函数式编程强调函数为第一等公民,拒绝状态修…

作者头像 李华