欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

在ARM微控制器上部署MATLAB/Simulink仿真模型

CHANBAEK ? 來源:安德魯?shù)脑O(shè)計筆記本 ? 作者:安德魯蘇 ? 2023-06-16 10:52 ? 次閱讀

本文在于記錄使用Simulink建模仿真,到最終部署到微控制器上的過程。從Simulink算法模型到目標硬件平臺可以支持的可執(zhí)行文件,大體經(jīng)過Matlab的各種模型描述語言,編譯成通用C語言,再在目標硬件平臺的編譯環(huán)境中編譯生成最終的可執(zhí)行文件。市面上的相關(guān)的學(xué)術(shù)研究和實踐經(jīng)驗,大多是使用了MATLAB已經(jīng)官方認證集成的BSP,例如:ArduinoTI DSP、STM32、樹莓派等,在這些工具包的加持下,MATLAB配合具體的目標平臺的集成開發(fā)環(huán)境,可以一通到底。但實際上,MATLAB只要在將Simulink工具描述的算法模型轉(zhuǎn)化成C語言,完全可以由開發(fā)者自行進一步適配的具體平臺,而不需要依賴于具體的官方認證的設(shè)備支持包。更進一步,適用于Arm兼容的微控制器,MATLAB已經(jīng)集成了一個通用的模板,在將MATLAB算法語言轉(zhuǎn)化成C語言的過程中特別考慮在嵌入式平臺上執(zhí)行的代碼優(yōu)化。

本文詳細演繹了從Simulink創(chuàng)建模型,仿真驗證,之后再生成C源碼部署到plus-f5270開發(fā)板的全過程。其中描述的方法和操作步驟,為后續(xù)部署更多仿真模型奠定了基礎(chǔ)。

Overview

從Simulink中以符號圖形和算法框圖表示的仿真模型,轉(zhuǎn)化成可編譯的C源碼,再到可以運行在嵌入式平臺的可執(zhí)行程序,經(jīng)歷了多個階段的處理,在每個階段需要對應(yīng)的工具,將上一階段的輸出文件作為本階段的輸入,經(jīng)過處理后再輸出給后續(xù)的環(huán)節(jié)。

圖片

圖x 從Matlab模型到目標平臺可執(zhí)行文件

圖x完整展示了MATLAB從算法模型到可執(zhí)行程序的各個環(huán)節(jié):

?使用MATLAB、Simulink和Stateflow工具可以在MATLAB中創(chuàng)建模型,此時的模型可能是以邏輯圖符號的方式表示,保存成model.mdl文件

?RealTime Workshop(RTW)是MATLAB中的一個工具,是用來做仿真的軟件開發(fā)環(huán)境,可以使用描述模型符號及其邏輯關(guān)系的model.mdl文件作為輸入,經(jīng)過本地編譯,形成描述模型的model.rtw文件。RTW文件是以ASCII碼的形式存放,開發(fā)者可以直接讀其中的內(nèi)容。

–TLC目標語言編譯器(Target Language Compiler)是生成C源碼的關(guān)鍵環(huán)節(jié)。TLC目標語言編譯器也是RTW的一部分,可以讀取model.rtw文件

–中的信息,將模型轉(zhuǎn)化成源代碼的描述。TLC目標語言編譯器可以輸出成多種語言,例如M語言、VHDL語言等,C語言是其中的一種選項。生成C語言也可以使用不同的模板,以約束生成代碼的組織方式和風(fēng)格,例如,一般實時目標使用grt.tlc模板,嵌入式實時目標使用ert.tlc模板。

–使用RTW生成源碼,還有更多靈活的操作,例如,使用配置宏觀代碼框架的系統(tǒng)TLC文件和配置單個模塊的模塊TLC文件,直接用函數(shù)源碼定義算法模塊的S-Function等。RTW不能轉(zhuǎn)換S-Function的代碼,需要開發(fā)者手寫代碼嵌入到生成代碼中。

–RTW還能根據(jù)makefile的模板文件,生成可適用于目標硬件平臺編譯環(huán)境的makefile文件model.mk。但這個不是必須的,如果某些集成開發(fā)環(huán)境沒有適配到MATLAB中,就需要手動添加生成的源文件到對應(yīng)的集成開發(fā)環(huán)境當中。

?通過TLC目標語言編譯器生成的C源碼文件model.c文件,可以直接加入到嵌入式系統(tǒng)的集成開發(fā)環(huán)境當中(例如Keil)參與編譯。但實際上,這里生成的C源碼文件主要是描述算法的實現(xiàn),是應(yīng)用程序的框架,仍需要開發(fā)者在具體嵌入式硬件平臺上,結(jié)合實際應(yīng)用,手動向其中嵌入具體的輸入輸出函數(shù)。

