• 252查看
  • 0回复

[应用层软件] 使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示

[复制链接]


该用户从未签到

发表于 10-4-2024 21:58:12 | 显示全部楼层 |阅读模式

汽车零部件采购、销售通信录       填写你的培训需求,我们帮你找      招募汽车专业培训老师


实验环境

Matlab版本:2023b

操作系统:Win10专业版

硬件平台:YF-STM32-ALPHA 1R5
      实验内容:使用 Constant 变量控制 S-Function Builer 模块数码管显示数字 0~F
使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w1.jpg

模型与原理图

     本次实验效果如图 5.1 所示,改变“Constant”变量值可以控制数码管的数字显示,所用到的simulink模型如图5.2所示,电路原图如图5.3所示。

使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w2.jpg

图 5.1 使用自建模型驱动数码管效果

使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w3.jpg

图 5.2  I2C 自建数码管驱动模型

使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w4.jpg

图 5.3 数码管原理图



基础模型介绍与分析

       如图 5.4 所示为拖入 simulink 工程中的“S-Function Builder”函数,通过在里面添加 C /C++ 语言语句就可以帮助我们实现相应功能,对于习惯于使用 C /C++ 语言用户的 来说,这无疑是非常方便的,"S-Function Builder"模型在库中的位置如图 5.5 所示。

使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w6.jpg

图 5.4 “S-Function Builder” 模型

使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w7.jpg

图 5.5 “S-Function Builder” 模型位置

       双击“S-Function Builder”模型,弹出如图 5.6 所示窗口,在“S-Function 名称”中填入名字“CH422G”,注意该名字不要与 本工程 xxx.slx 名字同名,然后将“语言”设置为“C++”(这是因为本次使用的接口函数底层使用 C ++编写),右侧的离散状态的树木设置为“1”,采样模式设置为“Discrete”,”采样时间值“设置为“0.01”,将最下边不用的端口删除,并对照着将“名称”和“数据类型”进行设置,其它保持默认即可。

⚠️注 意:由于 mbed-os 部分代码使用 C++编写,“语言”栏一定要设置为“C++”,否则在 simulink 中编译时会报莫名其妙的错误。

使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w8.jpg

图 5.6 “S-Function Builder”窗口参数设置

     接下来我们往 “编辑器”中添加代码,完整代码如下所示,看起来感觉有点复杂,其实我们实际使用中不用关注那么多,根据实际需要操作其中部分内容即可。

