tifmill 发表于 2024-11-22 11:03

单片机+Simulink开发方式

在simulink中搭建的LED闪烁的一个例子,相比之前C语言代码实现的方式,这里没有写一行代码就实现了LED闪烁。读者有没有感觉这种开发方式即简单又方便,要实现什么功能就直奔主题,不用一行一行的敲代码、排查代码错误。图1只是arduino其中的I/O输出外设,在图2中还有其它很多外设可以使用,再结合matlab强大的功能,读者可以实现很多实际应用。

https://cdn.nlark.com/yuque/0/2022/png/886964/1665414280576-72c3ed92-8604-4b37-acb9-b7d385a12b23.png?x-oss-process=image%2Fformat%2Cwebp

图1 Arduino-simulink的LED闪烁模型
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414347360-96c0dc20-bdf3-4b0d-adf0-326f8fa5d2e9.png?x-oss-process=image%2Fformat%2Cwebp

图2 simulink中arduino其它外设的模型

任意单片机基于模型开发方式
      并不是每一个芯片厂商都有足够的人力和资金投入到主流开发软件的生态适配,目前除了市面上用的比较火的几款单片机(STM32、TMS320F28xx、S32K等)和Arduino平台可以直接使用Matlab的硬件支持包直接开发外,其它单片机没办法直接使用,这里给大家介绍一种万能的方式,可以在任意单片机上使用基于Simulink模型开发方式。

1、8051单片机上运行Simulink模型代码

第1步:搭建Simulink模型
    如图3 所示,,这里使用了三个库,分别是“Delay(延时模型)”、“Logical Operator-NOT(逻辑操作-非模型)”和“out(输出端口模型)”,这里的输出端口为了方便代码移植将名字改为LED。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414567520-752dfe8b-a015-42c4-a160-8234fcbea9c8.png?x-oss-process=image%2Fformat%2Cwebp

图3 LED闪烁simulink模型

第2步:设置模型生成参数并生成代码
    如图4所示,点击https://cdn.nlark.com/yuque/0/2022/png/886964/1665414662990-268ad510-8eb4-4e3a-95de-7b811f315712.png?x-oss-process=image%2Fformat%2Cwebp
按钮“Model Configuration Parameters”对simulink进行设置。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414579937-0f48307c-fc7d-4cff-ae32-8015ceee16e1.png?x-oss-process=image%2Fformat%2Cwebp

图4 simulink设置按钮
如图5所示,在弹出的“Configuration Parameters:xxxx”窗口中找到“Solver”栏,并点击设置运行参数,按照图中的设置,完成后点击“Apply”。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414588499-47ef6933-32a3-44b6-bd0a-b79336a101a5.png?x-oss-process=image%2Fformat%2Cwebp

图5 “Solver”栏参数设置
如图6所示,在“Hardware Implementtation”栏中设置硬件参数,按照图中的设置进行操作,完成后点击“Apply”。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414596593-42320624-347a-4d88-ab96-7bfb76ae1626.png?x-oss-process=image%2Fformat%2Cwebp

图6 “Hardware Implementtation”栏参数设置
如图7所示,点击“Code Generation”栏,设置代码生成参数,完成后点击“Apply”。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414603709-9c4cd920-156d-42b8-a265-5af29d8d5b1a.png?x-oss-process=image%2Fformat%2Cwebp

图7 “Code Generation”参数设置
如图8所示,点开“Code Generation”左边的“>”符号,在子栏目中找到“Code Style”项设置代码生成风格,完成后点击“Apply”。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414610929-500d01c2-4615-4265-92a6-7d4a8b899c5c.png?x-oss-process=image%2Fformat%2Cwebp

图8 “Code Style”栏设置
如图9所示,点开“Code Generation”左边的“>”符号,在子栏目中找到“Code Placement”中设置“File packaging format”参数,完成后点击“Apply”,到这一步,所有参数都设置完成,然后点击“OK”按钮。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414619414-dade007b-5f06-47a0-a891-3cc86d265c22.png?x-oss-process=image%2Fformat%2Cwebp

图9 “Code Placement”栏设置
如图10所示,点击https://cdn.nlark.com/yuque/0/2022/png/886964/1665414719362-8764ccab-d7f1-444e-83a1-4e09ea929ea0.png?x-oss-process=image%2Fformat%2Cwebp
按钮“Build Model”生成代码。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414739288-434803be-9c64-45d1-bc05-89efa100f8e7.png?x-oss-process=image%2Fformat%2Cwebp

图10 点击生成模型代码
代码生成根据电脑性能不同,需要的时间也不一样,稍等一会儿,弹出“Code Generation Report”窗口报告,如图11所示,在这个窗口中可以看到整个模型生成了三个文件,分别是“ert_main.c”、"LED_Blink.c"和"LED_Blink.h",然后在LED_Blink.slx文件所在的目录下多了一个“LED_Blink_ert_rtw”名字的文件夹,生成的三个文件也包含在当中;看这三个代码有点像之前讲的模块化编程方式命名。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414747174-9f2a9ee6-e9a1-4bd9-a627-819b90bfa5a4.png?x-oss-process=image%2Fformat%2Cwebp