?MATLAB的工具生成算法執(zhí)行的源碼框架,配合目標嵌入式硬件平臺的適配移植,最終在嵌入式硬件平臺的編譯環(huán)境中完成編譯鏈接,最終生成可以在目標嵌入式硬件平臺上運行的可執(zhí)行文件。后續(xù)可以使用目標嵌入式硬件平臺的一般操作過程完成下載和調(diào)試。

MATLAB、Simulink、StateFlow、Real-Time Workshop之間的關(guān)系

MathWorks

?MATLAB 是一個集成開發(fā)環(huán)境,包含M語言的解析器,同時還提供多種特定應(yīng)用的工具箱。

?Simulink 是集成在 MATLAB 中的眾多工具箱的一個,作為建模、分析和仿真的交互環(huán)境。

?Stateflow 是Simulink中的一個功能組件,通過狀態(tài)圖執(zhí)行選項拓展了 Simulink 的功能,使得可編程的狀態(tài)圖也能作為Simulink仿真系統(tǒng)中的一個組件。

?Real-Time Workshop 在早期版本的MATLAB中曾經(jīng)作為一個獨立的組件,但后來并入Simulink工具箱中,可用于從Simulink模型生成優(yōu)化的、可移植的和可定制的ANSIC代碼。利用它可以針對某種目標平臺(例如嵌入式平臺)或是部分子系統(tǒng)可下載執(zhí)行的C代碼,以展開硬件在回路仿真。

?Simulink Coder即是之前的 Real-Time Workshop 和 StateflowCoder,可以從 Simulink 框圖和 Stateflow 系統(tǒng)以及 TargetLink 模型中自動生成 C 代碼。

MATLAB Coder、Simulink Coder、Embedded Coder之間的關(guān)系

Mathworks公司的MATLAB軟件環(huán)境中有3個代碼生成工具:Matlab Coder、Simulink Coder和Embedded Coder。MATLAB可以將M語言轉(zhuǎn)化成目標代碼,Simulink Coder可以將Simulink中的仿真模型轉(zhuǎn)化成目標代碼,而Embedded Coder 依賴于MATLAB Coder以及Simulink Coder的,通過進一步優(yōu)化,主要生成用于部署在嵌入式平臺上的源碼。

圖片

圖x MATLAB中的3中Coder生成器的關(guān)系

考慮最終將生成的C代碼部署到嵌入式平臺上,從MATLAB程序和從Simulink模型生成源碼的工具流有一些區(qū)別,如圖x所示。

圖片

圖x MATLAB中多種Coder生成器的工作流

從MATLAB算法模型到C語言

此處,以實現(xiàn)一個流水燈的模型為例,說明基于模型設(shè)計的全過程。

在Simulink中配置模型的開發(fā)環(huán)境

在MATLAB中啟動Simulink后,可通過工具欄的“建?!?>“模型設(shè)置”,激活“配置參數(shù)”對話框。如圖x所示。

圖片

圖x 在Simulink中打開配置參數(shù)對話框

在“配置參數(shù)”對話框中,首先配置“求解器”。求解器是Simulink用數(shù)值方法結(jié)算模型切片狀態(tài)的引擎,對應(yīng)于Simulink的仿真過程的行為。這里考慮將來是在嵌入式系統(tǒng)中作為周期任務(wù)更新求解過程,設(shè)定在Simulink的仿真行為同嵌入式系統(tǒng)類似,為“離散”的“固定步長”,計算步長的時間為10ms,對應(yīng)于配置對話框中的0.01s。如圖x所示。在實際的嵌入式系統(tǒng)平臺運行求解器時,將使用一個硬件定時器,以10ms的周期觸發(fā)中斷,執(zhí)行求解器的程序。

圖片

圖x 在配置參數(shù)對話框中配置求解器

在“配置參數(shù)”對話框的“硬件實現(xiàn)”標簽中,選擇即將生成代碼的目標平臺??紤]到未來將會在ARM微控制器的平臺上部署(但不在Simulink的支持設(shè)備清單中),這里將“設(shè)備供應(yīng)商”選擇為“ARM Compatible”,選擇“設(shè)備”類型為“ARM Cortex-M”。特別注意將“Code Generation system target file”選擇成為“ert.tlc”,這是最終生成C語言的配置文件。

圖片

圖x 在配置參數(shù)對話框中配置硬件實現(xiàn)

實際上,在配置TLC時,配置參數(shù)對話框會自動切換到“代碼生成”頁面,在這里選擇使用etc.tlc文件。如圖x所示。

圖片

圖x 在配置參數(shù)對話框中配置代碼生成

從圖x中可以看到,Simulink提供了多種TLC配置文件可選。這里選擇的ert.tlc,是專門適用于Embedded Coder生成嵌入式系統(tǒng)C代碼的。