⚠️注 意:在 S-Function Builder 编辑代码时,实际可改动的位置为/* xxx_BEGIN */     /* xxx_END */中间部分,读者朋友如果更改其它地方,可能会出现编辑不了的情况。
/* Includes_BEGIN */#include <math.h>
#ifndef MATLAB_MEX_FILE
#include <mbed.h>
I2C i2c1(PB_11, PB_10);  
char BCD_decode_tab[ 0x10 ] = { 0X3F, 0X06, 0X5B, 0X4F, 0X66, 0X6D, 0X7D, 0X07, 0X7F, 0X6F, 0X77, 0X7C, 0X58, 0X5E, 0X79, 0X71 };   // unsigned char cnt = 0;  // 定义计数变量char *seg_ptr;          // 定义指针变量
#endif/* Includes_END */
/* Externs_BEGIN *//* extern double func(double a); *//* Externs_END */
void CH422G_Start_wrapper(real_T *xD){    /* Start_BEGIN */    /* * 此处显示自定义开始代码。 */    /* Start_END */}
void CH422G_Outputs_wrapper(const uint8_T *NMU,const real_T *xD){    /* Output_BEGIN */    #ifndef MATLAB_MEX_FILE    seg_ptr = BCD_decode_tab + NMU[0];    i2c1.write(0x60,seg_ptr,1);    #endif    /* 此示例将输出设置为等于输入 y0[0] = u0[0];  对于复信号,使用: y0[0].re = u0[0].re;  y0[0].im = u0[0].im; y1[0].re = u1[0].re; y1[0].im = u1[0].im; */    /* Output_END */}
void CH422G_Update_wrapper(const uint8_T *NMU,real_T *xD){    /* Update_BEGIN */    if(xD[0] !=1 )    {        #ifndef MATLAB_MEX_FILE        char cmd[2];
        /* 输出引脚 OC3~OC0 开漏输出使能 */        cmd[0] = 0x01;        i2c1.write(0x48,cmd,1);  // 往地址0x48设置0x01值
        /* 使OC3~OC0引脚输出低电平*/        cmd[0] = 0x00;        i2c1.write(0x44,cmd,1);
        cmd[0] = 0x00;        i2c1.write(0x46,cmd,1);        #endif    }
    /* Update_END */}
void CH422G_Terminate_wrapper(real_T *xD){    /* Terminate_BEGIN */    /* * 此处显示自定义终止代码。 */    /* Terminate_END */}
第一部分:头文件包含,与 C /C++ 语言中使用方法类型,本次实验因为用到 mbed-os 框架的接口函数,所以我们需要添加 mbed.h 头文件,其余部分跟使用 C /C++ 语言方式 操作方式 差不多。注意添加的代码需要使用#ifndef MATLAB_MEX_FILE    #endif 将添加内容包含起来。
/* Includes_BEGIN */#include <math.h>
#ifndef MATLAB_MEX_FILE
#include <mbed.h>
I2C i2c1(PB_11, PB_10);  
char BCD_decode_tab[ 0x10 ] = { 0X3F, 0X06, 0X5B, 0X4F, 0X66, 0X6D, 0X7D, 0X07, 0X7F, 0X6F, 0X77, 0X7C, 0X58, 0X5E, 0X79, 0X71 };   // unsigned char cnt = 0;  // 定义计数变量char *seg_ptr;          // 定义指针变量
#endif/* Includes_END */
第二部分:初始化,这部分用于初始化变量或驱动芯片,代码如下所示,同样需要将内容放置#ifndef MATLAB_MEX_FILE    #endif 中,示例代码中初始化 CH422 芯片的内部寄存器设置。
void CH422G_Update_wrapper(const uint8_T *NMU,real_T *xD){    /* Update_BEGIN */    if(xD[0] !=1 )    {        #ifndef MATLAB_MEX_FILE        char cmd[2];
        /* 输出引脚 OC3~OC0 开漏输出使能 */        cmd[0] = 0x01;        i2c1.write(0x48,cmd,1);  // 往地址0x48设置0x01值
        /* 使OC3~OC0引脚输出低电平*/        cmd[0] = 0x00;        i2c1.write(0x44,cmd,1);
        cmd[0] = 0x00;        i2c1.write(0x46,cmd,1);        #endif    }
    /* Update_END */}
第三部分:实际运行交互内容,这里面用于实际要控制或操作的内容,示例代码中接收“NMU”数据,然后通过 I2C 接口写入芯片驱动数码管显示对应数字。
void CH422G_Outputs_wrapper(const uint8_T *NMU,const real_T *xD){    /* Output_BEGIN */    #ifndef MATLAB_MEX_FILE    seg_ptr = BCD_decode_tab + NMU[0];    i2c1.write(0x60,seg_ptr,1);    #endif    /* 此示例将输出设置为等于输入    /* Output_END */}
        以上内容设置好后,需要对代码进行进行编译包装,在编译器设置中只需勾选“生成 TLC 包装”即可,其它根据实际需求选择,然后点击编译,右侧编译日志会显示是否编译成功。

使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w9.jpg

图 5.5 “S-Function Builder”编译设置及编译成功效果

       回到 simulink 窗口中,我们可以看到“S-Function Builder”名字发生了改变,并且有一个输入端口“NMU”,如图 5.6 所示,往模型中 添加一个 "Constant"变量就可以控制显示数码管数字,其它 simulink 设置参考之前文章,这里就不再赘述。

使用Simulink学习STM32-(9)S-Function 调用外部C/C++ 模块 I2C 数码管显示w10.jpg

图 5.6 设置并编译好的自定义模型



✏️总结

        本节实验中我们通过添加一个自定义的“S-Function Builder”模型,然后在其中添加 mbed-os 接口函数从而实现驱动 I2C 数码管驱动芯片显示对应数字,这对于使用 simulink 提供了一定的灵活度,并且后期的外部 开源驱动模块都可以通过该方式引入到 simulink 中来,还是非常方便的。

快速发帖

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|Archiver|汽车工程师之家 ( 渝ICP备18012993号-1 )

GMT+8, 1-2-2025 07:54 , Processed in 0.236855 second(s), 31 queries .

Powered by Discuz! X3.5

© 2001-2013 Comsenz Inc.