精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

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

CHANBAEK ? 來源:安德魯的設計筆記本 ? 作者:安德魯蘇 ? 2023-06-16 10:52 ? 次閱讀

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

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

Overview

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

圖片

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

圖x完整展示了MATLAB從算法模型到可執行程序的各個環節:

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

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

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

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

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

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

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

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

MATLAB、Simulink、StateFlow、Real-Time Workshop之間的關系

MathWorks

?MATLAB 是一個集成開發環境,包含M語言的解析器,同時還提供多種特定應用的工具箱。

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

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

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

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

MATLAB Coder、Simulink Coder、Embedded Coder之間的關系

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

圖片

圖x MATLAB中的3中Coder生成器的關系

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

圖片

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

從MATLAB算法模型到C語言

此處,以實現一個流水燈的模型為例,說明基于模型設計的全過程。

在Simulink中配置模型的開發環境

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

圖片

圖x 在Simulink中打開配置參數對話框

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

圖片

圖x 在配置參數對話框中配置求解器

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

圖片

圖x 在配置參數對話框中配置硬件實現

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

圖片

圖x 在配置參數對話框中配置代碼生成

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

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

圖片

圖x 在Simulink中保存模型文件

在MATLAB中創建符號和框圖描述的算法模型

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

圖片

圖x plus-f5270開發板上的可編程LED燈

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

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

圖片

圖x leds_model模型的功能框圖

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

圖片

圖x 配置計數器的計時步長

此時,使用計數器控制小燈閃爍的流水燈模型就已經搭建完成。

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

圖片

圖x Simulink的仿真工具欄

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

圖片

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

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

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

經過仿真驗證的系統設計框圖,可以直接轉化成嵌入式系統可以可以執行的C程序源碼。在調用RTW編譯模型生成C源碼之前,必須再次確認幾個配置要點:

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

?配置求解器的計算步長,0.001s或者0.01s均可,可根據實際需要的計算時間精度設定,這個時間長度對應于嵌入式系統中部署模型時,周期調用求解器程序的中斷服務程序的周期。

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

圖片

圖x 在MATLAB中設定當前工作目錄

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

圖片

圖片

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

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

圖片

圖x Embedded Coder生成的C源碼

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

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

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

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

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

圖片

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

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

圖片

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

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

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

?不要添加模型的ert_main.c文件。Embedded Coder為模型生成的ert_main.c文件中,包含了在嵌入式環境中調用模型的參考用例,其中包含兩個重要的函數:一個是頂級調用main()函數,另一個是需要基于硬件定時器中實現的中斷回調函數rt_OneStep()。在ert_main.c文件中,有注釋對main()函數和rt_oneStep()函數的用法進行了詳細的解釋。見代碼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目錄下創建model_port.c文件,集中存放基于plus-f5270開發板適配leds_model模型的配置源碼。在model_port.c文件中創建model_init()函數,在頂級調用main()函數中將調用model_init()函數初始化并啟動模型求解器。同時,在model_port.c文件中創建model_input()和model_output()函數,用于同步模型同硬件的綁定關系。

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

使用硬件定時器調用求解器程序

在plus-f5270開發板上,選用硬件定時器TIM4產生周期為10ms的中斷服務程序,在中斷服務中周期調用模型生成的求解器處理函數,執行模型。

在model_init()函數中配置硬件定時器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()函數中調用TIM_Start()函數之后,硬件定時器開始工作,自動周期觸發定時器中斷服務,由硬件中斷服務程序自動周期調用模型生成的求解器程序leds_model_step()。在定時器中斷服務程序中調用求解器之前,需要手動執行在適配過程中創建的model_input()函數,將嵌入式平臺電子系統中的狀態量同步到模型內部的輸入變量中;在調用求解器之后,需要手動執行在適配過程中創建的model_output()函數,將模型求解器更新的輸出變量的狀態同步到嵌入式平臺電子系統中,控制電路完成相關的操作。

將模型的控制量同步到電路系統中

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

在model_port.c文件中的modelinit()函數中,添加配置GPIO引腳控制LED燈全部熄滅,在model_output()函數中,根據模型中表示LED燈狀態的變量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()函數的聲明。board_init.h文件也是main.c中包含硬件相關資源的統一入口,在適配模型的過程中所需要的其他軟硬件相關的組件,也都可以在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()函數中添加代碼,啟用GPIOB、GPIOC、GPIOD、GPIOI,以及TIM4外設模塊的總線時鐘。

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()函數中添加代碼,配置LED燈對應的PI0、PD2、PB14、PC9引腳的復用功能為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()函數中調用模型

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

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);
    }
}

編譯嵌入式工程并運行

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

圖片

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

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

圖片

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

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 微控制器
    +關注

    關注

    48

    文章

    7489

    瀏覽量

    151051
  • ARM
    ARM
    +關注

    關注

    134

    文章

    9046

    瀏覽量

    366820
  • matlab
    +關注

    關注

    182

    文章

    2963

    瀏覽量

    230167
  • C語言
    +關注

    關注

    180

    文章

    7598

    瀏覽量

    136200
  • Simulink
    +關注

    關注

    22

    文章

    522

    瀏覽量

    62307
收藏 人收藏

    評論

    相關推薦

    利用MATLABsimulink建立仿真模型

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

    如何利用MATLABsimulink建立仿真模型

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

    淺析MATLABSimulink嵌入式視覺應用

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

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

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

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

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

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

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

    MIMO-OFDM的matlabsimulink仿真程序或

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

    Matlab Simulink控制系統仿真

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

    基于MATLAB/simulink的直接轉矩控制離散仿真系統的研究分析

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

    如何使用S函數實現BP神經網絡PID控制器Simulink仿真的資料說明

    BP網絡人工神經網絡中應用最為廣泛,文中給出基于MATLAB語言的BP神經網絡PID控制器的S函數實,現,在此基礎上建立BP神經網絡PID控制器
    發表于 03-13 08:00 ?28次下載
    如何使用S函數實現BP神經網絡PID<b class='flag-5'>控制器</b>及<b class='flag-5'>Simulink</b><b class='flag-5'>仿真</b>的資料說明

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

    基于Matlab simulink的蓄電池雙向DCDC控制模型(5g電源技術要求)-該資料為基于Matlab
    發表于 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的工業自動化控制系統設計

    使用 MATLABSimulink,工程師可以創建物理系統的模型,開發控制和調度邏輯算法。然后,工程師可以仿真各種配置并執行多種測試。
    發表于 07-07 15:34 ?2364次閱讀

    simulink中搭建逆變器仿真模型

    逆變器仿真simulink中搭建了逆變器仿真模型,采用電壓電流雙閉環控制,采用LC濾波
    發表于 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工作流程

    電子發燒友網站提供《FPGA上部署5G NR無線通信:MATLABSimulink工作流程.pdf》資料免費下載
    發表于 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工作流程

    電子發燒友網站提供《FPGA上部署5G NR無線通信:MATLABSimulink工作流程.pdf》資料免費下載
    發表于 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>工作流程