配置好項目之后,保存模型文件到文件系統(tǒng)中。從圖x中可以看到,Simulink保存的模型文件可以有兩種后綴名,一種是“.slx”,另一種是“.mdl”,這里,我們使用默認的“.slx”文件后綴名,保存成“leds_model.slx”文件。

圖片

圖x 在Simulink中保存模型文件

在MATLAB中創(chuàng)建符號和框圖描述的算法模型

在plus-f5270開發(fā)板上設(shè)計了4個可編程的LED燈,有原理圖如圖x所示。

圖片

圖x plus-f5270開發(fā)板上的可編程LED燈

這里要設(shè)計一個邏輯,用一個計數(shù)器驅(qū)動小燈的亮暗狀態(tài),當計數(shù)器輸出0時,控制僅LED1亮,當計數(shù)器輸出1時,控制僅LED2亮,以此類推。計數(shù)器從0到3周期計數(shù),小燈也依次閃爍。

在“庫瀏覽器”中選擇需要的符號元件,拖放到繪圖工作區(qū)中,例如,常量“Constant”、等于號“Equal”、有限計數(shù)器“Counter Limited”、輸出端點“Out”等,并可用示波器“Scope”和顯示器“Display”查看仿真輸出結(jié)果。使用連線,將符號的輸入輸出信號連接在一起,形成一個有輸入輸出的完整系統(tǒng)的功能框圖。如圖x所示。

圖片

圖x leds_model模型的功能框圖

從圖x中可以看出,計數(shù)器的輸出值驅(qū)動4個LED燈的亮暗狀態(tài)。但默認情況下,計數(shù)器的計數(shù)節(jié)奏是同求解器的計算步長保持一致的,如之前設(shè)定求解器的計算步長是10ms,這就意味著這些小燈會閃爍得非常快,難以被人眼觀察到。這里希望調(diào)整計數(shù)器的計數(shù)節(jié)奏為1m,需要調(diào)整計數(shù)器的計數(shù)節(jié)奏。雙擊計數(shù)器的圖標,可以激活計數(shù)器模塊的參數(shù)配置對話框,配置其中的“采樣時間”值為1。如圖x所示

圖片

圖x 配置計數(shù)器的計時步長

此時,使用計數(shù)器控制小燈閃爍的流水燈模型就已經(jīng)搭建完成。

在仿真的工具欄中,點擊“步進”即可逐步運行,點擊“運行”可以全速仿真運行。如圖x所示。

圖片

圖x Simulink的仿真工具欄

啟動仿真后,可以通過系統(tǒng)框圖中的示波器模塊查看仿真結(jié)果,如圖x所示。

圖片

圖x leds_model模型中的示波器模塊顯示仿真結(jié)果

從圖x中顯示的示波器輸出波形可以看到,4個輸出通道以1s為控制節(jié)奏,依次輸出高電平。驗證仿真結(jié)果達到預(yù)期設(shè)計。

使用TLC目標語言編譯器生成描述算法的C源碼

經(jīng)過仿真驗證的系統(tǒng)設(shè)計框圖,可以直接轉(zhuǎn)化成嵌入式系統(tǒng)可以可以執(zhí)行的C程序源碼。在調(diào)用RTW編譯模型生成C源碼之前,必須再次確認幾個配置要點:

?配置模型使用ert.tlc,這是專用于嵌入式系統(tǒng)平臺的目標語言編譯器配置選項。

?配置求解器的計算步長,0.001s或者0.01s均可,可根據(jù)實際需要的計算時間精度設(shè)定,這個時間長度對應(yīng)于嵌入式系統(tǒng)中部署模型時,周期調(diào)用求解器程序的中斷服務(wù)程序的周期。

?在MATLAB的主窗口切換當前工作目錄到指定的項目錄下。如圖x所示。即將生成的C代碼工程將位于這里指定的目錄下。

圖片

圖x 在MATLAB中設(shè)定當前工作目錄

然后,試著生成C源碼。在Simulink的界面中,在工具欄“APP”頁面中選擇“Embedded Coder”激活“C代碼”標簽頁,然后在“C代碼”標簽頁中其中選擇“生成待代碼”。如圖x所示。

圖片

圖片

圖x 在Simulink中使用Embedded Coder生成C代碼

此時,Simulink的目標語言編譯器TLC將啟動編譯,并生成C源碼程序文件。如圖x所示。

圖片

圖x Embedded Coder生成的C源碼

