サンプルプログラム NF446RE_UART1 の説明
マスコット   UART(非同期シリアル通信)の
 サンプルプログラムです。

  STMicroelectronics社製の
 評価用基板、NUCLEO-F446RE と
 freeの開発ツール、STM32CubeIDE
 使用しています。

  STM32F446RE の USART1 を使用して、
 UARTの送受信を行うプログラムです。


目次

UART(非同期シリアル通信)について

サンプルプログラム NF446RE_UART1 のソース

サンプルプログラム NF446RE_UART1 の説明
 NF446RE_UART1 の構成
 NF446RE_UART1 の動作パラメータの定義
 ユーザープログラムの実行開始位置
 NF446RE_UART1 のmain()の説明
  1) 初期化の部分
  2) LED点滅 と UART1通信処理 の部分

 UART1通信処理 Commu_UART1 の説明

PCアプリケーション Access_UART
 サンプルプログラム NF446RE_UART1 を試験するためのPCアプリケーションです。



  このサンプルプログラムは、えがおのでんし製の試験用基板
  Base-N446RE と UART-CMOS基板 および UART-RS232C基板 を
 使用して動作を確認しています。

動作試験用基板 Base_N446RE の説明

動作試験用基板 UART基板 の説明



UART(非同期シリアル通信)について
 以下のページでUARTについて簡単に説明しています。
 UART(非同期シリアル通信) の説明 をご覧ください。


サンプルプログラム NF446RE_UART1 のソース
 STM32CubeIDE 1.8.0 を使用して作成しました。
 ここからサンプルプログラム R_NF446RE_UART1.zip をダウンロードしてください。



サンプルプログラム NF446RE_UART1 の説明
  STM32F446REのUART1の通信を行うプログラムです。
  PCが送信したコマンドを受信して、コマンドに応じてLEDの点滅間隔を変化させます。

 プロジェクトを最初に開いた画面は以下のようになります。

UART1_Scrn_First

 以下、サンプルプログラム NF446RE_UART1 について説明していきます。



 NF446RE_UART1 の構成
  STM32CubeIDEの画面左側、Project Explorerの
 NF446RE_UART1を展開した画面は以下のようになります。

UART1_Tree

  サンプルプログラム NF446RE_UART1 の構成を以下に示します。

NF446RE_UART1
  |- Includes
  |
  |- Access_UART_LED : 受信コマンド実行
  |    |-Access_UART_LED.c
  |    |-Access_UART_LED.h
  |
  |- Blk_LED_Stat : Status LED点滅処理
  |    |-Blk_LED_Stat.c
  |    |-Blk_LED_Stat.h
  |
  |- Commu_UART1 : UART1通信処理
  |    |-Commu_UART1.c
  |    |-Commu_UART1.h
  |
  |- Core
  |    |- Inc
  |    |    |- main.h
  |    |    |- stm32f4xx_hal_conf.h
  |    |    |- stm32f4xx_it.h
  |    |
  |    |- Src
  |    |    |- main.c
  |    |    |- stm32f4xx_hal_msp.c
  |    |    |- stm32f4xx_it.c
  |    |    |- syscalls.c
  |    |    |- system.c
  |    |    |- system_stm32f4xx.c
  |    |
  |    |- Startup
  |
  |- Drivers
  |
  |- H_F4_UART1 : UART1ハンドラ
  |    |- H_F4_UART1.c
  |    |- H_F4_UART1.h
  |
  |- Handle_F4 : 周辺インターフェース処理
  |    |- H_F4_GPIO.c
  |    |- H_F4_GPIO.h
  |
  |- NF446RE_UART1_Config : 動作パラメータの定義
  |    |- Dev_Conf.h
  |
  |- Wait_Itvl : 時間待ち処理
  |    |- Wait_Itvl.c
  |    |- Wait_Itvl.h
  |
  |- NF446RE_UART1.launch
  |- STM32F446RETX_FLASH.ld
  |- STM32F446RETX_RAM.ld



 NF446RE_UART1 の動作パラメータの定義
  サンプルプログラム NF446RE_UART1 の 動作パラメータの定義を
  NF446RE_UART1_Config/Dev_Conf.h に記述しています。

  使用する CPU の定義、ヘッダ名の定義、GPIO のポートとピンの定義、
 などを記述しています。



 ユーザープログラムの実行開始位置
  プログラムは、int main(void) から実行開始します。

  int main(void) は、フォルダ Core/Src/main.c にあります。

UART1_main

  STM32CubeIDEでビルドされたプログラムは、自動的にCPUの初期化を
 行った後、int main(void) を呼び出します。

  ユーザーコード(記述したプログラム)は、
 int main(void) の先頭から実行されます。



 NF446RE_UART1 のmain()の説明
  サンプルプログラム NF446RE_UART1 の main() の記述は、
 以下のとおりです。