图11 LED_Blink模型代码生成报告

第3步:将simulink生产的代码添加到8051单片机工程中
      这一步也是整个过程中最关键部分,也是在很多资料中一直没讲清楚的部分,将生成的代码移植到51单片机工程中去。先新建一个名字(其它名字也可以,只要正确建立Keil工程即可)为“LED_Blink”的Keil工程,工程的存放路径放在刚刚模型生成代码"Blink→LED_Blink_ert_rtw“文件夹下,如图12所示。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414754414-6f56a4a2-cb73-41b1-9608-dffd2f28cae3.png?x-oss-process=image%2Fformat%2Cwebp

图12 在生成模型文件夹下建一个Keil工程
打开刚刚建立的Keil工程,将ert_main.c和LED_Blink.c文件添加到”Source Group 1“中,如图13所示。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665414761237-11fa53e4-ecc2-41d1-bc7b-7e19f796c70d.png?x-oss-process=image%2Fformat%2Cwebp

图13 模型代码添加
      在刚刚添加的文件中双击打开ert_main.c,在下面代码位置处加入8051单片机的内容,代码如下所示:

添加单片机代码
然后在ert_main.c文件中添加定时器初始化代码,如下所示:

在ert_main.c中编写定时器中断代码,如下所示:

定时器中断函数代码
在main主函数中对代码进行修改,如下所示:

main函数中代码

第4步:编译Keil工程并运行代码
      点击Keil编译按钮编译代码,然后将代码烧录到实际芯片中或使用Pretous仿真验证代码。到这里大家就完成了在51单片机上实现LED闪烁Simulink模型代码移植的例子,LED闪烁的频率实际由宏定义#define LED_TASK_TIME 500来控制,在8051单片机上运行该代码时LED将以500ms的周期翻转。

2、simulink生成模型代码剖析
      关于8051单片机怎么搭建简单操作系统框架可以参考网络上其他文章或关注作者的后续文章,这里就不再赘述,如图14所示的LED闪烁模型,实际上就是运行模型生成的rt_OneStep()函数,每个Simulink生成的模型里面都会有这个函数,rt_OneStep()运行完之后所有通过输入端的数据都会在搭建的模型逻辑中处理,然后通过输出端输出处理完后的数据,在LED闪烁模型中,没有输入端,只有输出端,所以模型每运行完一次,里面的逻辑翻转一次输出端口LED状态,即LED_Blink_Y.LED的数据,然后只需将模型输出端口与实际物理端口关联即可,这里关联的是P1_0端口,则最终表现出来的效果就是P1_0状态,即模型每运行一次,P1_0端口电平发生一次翻转,P1_0端口有连接LED,LED就会一直闪烁。
https://cdn.nlark.com/yuque/0/2022/png/886964/1665415773837-19d26425-4bd6-4498-8635-29b8c09e7830.png?x-oss-process=image%2Fformat%2Cwebp

图14 基于模型LED程序执行流程
      下面再深入到rt_OneStep()函数详细了解下它到底在里面做了什么事情,是不是与前面所说的一致,rt_OneStep()函数详细内容,函数中的其它内容暂时不管,可以看到里面关键的一步,调用了LED_Blink_step()函数,具体代码如下所示:

C


rt_OneStep(void)
{
    static boolean_T OverrunFlag = false;

    /* Disable interrupts here */

    /* Check for overrun */
    if (OverrunFlag) {
      rtmSetErrorStatus(LED_Blink_M, "Overrun");
      return;
    }

    OverrunFlag = true;

    /* Save FPU context here (if necessary) */
    /* Re-enable timer or interrupt here */
    /* Set model inputs here */

    /* Step the model */
    LED_Blink_step();

    /* Get model outputs here */

    /* Indicate task complete */
    OverrunFlag = false;

    /* Disable interrupts here */
    /* Restore FPU context here (if necessary) */
    /* Enable interrupts here */
}



      然后再到LED_Blink_step()函数中查看具体内容,在主函数中调用的LED_Blink_Y.LED在该函数中可以找到具体的逻辑。至此,LED闪烁模型的整个代码分析完成。其它模型也可以采用类似的方式来分析,具体代码如下所示:

LED_Blink_step(void)
{
    boolean_T rtb_Delay;

    /* Delay: '<Root>/Delay' */
    rtb_Delay = LED_Blink_DW.Delay_DSTATE[0];

    /* Outport: '<Root>/LED' incorporates:
   *Delay: '<Root>/Delay'
   */
    LED_Blink_Y.LED = LED_Blink_DW.Delay_DSTATE[0];

    /* Update for Delay: '<Root>/Delay' incorporates:
   *Logic: '<Root>/Logical Operator'
   */
    LED_Blink_DW.Delay_DSTATE[0] = LED_Blink_DW.Delay_DSTATE[1];
    LED_Blink_DW.Delay_DSTATE[1] = !rtb_Delay;
}



页: [1]
查看完整版本: 单片机+Simulink开发方式