至此,在Simulink中調(diào)用Embedded Coder,已經(jīng)將創(chuàng)建的leds_model模型轉(zhuǎn)化成了C源碼,保存在一系列源碼文件中。此時,可以在預(yù)先設(shè)定的當前工作目錄中,找到新建保存生成源碼文件的文件夾“l(fā)eds_model_ert_rtw”,顧名思義:leds_model是模型的名字;ert是Embedded Real-Time Target,對應(yīng)源碼生成器的配置選項;rtw是Real-Time Workshop,這是源碼生成器的工具包,在MATLAB的早期版本中獨立作為一個工具包,現(xiàn)在已經(jīng)被集成在源碼生成器內(nèi)部。

將模型C源碼集成到嵌入式平臺工程

集成模型C源碼碼到Keil工程中

這里準備了一個plus-f5270開發(fā)板上可以運行的工程,plus-f5270_hello_world_mdk,作為部署模型的基礎(chǔ)。

首先,將工程的目錄名改為“plus-f5270_leds_model_mdk” ,便于標識該工程專用于部署leds_model模型。在該工程根目錄下創(chuàng)建“model”目錄,將由Embedded Coder生成的模型C源碼文件全部復(fù)制到其中。此時,工程目錄的源碼結(jié)構(gòu)如圖x所示。

圖片

圖x 將生成的模型源碼文件復(fù)制到Keil工程目錄下

然后,在Keil工程中添加模型源碼,先試著編譯一下,驗證模型文件本身源碼的完整性。如圖x所示。

圖片

圖x 在Keil中編譯包含模型源碼的工程

經(jīng)編譯驗證可知,模型源碼本身是閉包無誤的,不會為基礎(chǔ)工程引入額外的錯誤,也不需要專門針對嵌入式編譯環(huán)境調(diào)整任何源碼。在Keil中編譯模型文件需要注意:

?需要在Keil工程中為新加入的模型源碼添加源文件搜索路徑。

?不要添加模型的ert_main.c文件。Embedded Coder為模型生成的ert_main.c文件中,包含了在嵌入式環(huán)境中調(diào)用模型的參考用例,其中包含兩個重要的函數(shù):一個是頂級調(diào)用main()函數(shù),另一個是需要基于硬件定時器中實現(xiàn)的中斷回調(diào)函數(shù)rt_OneStep()。在ert_main.c文件中,有注釋對main()函數(shù)和rt_oneStep()函數(shù)的用法進行了詳細的解釋。見代碼x所示。

代碼x Embedded Coder為leds_model生成的ert_main.c文件

/*
* File: ert_main.c
*
* Code generated for Simulink model 'leds'.
*
* Model version                  : 1.4
* Simulink Coder version         : 9.8 (R2022b) 13-May-2022
* C/C++ source code generated on : Mon Dec 19 18:09:56 2022
*
* Target selection: ert.tlc
* Embedded hardware selection: ARM Compatible- >ARM Cortex-M
* Code generation objectives: Unspecified
* Validation result: Not run
*/


#include 
#include             /* This example main program uses printf/fflush */
#include "leds_model.h"                      /* Model header file */