/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  uint8_t uint8_JobNum_LED = 0;   // LED点滅処理番号
  uint8_t uint8_JobNum_UART = 0;  // UART処理番号

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    //------------------------------------------------------
    // Status LED点滅 : 初期化内蔵
    //------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号を格納する変数のポインタ
    // uint16_t uint16_Time_ON  : 点灯時間
    // uint16_t uint16_Time_OFF : 消灯時間

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG
    //------------------------------------------------------
    Blk_LED_Stat_with_Init(&uint8_JobNum_LED,
                           GLB_uint16_Time_LED_Stat_ON, GLB_uint16_Time_LED_Stat_OFF);


    //------------------------------------------------------------
    // UART1通信処理
    //------------------------------------------------------------
    // 処理内容 :

    //  1. UART1の初期化がされていない場合、初期化します。
    //  2. 受信が発生するのを待ち、受信データを取得します。
    //  3. 受信データを判定して、内容に従い処理を行います。
    //  4. 受信データによる処理の結果、送信データがセットされた場合、送信処理を行います。
    //------------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //------------------------------------------------------------
    Commu_UART1(&uint8_JobNum_UART);
  }
  /* USER CODE END 3 */
}


 1) 初期化の部分

  a) CPUのPeripheral初期化
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
   により、CPUのPeripheralなどの基本的な初期化を行います。
  PeripheralとはCPUの周辺インターフェースなどのことを言います。

   プロジェクト構築時に自動的に組み込まれる、
  HAL Drivers(フォルダ Drivers/STM32F4xx_HAL_Drivers) 内に記述されています。


  b) CPU動作クロックの設定
  /* Configure the system clock */
  SystemClock_Config();

   CPUの動作クロックとPeripheralの動作クロックを設定します。

   SystemClock_Config(); の設定内容は、

int main(void)
{
         .
         .
         .
}
 の、すぐ下に記述されています。



 2) LED点滅 と UART1通信処理 の部分
   永久ループ部分の記述を以下に示します。


  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    //------------------------------------------------------
    // Status LED点滅 : 初期化内蔵
    //------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号を格納する変数のポインタ
    // uint16_t uint16_Time_ON  : 点灯時間
    // uint16_t uint16_Time_OFF : 消灯時間

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG
    //------------------------------------------------------
    Blk_LED_Stat_with_Init(&uint8_JobNum_LED,
                           GLB_uint16_Time_LED_Stat_ON, GLB_uint16_Time_LED_Stat_OFF);


    //------------------------------------------------------------
    // UART1通信処理
    //------------------------------------------------------------
    // 処理内容 :

    //  1. UART1の初期化がされていない場合、初期化します。
    //  2. 受信が発生するのを待ち、受信データを取得します。
    //  3. 受信データを判定して、内容に従い処理を行います。
    //  4. 受信データによる処理の結果、送信データがセットされた場合、送信処理を行います。
    //------------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //------------------------------------------------------------
    Commu_UART1(&uint8_JobNum_UART);
  }
  /* USER CODE END 3 */

  Status LED点滅処理 Blk_LED_Stat_with_Init と UART1通信処理 Commu_UART1 を呼び出しています。
  Commu_UART1 では、コマンドを受信して、コマンドの内容に応じて
 LEDの点滅時間変更を行います。



 UART1通信処理 Commu_UART1 の説明
  データを受信して、LED点滅コマンドの場合、コマンドの内容に応じて、LEDの点滅間隔を変更します。
  受信したデータはエコーバックされます。

  LED点滅コマンドは以下の通りです。
LED1 B0%00 : 1000mSec 点灯 / 2000mSec 消灯
LED1 B1%00 : 100mSec 点灯 / 100mSec 消灯
LED1 B2%00 : 200mSec 点灯 / 200mSec 消灯
LED1 B3%00 : 300mSec 点灯 / 300mSec 消灯
LED1 B4%00 : 400mSec 点灯 / 400mSec 消灯
LED1 B5%00 : 500mSec 点灯 / 500mSec 消灯
  %00 は 0x00 を表します。

  以下に、Commu_UART1 のコードを示します。
//------------------------------------------------------------
// UART1通信処理
//------------------------------------------------------------
// 処理内容 :

//  1. UART1の初期化がされていない場合、初期化します。
//  2. 受信が発生するのを待ち、受信データを取得します。
//  3. 受信データを判定して、内容に従い処理を行います。
//  4. 受信データによる処理の結果、送信データがセットされた場合、送信処理を行います。
//------------------------------------------------------------
// 引数:
// uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