/*
* Associating rt_OneStep with a real-time clock or interrupt service routine
* is what makes the generated code "real-time".  The function rt_OneStep is
* always associated with the base rate of the model.  Subrates are managed
* by the base rate from inside the generated code.  Enabling/disabling
* interrupts and floating point context switches are target specific.  This
* example code indicates where these should take place relative to executing
* the generated code step function.  Overrun behavior should be tailored to
* your application needs.  This example simply sets an error status in the
* real-time model and returns from rt_OneStep.
*/
void rt_OneStep(void);
void rt_OneStep(void)
{
  static boolean_T OverrunFlag = false;


  /* Disable interrupts here */


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


  OverrunFlag = true;


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


  /* Step the model */
  leds_model_step();


  /* Get model outputs here */


  /* Indicate task complete */
  OverrunFlag = false;


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


/*
* The example main function illustrates what is required by your
* application code to initialize, execute, and terminate the generated code.
* Attaching rt_OneStep to a real-time clock is target specific. This example
* illustrates how you do this relative to initializing the model.
*/
int_T main(int_T argc, const char *argv[])
{
  /* Unused arguments */
  (void)(argc);
  (void)(argv);


  /* Initialize model */
  leds_model_initialize();


  /* Attach rt_OneStep to a timer or interrupt service routine with
   * period 0.001 seconds (base rate of the model) here.
   * The call syntax for rt_OneStep is
   *
   *  rt_OneStep();
   */
  printf("Warning: The simulation will run forever. "
         "Generated ERT main won't simulate model step behavior. "
         "To change this behavior select the 'MAT-file logging' option.\\n");
  fflush((NULL));
  while (rtmGetErrorStatus(leds_model_M) == (NULL)) {
    /*  Perform application tasks here */
  }


  /* Terminate model */
  leds_model_terminate();
  return 0;
}


/*
* File trailer for generated code.
*
* [EOF]
*/

在嵌入式工程中適配模型

在plus-f5270工程的boards目錄下創(chuàng)建model_port.c文件,集中存放基于plus-f5270開發(fā)板適配leds_model模型的配置源碼。在model_port.c文件中創(chuàng)建model_init()函數(shù),在頂級調(diào)用main()函數(shù)中將調(diào)用model_init()函數(shù)初始化并啟動模型求解器。同時,在model_port.c文件中創(chuàng)建model_input()和model_output()函數(shù),用于同步模型同硬件的綁定關(guān)系。

Note:在模型中使用的輸入和輸出,都是保存在內(nèi)存中的數(shù)據(jù)。在微控制器芯片內(nèi)部的電路系統(tǒng)中,通過訪問地址映射空間中的寄存器,控制的狀態(tài)和行為。在面向嵌入式平臺設(shè)計的仿真系統(tǒng)中,生成的C源碼,是不會直接控制具體嵌入式平臺的電路系統(tǒng)的。這個比較好理解,因為仿真系統(tǒng)是同一份,但運行在不同的嵌入式平臺上,對應(yīng)的寄存器是不同的。這就需要嵌入式平臺的開發(fā)者自行適配代碼,將電路系統(tǒng)中狀態(tài)量和控制量,與仿真模型的輸入和輸出進行同步。

使用硬件定時器調(diào)用求解器程序

在plus-f5270開發(fā)板上,選用硬件定時器TIM4產(chǎn)生周期為10ms的中斷服務(wù)程序,在中斷服務(wù)中周期調(diào)用模型生成的求解器處理函數(shù),執(zhí)行模型。

在model_init()函數(shù)中配置硬件定時器TIM4的代碼如下:

/* model_port.c */
#include "board_init.h"


#include 
#include             /* This example main program uses printf/fflush */
#include "leds_model.h"                      /* Model header file */


extern void leds_model_initialize(void);
extern void leds_model_step(void);


void model_init(void)
{
    /* prepare the models. */
    leds_model_initialize();

    /* setup timer. */
    TIM_Init_Type tim_init;
    tim_init.ClockFreqHz = BOARD_MODEL_TIMER_CLKSRC_HZ;
    tim_init.StepFreqHz = 1000000; /* 1mhz per step. */
    tim_init.Period = 10000; /* 100hz for a round. */
    tim_init.EnablePreloadPeriod = true;
    tim_init.PeriodMode = TIM_PeriodMode_Continuous;
    tim_init.CountMode = TIM_CountMode_Increasing;
    TIM_Init(BOARD_MODEL_TIMER_PORT, &tim_init);

    /* enable interrupt. */
    NVIC_EnableIRQ(BOARD_MODEL_TIMER_NVIC_IRQn);
    TIM_EnableInterrupts(BOARD_MODEL_TIMER_PORT, TIM_INT_UPDATE_PERIOD, true);

    /* start timer. */
    TIM_Start(BOARD_MODEL_TIMER_PORT);
}


/* bind the model input to hardware. */
void model_input(void)
{
}


/* bind the model output to hardware. */
void model_output(void)
{
}


/* hardware timer interrupt for model solver. */
void BOARD_MODEL_TIMER_NVIC_IRQHandler(void)
{
    uint32_t flags = TIM_GetInterruptStatus(BOARD_MODEL_TIMER_PORT);

    if (flags & TIM_STATUS_UPDATE_PERIOD)
    {
        model_input();
        leds_model_step(); /* call the model solver step by step. */
        model_output();
    }

    TIM_ClearInterruptStatus(BOARD_MODEL_TIMER_PORT, flags);
}
/* EOF. */

當在model_init()函數(shù)中調(diào)用TIM_Start()函數(shù)之后,硬件定時器開始工作,自動周期觸發(fā)定時器中斷服務(wù),由硬件中斷服務(wù)程序自動周期調(diào)用模型生成的求解器程序leds_model_step()。在定時器中斷服務(wù)程序中調(diào)用求解器之前,需要手動執(zhí)行在適配過程中創(chuàng)建的model_input()函數(shù),將嵌入式平臺電子系統(tǒng)中的狀態(tài)量同步到模型內(nèi)部的輸入變量中;在調(diào)用求解器之后,需要手動執(zhí)行在適配過程中創(chuàng)建的model_output()函數(shù),將模型求解器更新的輸出變量的狀態(tài)同步到嵌入式平臺電子系統(tǒng)中,控制電路完成相關(guān)的操作。

將模型的控制量同步到電路系統(tǒng)中

具體在本例中使用定時器控制LED燈,僅需要在model_output()函數(shù)中實現(xiàn)根據(jù)模型輸出狀態(tài)控制LED燈的亮暗狀態(tài)。但嵌入式平臺進行編程時需要注意,使用GPIO控制LED燈之前,需要對將要使用到的GPIO硬件資源預(yù)先初始化,配置好對應(yīng)的外設(shè)時鐘、引腳復(fù)用功能,以及初始狀態(tài)等。

在model_port.c文件中的modelinit()函數(shù)中,添加配置GPIO引腳控制LED燈全部熄滅,在model_output()函數(shù)中,根據(jù)模型中表示LED燈狀態(tài)的變量leds_model_Y.ledn(n=1, 2, 3, 4)配置到控制LED燈的GPIO引腳輸出信號上。

void model_init(void)
{
    ...
    /* setup leds. */
    GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, 1u);
    GPIO_WriteBit(BOARD_LED2_GPIO_PORT, BOARD_LED2_GPIO_PIN, 1u);
    GPIO_WriteBit(BOARD_LED3_GPIO_PORT, BOARD_LED3_GPIO_PIN, 1u);
    GPIO_WriteBit(BOARD_LED4_GPIO_PORT, BOARD_LED4_GPIO_PIN, 1u);
    ...
}


/* bind the model output to hardware. */
void model_output(void)
{
    GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, (leds_model_Y.led1?0u:1u) );
    GPIO_WriteBit(BOARD_LED2_GPIO_PORT, BOARD_LED2_GPIO_PIN, (leds_model_Y.led2?0u:1u) );
    GPIO_WriteBit(BOARD_LED3_GPIO_PORT, BOARD_LED3_GPIO_PIN, (leds_model_Y.led3?0u:1u) );
    GPIO_WriteBit(BOARD_LED4_GPIO_PORT, BOARD_LED4_GPIO_PIN, (leds_model_Y.led4?0u:1u) );
}

在board_init.h文件中定義LED和硬件定時器的具體資源,并添加對model_init()函數(shù)的聲明。board_init.h文件也是main.c中包含硬件相關(guān)資源的統(tǒng)一入口,在適配模型的過程中所需要的其他軟硬件相關(guān)的組件,也都可以在board_init.h文件的頭部聲明引用。

#ifndef __BOARD_INIT_H__
#define __BOARD_INIT_H__


#include 
#include 


#include "hal_common.h"
#include "hal_rcc.h"
#include "hal_uart.h"
#include "hal_tim.h"
#include "hal_gpio.h"


#include "clock_init.h"
#include "pin_init.h"


/* DEBUG UART. */
#define BOARD_DEBUG_UART_PORT        UART1
#define BOARD_DEBUG_UART_BAUDRATE    115200u
#define BOARD_DEBUG_UART_FREQ        CLOCK_APB2_FREQ


/* leds. */
#define BOARD_LED1_GPIO_PORT         GPIOI
#define BOARD_LED1_GPIO_PIN          GPIO_PIN_0
#define BOARD_LED2_GPIO_PORT         GPIOD
#define BOARD_LED2_GPIO_PIN          GPIO_PIN_2
#define BOARD_LED3_GPIO_PORT         GPIOB
#define BOARD_LED3_GPIO_PIN          GPIO_PIN_14
#define BOARD_LED4_GPIO_PORT         GPIOC
#define BOARD_LED4_GPIO_PIN          GPIO_PIN_9


/* model timer. */
#define BOARD_MODEL_TIMER_PORT       (TIM_Type *)TIM4
#define BOARD_MODEL_TIMER_CLKSRC_HZ  CLOCK_APB1_FREQ
#define BOARD_MODEL_TIMER_NVIC_IRQn  TIM4_IRQn
#define BOARD_MODEL_TIMER_NVIC_IRQHandler TIM4_IRQHandler


void BOARD_Init(void);
void model_init(void);


#endif /* __BOARD_INIT_H__ */

在clock_init.c文件中的BOARD_InitBoardClocks()函數(shù)中添加代碼,啟用GPIOB、GPIOC、GPIOD、GPIOI,以及TIM4外設(shè)模塊的總線時鐘。

void BOARD_InitBootClocks(void)
{
    CLOCK_ResetToDefault();
    CLOCK_BootToHSE120MHz();


    /* UART1. */
    RCC_EnableAPB2Periphs(RCC_APB2_PERIPH_UART1, true);
    RCC_ResetAPB2Periphs(RCC_APB2_PERIPH_UART1);


    /* GPIOB. */
    RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOB, true);
    RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOB);

    /* GPIOC. */
    RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOC, true);
    RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOC);

    /* GPIOD. */
    RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOD, true);
    RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOD);

    /* GPIOI. */
    RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOI, true);
    RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOI);

    /* TIM4. */
    RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_TIM4, true);
    RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_TIM4);
}

在pin_init.c文件中的BOARD_InitPins()函數(shù)中添加代碼,配置LED燈對應(yīng)的PI0、PD2、PB14、PC9引腳的復(fù)用功能為GPIO輸出。