// 戻り値:
//    -1 : 処理中
//    0 : OK終了
//    1 : NG終了
//------------------------------------------------------------
int16_t Commu_UART1(uint8_t *puint8_JobNum)
{
  static uint8_t STC_uint8_JobNum_UART;

  int16_t int16_ReceiveLength;

  int16_t int16_Return;


  switch(*puint8_JobNum)
  {
  case 0:
    if(GLB_int16_vUART1_InitDone == 0){
      //-----------------------------------------------------------
      // UART1通信パラメータ初期化
      //-----------------------------------------------------------
      // 引数:
      // uint32_t uint32_BaudRate : 通信速度
      //-----------------------------------------------------------
      Init_Commu_UART1((uint32_t)115200);
    }


    STC_uint8_JobNum_UART = 0;  // UART処理番号初期化


    (*puint8_JobNum)++;  // 次の処理番号に移行する。: case 1:
    int16_Return = -1;   // 処理継続
    break;

  case 1:
    //--------------------------------------------------
    // UART1 受信処理
    //--------------------------------------------------
    // 戻り値:
    //    -2 : エラー発生
    //    -1 : 受信なし
    //     0 : 受信なし
    // 1以上 : 受信byte数
    //--------------------------------------------------
    int16_ReceiveLength = Receive_UART1(&STC_uint8_JobNum_UART,
                      GLB_uint8_ReceiveData_UART1);
    if(int16_ReceiveLength <= 0){
      if(int16_ReceiveLength ==  -2){
        //--------------------------
        // エラー発生
        //--------------------------
        *puint8_JobNum = 0;  // 処理番号初期化 : case 0: に移行する。
        int16_Return = -2;   // エラー発生
        break;  // エラー終了
      }

      //-------------------
      // 受信なし
      //-------------------
      int16_Return = -1;  // 処理継続 : case 1: をループ
      break;  // 処理番号維持
    }


    //-----------------------------------------------------------------
    // 受信コマンド実行
    //-----------------------------------------------------------------
    GLB_uint16_vTx1_Transfer = Execute_Command_UART((uint16_t)int16_ReceiveLength,
                                                    GLB_uint8_ReceiveData_UART1,
                                                    GLB_uint8_Tx1_Buffer);


    (*puint8_JobNum)++;  // 次の処理番号に移行する。: case 2:
    int16_Return = -1;   // 処理継続
    break;

  case 2:
    // 応答データ送信
    //------------------------------------------------------------------
    // UART1 送信処理
    //------------------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : 送信終了
    //    1 : エラー
    //------------------------------------------------------------------
    int16_Return = Send_UART1(&STC_uint8_JobNum_UART);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 2: をループ
    }

    *puint8_JobNum = 0;  // 処理番号初期化
    // int16_Return : 結果
    break;

  default:
    *puint8_JobNum = 0;  // 処理番号初期化
    int16_Return = 1;    // NG
    break;
  }

  return(int16_Return);
}

 1) case 0:
   初期化済みのフラグ GLB_int16_vUART1_InitDone を判定して
  0 の場合、UART1 の初期化を行います。

 2) case 1:
   UART1 の受信処理を行います。
   受信が発生して、1回の受信が終了するまで、case 1: をループします。

  a) エラーが発生した場合は、処理番号を 0 にして、エラー終了します。
   Commu_UART1 は、case 0: から処理を実行します。

  b) 1回の受信が終了した場合、受信データは GLB_uint8_ReceiveData_UART1 にセットされています。

  c) 受信コマンド実行 Execute_Command_UART に GLB_uint8_ReceiveData_UART1 を渡して実行します。
   受信コマンド実行結果に伴う送信データは GLB_uint8_Tx1_Buffer にセットされます。

  d) 処理番号をインクリメントします。
    処理は、case 2: に移行します。

 3) case 2:
   UART1 送信処理 Send_UART1 を実行して、GLB_uint8_Tx1_Buffer のデータを送信します。

  a) 送信が終了するまで、case 2: をループします。

  b) 送信が終了すると、処理番号を 0 に初期化して終了します。

  Commu_UART1 は再び、処理番号 0 : case 0: から実行されます。



 PCアプリケーション Access_UART
  サンプルプログラム NF446RE_UART1 を試験するためのPCアプリケーションです。

 PCアプリケーション Access_UART の説明 をご覧ください。



  このサンプルプログラムは、
  えがおのでんし製の試験用基板 Base-N446RE と UART-CMOS基板 および UART-RS232C基板 を
 使用して動作を確認しています。



動作試験用基板 Base-N446RE の説明

Base-N446RE-V1_Dim

  基板については、
 Base-N446RE基板 の説明 をご覧ください。



動作試験用基板 UART基板 の説明

  1) UART-CMOS基板

IF-NF446RE-UART-CMOS_Dim

  基板については、
 UART-CMOS基板 の説明 をご覧ください。

  2) UART-RS232C基板

IF-NF446RE-RS232C_Dim

  基板については、
 UART-RS232C基板 の説明 をご覧ください。



A+-2C (ええ加減にC) のページに戻る




 メールアドレス: apm2c.sumi@gmail.com

 なんでも、気軽に ご相談ください。
 担当:おの

マスコット
  えがおのでんし 案内