void BOARD_InitPins(void)
{
    /* PB7 - UART1_TX. */
    GPIO_Init_Type gpio_init;
    gpio_init.Pins  = GPIO_PIN_6;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull; //GPIO_PinMode_AF_PushPull
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_7);


    /* PB6 - UART1_RX. */
    gpio_init.Pins  = GPIO_PIN_7;
    gpio_init.PinMode  = GPIO_PinMode_In_Floating; //GPIO_PinMode_In_Floating
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_7);

    /* PI0 - led1. */
    gpio_init.Pins  = GPIO_PIN_0;
    gpio_init.PinMode  = GPIO_PinMode_Out_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOI, &gpio_init);
    GPIO_PinAFConf(GPIOI, gpio_init.Pins, GPIO_AF_15);


    /* PD2 - led2. */
    gpio_init.Pins  = GPIO_PIN_2;
    gpio_init.PinMode  = GPIO_PinMode_Out_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &gpio_init);
    GPIO_PinAFConf(GPIOD, gpio_init.Pins, GPIO_AF_15);

    /* PB14 - led3. */
    gpio_init.Pins  = GPIO_PIN_14;
    gpio_init.PinMode  = GPIO_PinMode_Out_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_15);


    /* PC9 - led4. */
    gpio_init.Pins  = GPIO_PIN_9;
    gpio_init.PinMode  = GPIO_PinMode_Out_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &gpio_init);
    GPIO_PinAFConf(GPIOC, gpio_init.Pins, GPIO_AF_15);
}
在main()函數(shù)中調(diào)用模型

模型的求解器是由硬件定時器中斷自動觸發(fā)執(zhí)行的,除了模型的初始化函數(shù)mode_init()之外,不需要嵌入式平臺的開發(fā)者在main() 函數(shù)中人為調(diào)用任何模型生成的函數(shù),并且也不影響原有程序的正常執(zhí)行。實際上,本例工程中的main.c,在原有hello_world工程的main.c中,僅添加了一行model_init()函數(shù)的調(diào)用。

int main(void)
{
    uint8_t ch;


    BOARD_Init();
    printf("hello, world\\r\\n");


    /* init & start the model solver. */
    model_init();


    while (1)
    {
        ch = getchar();
        putchar(ch);
    }
}

編譯嵌入式工程并運行

在嵌入式平臺上編譯工程和下載的操作同一般嵌入式開發(fā)無異。在Keil中編譯,下載可執(zhí)行程序到plus-f5270開發(fā)板中。

圖片

圖x 在Keil中編譯包含模型源碼的嵌入式工程

下載可執(zhí)行程序到到開發(fā)板上,運行,可以觀察到開發(fā)板上的4個LED小燈以1s為節(jié)奏演示流水燈的效果。如圖x所示。

圖片

圖x 在plus-f5270上部署leds_model模型

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 微控制器
    +關(guān)注

    關(guān)注

    48

    文章

    7658

    瀏覽量

    152172
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9177

    瀏覽量

    369372
  • matlab
    +關(guān)注

    關(guān)注

    186

    文章

    2981

    瀏覽量

    231062
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7614

    瀏覽量

    137801
  • Simulink
    +關(guān)注

    關(guān)注

    22

    文章

    536

    瀏覽量

    62712
收藏 人收藏

    評論

    相關(guān)推薦

    利用MATLABsimulink建立仿真模型

    利用MATLABsimulink建立仿真模型,與stm32cubemx搭建數(shù)據(jù)鏈,通過simulink搭建的
    發(fā)表于 08-17 07:11

    如何利用MATLABsimulink建立仿真模型

    如何利用MATLABsimulink建立仿真模型呢?并與stm32cubemx搭建數(shù)據(jù)鏈呢?
    發(fā)表于 11-18 07:17

    淺析MATLABSimulink嵌入式視覺應(yīng)用

    MATLABSimulink 工具,為嵌入式視覺系統(tǒng)設(shè)計算法和系統(tǒng)模型。借助用于采集攝像機和其他傳感實時圖像和視頻數(shù)據(jù)的應(yīng)用程序,以及用于處理、分析、
    發(fā)表于 12-04 08:00

    介紹STM32cubeIDE上部署AI模型的系列教程

    介紹STM32cubeIDE上部署AI模型的系列教程,開發(fā)板型號STM32H747I-disco,值得一看。MCUAI原文鏈接:【嵌入式AI開發(fā)】篇四|部署篇:STM32cubeID
    發(fā)表于 12-14 09:05

    Arm虛擬硬件上部署PP-PicoDet模型

    1、Arm虛擬硬件上部署PP-PicoDet模型  經(jīng)典的深度學(xué)習(xí)工程是從確認任務(wù)目標開始的,我們首先來簡單地介紹一下目標檢測任務(wù)以及本期部署
    發(fā)表于 09-16 14:42

    如何將ML模型部署微控制器?

    大家好,的我正在嘗試將 ML 模型部署微控制器,我有兩塊 STM32L4R9I-Discovery 和 STM32H7B3I-Discovery 板。實驗及相關(guān)結(jié)果如下所示:我使用 TFLite
    發(fā)表于 12-29 13:09

    MIMO-OFDM的matlabsimulink仿真程序或

    MIMO-OFDM的matlabsimulink仿真程序或模型(有OFDM的simulink仿真
    發(fā)表于 02-08 14:38 ?540次下載

    Matlab Simulink控制系統(tǒng)仿真

    Matlab Simulink控制系統(tǒng)仿真》,感興趣的小伙伴們可以看看。
    發(fā)表于 08-09 17:33 ?82次下載

    基于MATLAB/simulink的直接轉(zhuǎn)矩控制離散仿真系統(tǒng)的研究分析

    SIMUUNK是MATLAB提供用來對動態(tài)系統(tǒng)進行建模、仿真、分析的軟件包。SIMULINK包含許多模塊庫,利用這些模塊庫可以很方便的進行復(fù)雜系統(tǒng)構(gòu)建與仿真分析,為研究者提供了一個實用
    的頭像 發(fā)表于 10-17 07:57 ?5020次閱讀
    基于<b class='flag-5'>MATLAB</b>/<b class='flag-5'>simulink</b>的直接轉(zhuǎn)矩<b class='flag-5'>控制</b>離散<b class='flag-5'>仿真</b>系統(tǒng)的研究分析

    如何使用S函數(shù)實現(xiàn)BP神經(jīng)網(wǎng)絡(luò)PID控制器Simulink仿真的資料說明

    BP網(wǎng)絡(luò)人工神經(jīng)網(wǎng)絡(luò)中應(yīng)用最為廣泛,文中給出基于MATLAB語言的BP神經(jīng)網(wǎng)絡(luò)PID控制器的S函數(shù)實,現(xiàn),在此基礎(chǔ)上建立BP神經(jīng)網(wǎng)絡(luò)PID控制器
    發(fā)表于 03-13 08:00 ?28次下載
    如何使用S函數(shù)實現(xiàn)BP神經(jīng)網(wǎng)絡(luò)PID<b class='flag-5'>控制器</b>及<b class='flag-5'>Simulink</b><b class='flag-5'>仿真</b>的資料說明

    基于Matlab simulink的蓄電池雙向DCDC控制模型

    基于Matlab simulink的蓄電池雙向DCDC控制模型(5g電源技術(shù)要求)-該資料為基于Matlab
    發(fā)表于 09-28 11:02 ?86次下載
    基于<b class='flag-5'>Matlab</b> <b class='flag-5'>simulink</b>的蓄電池雙向DCDC<b class='flag-5'>控制</b><b class='flag-5'>模型</b>

    基于MATLABSimulink的工業(yè)自動化控制系統(tǒng)設(shè)計

    使用 MATLABSimulink,工程師可以創(chuàng)建物理系統(tǒng)的模型,開發(fā)控制和調(diào)度邏輯算法。然后,工程師可以仿真各種配置并執(zhí)行多種測試。
    發(fā)表于 07-07 15:34 ?2612次閱讀

    simulink中搭建逆變器仿真模型

    逆變器仿真simulink中搭建了逆變器仿真模型,采用電壓電流雙閉環(huán)控制,采用LC濾波
    發(fā)表于 02-28 15:32 ?12次下載
    <b class='flag-5'>在</b><b class='flag-5'>simulink</b>中搭建逆變器<b class='flag-5'>仿真</b><b class='flag-5'>模型</b>

    FPGA上部署5G NR無線通信:MATLABSimulink工作流程

    電子發(fā)燒友網(wǎng)站提供《FPGA上部署5G NR無線通信:MATLABSimulink工作流程.pdf》資料免費下載
    發(fā)表于 09-14 09:42 ?0次下載
    <b class='flag-5'>在</b>FPGA<b class='flag-5'>上部署</b>5G NR無線通信:<b class='flag-5'>MATLAB</b>與<b class='flag-5'>Simulink</b>工作流程

    FPGA上部署5G NR無線通信:MATLABSimulink工作流程

    電子發(fā)燒友網(wǎng)站提供《FPGA上部署5G NR無線通信:MATLABSimulink工作流程.pdf》資料免費下載
    發(fā)表于 09-13 11:24 ?1次下載
    <b class='flag-5'>在</b>FPGA<b class='flag-5'>上部署</b>5G NR無線通信:<b class='flag-5'>MATLAB</b>與<b class='flag-5'>Simulink</b>工作流程