サンプルプログラム N446RE_AQM1602_I2C1 の説明
マスコット
  I2C 接続の LCD AQM1602 の
 表示を行うサンプルプログラムです。

  AQM1602 は秋月電子通商で販売しています。

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

目次

LCD AQM1602 の表示の様子

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

サンプルプログラム N446RE_AQM1602_I2C1 の説明
 N446RE_AQM1602_I2C1 の構成
 N446RE_AQM1602_I2C1 の動作パラメータの定義
 ユーザープログラムの実行開始位置
 N446RE_AQM1602_I2C1 の main() の説明
  1) LED点滅 と AQM1602 の表示処理 の部分

 AQM1602 の表示処理 Transact_AQM1602 の説明
  1) Transact_AQM1602 のソース
  2) Transact_AQM1602 の動作

 AQM1602 コマンド書き込み Write_Command_AQM1602 の説明
  1) Write_Command_AQM1602 のソース
  2) Write_Command_AQM1602 の動作

 AQM1602 データ書き込み Write_DataAQM1602 の説明
  1) Write_Data_AQM1602 のソース
  2) Write_Data_AQM1602 の動作

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



LCD AQM1602 の表示の様子
  AQM1602 を IF-N446RE-I2C 基板に接続して、表示を行っている様子を、
 以下に示します。

AQM1602_with_IF_N446RE_I2C



サンプルプログラム N446RE_AQM1602_I2C1 のソース
 STMicroelectronics社製のfreeの開発環境 STM32CubeIDE 1.7.0 を使用して作成しました。

 ここからサンプルプログラム R_N446RE_AQM1602_I2C1.zip をダウンロードしてください。



サンプルプログラム N446RE_AQM1602_I2C1 の説明
  PWMを使用してRGB 3色LEDの点灯制御を行うプログラムです。
  RGBそれぞれの点灯制御を独立に行うことができます。

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

N446RE_AQM1602_I2C1_Scrn_First

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



サンプルプログラムの構成
  STM32CubeIDEの画面左側、Project Explorerの
 N446RE_AQM1602_I2C1を展開した画面は以下のようになります。

N446RE_AQM1602_I2C1_Tree

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

N446RE_AQM1602_I2C1
  |
  |- Includes
  |
  |- Blink_LED_Stat : Status LED点滅処理
  |     |- Blink_LED_Stat.c
  |     |- Blink_LED_Stat.h
  |
  |- Cont_AQM1602 : AQM1602 の制御
  |     |- Cont_AQM1602.c
  |     |- Cont_AQM1602.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
  |     |- CMSIS
  |     |- STM32F4xx_HAL_Driver
  |
  |- N446RE_I2C1_Config : 動作パラメータの定義
  |     |- Dev_Conf.h
  |
  |- Periph_F4 : 周辺インターフェース処理
  |     |- H_F4_GPIO.c
  |     |- H_F4_GPIO.h
  |     |- H_F4_I2C.c
  |     |- H_F4_I2C.h
  |
  |- Wait_Itvl : 時間待ち処理
  |     |- Wait_Itvl.c
  |     |- Wait_Itvl.h
  |
  |- N446RE_AQM1602_I2C1.launch
  |- STM32F446RETX_FLASH.ld
  |- STM32F446RETX_RAM.ld



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

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



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

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

N446RE_AQM1602_I2C1_main

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

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



 N446RE_AQM1602_I2C1 の main() の説明
  サンプルプログラム N446RE_AQM1602_I2C1 の 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_LCD = 0;  // LCD表示処理番号

  /* 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(&uint8_JobNum_LED,
                 GLB_uint16_Time_LED_Stat_ON, GLB_uint16_Time_LED_Stat_OFF);


    //---------------------------------------------------
    // LCD AQM1602 の表示処理
    //---------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK
    //    1 : NG
    //---------------------------------------------------
    Transact_AQM1602(&uint8_JobNum_LCD);
  }
  /* 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_Init はプロジェクト構築時に自動的に組み込まれる、
  HAL Drivers(フォルダ Drivers/STM32F4xx_HAL_Drivers) 内に記述されています。


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

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

   SystemClock_Config(); の設定内容は、

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



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


  /* 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(&uint8_JobNum_LED,
                 GLB_uint16_Time_LED_Stat_ON, GLB_uint16_Time_LED_Stat_OFF);


    //---------------------------------------------------
    // LCD AQM1602 の表示処理
    //---------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK
    //    1 : NG
    //---------------------------------------------------
    Transact_AQM1602(&uint8_JobNum_LCD);
  }
  /* USER CODE END 3 */

  Status LED点滅処理 Blk_LED_Stat と
  AQM1602 の表示処理 Transact_AQM1602 を呼び出しています。



 AQM1602 の表示処理 Transact_AQM1602 の説明


  1) Transact_AQM1602 のソース
  モジュール Transact_AQM1602 は
 Cont_AQM1602/Cont_AQM1602.c 内に記述されています。

  モジュール Transact_AQM1602 のソースを以下に示します。

//---------------------------------------------------
// LCD AQM1602 の表示処理
//---------------------------------------------------
// 引数:
// uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

// 戻り値:
//   -1 : 処理中
//    0 : OK
//    1 : NG
//---------------------------------------------------
int16_t Transact_AQM1602(uint8_t *puint8_JobNum)
{
  static uint8_t STC_uint8_JobNum_Wait;  // 時間待ちの処理番号
  static uint32_t STC_uint32_tikstart;  // 時間待ち開始時のカウント数
  static uint32_t STC_uint32_Interval;  // 待ち時間

  static uint8_t STC_uint8_JobNum_LCD;  // LCD処理番号

  static uint8_t STC_uint8_Address;
  static uint8_t STC_uint8_Number_TX;
  static uint8_t STC_uint8_Data_TX[16];

  int16_t int16_Return;


  switch(*puint8_JobNum)
  {
  case 0:
    //-------------------------------------------------------
    // I2C初期化 : AQM1602
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Init_I2C_AQM1602(&STC_uint8_JobNum_LCD);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 0: をループ
    }

    if(int16_Return != 0){
      // NG終了
      HAL_I2C_DeInit(&Handle_I2C1);
      GLB_int16_vI2C1_Initialize_Done = 0;

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


    STC_uint8_JobNum_LCD = 0;  // LCD表示処理番号初期化


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

  case 1:
    //-------------------------------------------------------
    // AQM1602 の初期設定を行う。
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Initial_Setting_AQM1602(&STC_uint8_JobNum_LCD);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 1: をループ
    }

    if(int16_Return != 0){
      // NG終了
      HAL_I2C_DeInit(&Handle_I2C1);
      GLB_int16_vI2C1_Initialize_Done = 0;

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


    STC_uint8_Address = 0x80;

    STC_uint8_Number_TX = 16;
    memcpy(STC_uint8_Data_TX, "0123456789ABCDEF", 16);


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

  case 2:
    //-------------------------------------------------------
    // AQM1602 データ書き込み
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint8_t uint8_Address : データ書き込みアドレス

    // uint8_t uint8_Number_TX : 送信データ数
    // uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Write_Data_AQM1602(&STC_uint8_JobNum_LCD,
                                      STC_uint8_Address,
                                      STC_uint8_Number_TX, STC_uint8_Data_TX);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 2: をループ
    }

    if(int16_Return != 0){
      // NG終了
      HAL_I2C_DeInit(&Handle_I2C1);
      GLB_int16_vI2C1_Initialize_Done = 0;

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


    STC_uint8_JobNum_Wait = 0;  // 時間待ちの処理番号初期化
    STC_uint32_Interval = (uint32_t)1000;  // 待ち時間


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

  case 3:
    //------------------------------------------------------
    // mSec待ちシーケンス : 処理番号使用 : 複数呼び出し用
    //------------------------------------------------------
    // 戻り値が -1 以外になるまで、繰り返し呼び出してください。
    //------------------------------------------------------
    // 引数 :
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint32_t *puint32_tikstart : 時間待ち開始時のカウント数
    // uint32_t uint32_mSec : 待ち時間(mSec)

    // 戻り値 :
    //   -1 : 処理中 : 時間が経過していない。
    //    0 : OK終了 : 時間が経過した。
    //    1 : NG終了
    //------------------------------------------------------
    int16_Return = Wait_mSec_Seq_Multi(&STC_uint8_JobNum_Wait,
                                       &STC_uint32_tikstart,
                                       STC_uint32_Interval);
    if(int16_Return == -1){
      // 処理中 : 時間未経過
      break;  // 処理番号維持 : 処理継続 : case 3: をループ
    }


    STC_uint8_Address = 0xC0;

    STC_uint8_Number_TX = 16;
    memcpy(STC_uint8_Data_TX, "GHIJKLMNOPQRSTUV", 16);


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

  case 4:
    //-------------------------------------------------------
    // AQM1602 データ書き込み
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint8_t uint8_Address : データ書き込みアドレス

    // uint8_t uint8_Number_TX : 送信データ数
    // uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Write_Data_AQM1602(&STC_uint8_JobNum_LCD,
                                      STC_uint8_Address,
                                      STC_uint8_Number_TX, STC_uint8_Data_TX);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 4: をループ
    }

    if(int16_Return != 0){
      // NG終了
      HAL_I2C_DeInit(&Handle_I2C1);
      GLB_int16_vI2C1_Initialize_Done = 0;

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


    STC_uint8_JobNum_Wait = 0;  // 時間待ちの処理番号初期化
    STC_uint32_Interval = (uint32_t)1000;  // 待ち時間


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

  case 5:
    //------------------------------------------------------
    // mSec待ちシーケンス : 処理番号使用 : 複数呼び出し用
    //------------------------------------------------------
    // 戻り値が -1 以外になるまで、繰り返し呼び出してください。
    //------------------------------------------------------
    // 引数 :
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint32_t *puint32_tikstart : 時間待ち開始時のカウント数
    // uint32_t uint32_mSec : 待ち時間(mSec)

    // 戻り値 :
    //   -1 : 処理中 : 時間が経過していない。
    //    0 : OK終了 : 時間が経過した。
    //    1 : NG終了
    //------------------------------------------------------
    int16_Return = Wait_mSec_Seq_Multi(&STC_uint8_JobNum_Wait,
                                       &STC_uint32_tikstart,
                                       STC_uint32_Interval);
    if(int16_Return == -1){
      // 処理中 : 時間未経過
      break;  // 処理番号維持 : 処理継続 : case 5: をループ
    }


    STC_uint8_Number_TX = 1;  // 送信データ数セット

    // コマンドセット
    STC_uint8_Data_TX[0] = 0x01;  // CLEAR DISPLAY


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

  case 6:
    //-------------------------------------------------------
    // AQM1602 コマンド書き込み
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint8_t uint8_Number_TX : 送信データ数
    // uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

    // uint32_t uint32_Interval : 待ち時間 (mSec)

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Write_Command_AQM1602(&STC_uint8_JobNum_LCD,
                                         STC_uint8_Number_TX, STC_uint8_Data_TX,
                                         (uint32_t)3);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 6: をループ
    }

    if(int16_Return != 0){
      // NG終了
      HAL_I2C_DeInit(&Handle_I2C1);
      GLB_int16_vI2C1_Initialize_Done = 0;

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


    STC_uint8_Address = 0x80;

    STC_uint8_Number_TX = 16;
    memcpy(STC_uint8_Data_TX, "Nice to meet you", 16);


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

  case 7:
    //-------------------------------------------------------
    // AQM1602 データ書き込み
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint8_t uint8_Address : データ書き込みアドレス

    // uint8_t uint8_Number_TX : 送信データ数
    // uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Write_Data_AQM1602(&STC_uint8_JobNum_LCD,
                                      STC_uint8_Address,
                                      STC_uint8_Number_TX, STC_uint8_Data_TX);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 7: をループ
    }

    if(int16_Return != 0){
      // NG終了
      HAL_I2C_DeInit(&Handle_I2C1);
      GLB_int16_vI2C1_Initialize_Done = 0;

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


    STC_uint8_JobNum_Wait = 0;  // 時間待ちの処理番号初期化
    STC_uint32_Interval = (uint32_t)1000;  // 待ち時間


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

  case 8:
    //------------------------------------------------------
    // mSec待ちシーケンス : 処理番号使用 : 複数呼び出し用
    //------------------------------------------------------
    // 戻り値が -1 以外になるまで、繰り返し呼び出してください。
    //------------------------------------------------------
    // 引数 :
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint32_t *puint32_tikstart : 時間待ち開始時のカウント数
    // uint32_t uint32_mSec : 待ち時間(mSec)

    // 戻り値 :
    //   -1 : 処理中 : 時間が経過していない。
    //    0 : OK終了 : 時間が経過した。
    //    1 : NG終了
    //------------------------------------------------------
    int16_Return = Wait_mSec_Seq_Multi(&STC_uint8_JobNum_Wait,
                                       &STC_uint32_tikstart,
                                       STC_uint32_Interval);
    if(int16_Return == -1){
      // 処理中 : 時間未経過
      break;  // 処理番号維持 : 処理継続 : case 8: をループ
    }


    STC_uint8_Address = 0xC0;

    STC_uint8_Number_TX = 16;
    memcpy(STC_uint8_Data_TX, "Take it easy!   ", 16);


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

  case 9:
    //-------------------------------------------------------
    // AQM1602 データ書き込み
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint8_t uint8_Address : データ書き込みアドレス

    // uint8_t uint8_Number_TX : 送信データ数
    // uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Write_Data_AQM1602(&STC_uint8_JobNum_LCD,
                                      STC_uint8_Address,
                                      STC_uint8_Number_TX, STC_uint8_Data_TX);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 9: をループ
    }

    if(int16_Return != 0){
      // NG終了
      HAL_I2C_DeInit(&Handle_I2C1);
      GLB_int16_vI2C1_Initialize_Done = 0;

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


    STC_uint8_JobNum_Wait = 0;  // 時間待ちの処理番号初期化
    STC_uint32_Interval = (uint32_t)1000;  // 待ち時間


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

  case 10:
    //------------------------------------------------------
    // mSec待ちシーケンス : 処理番号使用 : 複数呼び出し用
    //------------------------------------------------------
    // 戻り値が -1 以外になるまで、繰り返し呼び出してください。
    //------------------------------------------------------
    // 引数 :
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint32_t *puint32_tikstart : 時間待ち開始時のカウント数
    // uint32_t uint32_mSec : 待ち時間(mSec)

    // 戻り値 :
    //   -1 : 処理中 : 時間が経過していない。
    //    0 : OK終了 : 時間が経過した。
    //    1 : NG終了
    //------------------------------------------------------
    int16_Return = Wait_mSec_Seq_Multi(&STC_uint8_JobNum_Wait,
                                       &STC_uint32_tikstart,
                                       STC_uint32_Interval);
    if(int16_Return == -1){
      // 処理中 : 時間未経過
      break;  // 処理番号維持 : 処理継続 : case 10: をループ
    }


    STC_uint8_Number_TX = 1;  // 送信データ数セット

    // コマンドセット
    STC_uint8_Data_TX[0] = 0x01;  // CLEAR DISPLAY


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

  case 11:
    //-------------------------------------------------------
    // AQM1602 コマンド書き込み
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint8_t uint8_Number_TX : 送信データ数
    // uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

    // uint32_t uint32_Interval : 待ち時間 (mSec)

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Write_Command_AQM1602(&STC_uint8_JobNum_LCD,
                                         STC_uint8_Number_TX, STC_uint8_Data_TX,
                                         (uint32_t)3);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 11: をループ
    }

    if(int16_Return != 0){
      // NG終了
      HAL_I2C_DeInit(&Handle_I2C1);
      GLB_int16_vI2C1_Initialize_Done = 0;

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


    STC_uint8_Address = 0x80;

    STC_uint8_Number_TX = 16;
    memcpy(STC_uint8_Data_TX, "0123456789ABCDEF", 16);


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

  default:
    *puint8_JobNum = 0;
    int16_Return = 1;
    break;  // NG
  }

  return(int16_Return);
}


 2) Transact_AQM1602 の動作

  a) case 0:
    AQM1602表示に使用する I2C1 を初期化します。

  b) case 1:
    AQM1602 の初期設定を行います。

  b) case 2:
    表示データ "0123456789ABCDEF" を AQM1602 の 1行目に書き込みます。

    表示結果は以下のようになります。
Disp_AQM1602_1

  c) case 3:
    1000mSec 待ちます。

  d) case 4:
    表示データ "GHIJKLMNOPQRSTUV" を AQM1602 の 2行目に書き込みます。

    表示結果は以下のようになります。
Disp_AQM1602_2

  e) case 5:
    1000mSec 待ちます。

  f) case 6:
    AQM1602 の表示をクリアします。

  g) case 7:
    表示データ "Nice to meet you" を AQM1602 の 1行目に書き込みます。

    表示結果は以下のようになります。
Disp_AQM1602_3

  h) case 8:
    1000mSec 待ちます。

  i) case 9:
    表示データ "Take it easy! " を AQM1602 の 2行目に書き込みます。

    表示結果は以下のようになります。
Disp_AQM1602_4

  j) case 10:
    1000mSec 待ちます。

  k) case 11:
    AQM1602 の表示をクリアします。

    クリア動作終了後、表示データバッファ STC_uint8_Data_TX に
   "0123456789ABCDEF" をセットして、処理番号に 2 をセットします。

    Transact_AQM1602 の処理は、再び case 2: から実行されます。
    こうして、Transact_AQM1602 の処理は、case 2: - case 11: をループします。



 AQM1602 コマンド書き込み Write_Command_AQM1602 の説明


  1) Write_Command_AQM1602 のソース
    モジュール Write_Command_AQM1602 は
    Cont_AQM1602/Cont_AQM1602B.c 内に記述されています。

    モジュール Write_Command_AQM1602 のソースを以下に示します。

//-------------------------------------------------------
// AQM1602 コマンド書き込み
//-------------------------------------------------------
// 引数:
// uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

// uint8_t uint8_Number_TX : 送信データ数
// uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

// uint32_t uint32_Interval : 待ち時間 (mSec)

// 戻り値:
//   -1 : 処理中
//    0 : OK終了
//    1 : NG終了
//-------------------------------------------------------
int16_t Write_Command_AQM1602(uint8_t *puint8_JobNum,
                              uint8_t uint8_Number_TX, uint8_t *puint8_Data_TX,
                              uint32_t uint32_Interval)
{
  static uint8_t STC_uint8_JobNum_Wait;  // 時間待ちの処理番号
  static uint32_t STC_uint32_tikstart;  // 時間待ち開始時のカウント数
  static uint32_t STC_uint32_Interval;  // 待ち時間

  static uint8_t STC_uint8_JobNum_I2C;  // I2C処理番号

  static uint8_t STC_uint8_Count_TX;  // 送信回数カウンタ
  static uint8_t STC_uint8_I2C_TX[2];  // I2C送信データ

  int16_t int16_Return;


  switch(*puint8_JobNum)
  {
  case 0:
    STC_uint8_JobNum_I2C = 0;  // I2C処理番号初期化
    STC_uint8_Count_TX = 0;    // 送信回数カウンタ初期化

    // I2C送信データセット
    STC_uint8_I2C_TX[0] = 0x00;  // control bytee
    STC_uint8_I2C_TX[1] = puint8_Data_TX[STC_uint8_Count_TX];  // data byte : Instruction


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

  case 1:
    //------------------------------------------------------------------------
    // I2C Master送信 : Register指定 1byte + 設定データ 1byteを送信
    //------------------------------------------------------------------------
    //引数 :
    // uint8_t *puint8_JobNum : 処理番号

    // uint8_t *puint8_TxBuffer : 送信データが格納されたBufferのポインタ
    // uint16_t uint16_TxNumber : 送信データ数

    //戻り値 :
    //   -1 : 処理中
    //    0 : OK
    //    1 : NG
    //------------------------------------------------------------------------
    int16_Return = I2C1_Master_TxByte(&STC_uint8_JobNum_I2C,
                                      STC_uint8_I2C_TX, (uint16_t)2);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 1: をループ
    }

    if(int16_Return != 0){
      // NG終了
      *puint8_JobNum = 0;  // 処理番号初期化
      // int16_Return : 結果
      break;
    }


    STC_uint8_JobNum_Wait = 0;  // 時間待ちの処理番号初期化
    STC_uint32_Interval = uint32_Interval;  // 待ち時間


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

  case 2:
    //------------------------------------------------------
    // mSec待ちシーケンス : 処理番号使用 : 複数呼び出し用
    //------------------------------------------------------
    // 戻り値が -1 以外になるまで、繰り返し呼び出してください。
    //------------------------------------------------------
    // 引数 :
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint32_t *puint32_tikstart : 時間待ち開始時のカウント数
    // uint32_t uint32_mSec : 待ち時間(mSec)

    // 戻り値 :
    //   -1 : 処理中 : 時間が経過していない。
    //    0 : OK終了 : 時間が経過した。
    //    1 : NG終了
    //------------------------------------------------------
    int16_Return = Wait_mSec_Seq_Multi(&STC_uint8_JobNum_Wait,
                                       &STC_uint32_tikstart,
                                       STC_uint32_Interval);
    if(int16_Return == -1){
      // 処理中 : 時間未経過
      break;  // 処理番号維持 : 処理継続 : case 2: をループ
    }


    STC_uint8_Count_TX++;  // 送信回数カウンタ インクリメント

    // 送信回数判定
    if(STC_uint8_Count_TX < uint8_Number_TX){
      // 指定された送信回数に達していない。

      // I2C送信データセット
      STC_uint8_I2C_TX[1] = puint8_Data_TX[STC_uint8_Count_TX];  // data byte : Instructio

      *puint8_JobNum = 1;  // 処理番号 1 に戻る。: case 1:
      int16_Return = -1;   // 処理継続
      break;
    }


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

  default:
    *puint8_JobNum = 0;
    int16_Return = 1;
    break;  // NG
  }

  return(int16_Return);
}


  2) Write_Command_AQM1602 の動作

   a) case 0:
     I2C処理番号初期化 と 送信回数カウンタ初期化 を行い、
    送信データバッファ STC_uint8_Data_TX に
    control byte と Instruction をセットします。

   b) case 1:
     AQM1602 に control byte と Instruction を送信します。

   c) case 2:
     指定された時間を待ちます。

     時間待ち終了後、送信回数を判定します。

     送信回数に達していない場合
      STC_uint8_I2C_TX[1] に次の Instruction をセットして、
     処理番号を 1 にします。

      送信回数に達するまで case 1: と case 2: をループします。

     送信回数に達した場合
      処理番号を 0 にして、処理を終了します。


 AQM1602 データ書き込み Write_Data_AQM1602 の説明


  1) Write_Data_AQM1602 のソース
    モジュール Write_Data_AQM1602 は
    Cont_AQM1602/Cont_AQM1602B.c 内に記述されています。

    モジュール Write_Data_AQM1602 のソースを以下に示します。

//-------------------------------------------------------
// AQM1602 データ書き込み
//-------------------------------------------------------
// 引数:
// uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

// uint8_t uint8_Address : データ書き込みアドレス

// uint8_t uint8_Number_TX : 送信データ数
// uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

// 戻り値:
//   -1 : 処理中
//    0 : OK終了
//    1 : NG終了
//-------------------------------------------------------
int16_t Write_Data_AQM1602(uint8_t *puint8_JobNum,
                           uint8_t uint8_Address,
                           uint8_t uint8_Number_TX, uint8_t *puint8_Data_TX)
{
  static uint8_t STC_uint8_JobNum_I2C;  // I2C処理番号

  static uint8_t STC_uint8_Count_TX;  // 送信回数カウンタ
  static uint8_t STC_uint8_Data_TX[4];  // I2C送信データ

  int16_t int16_Return;


  switch(*puint8_JobNum)
  {
  case 0:
    STC_uint8_JobNum_I2C = 0;  // I2C処理番号初期化
    STC_uint8_Count_TX = 0;    // 送信回数カウンタ初期化

    // 送信データセット
    STC_uint8_Data_TX[0] = uint8_Address;  // 表示アドレス


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

  case 1:
    //-------------------------------------
    // 表示アドレスセット
    //-------------------------------------
    //-------------------------------------------------------
    // AQM1602 コマンド書き込み
    //-------------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // uint8_t uint8_Number_TX : 送信データ数
    // uint8_t *puint8_Data_TX : 送信データを格納したバッファのポインタ

    // uint32_t uint32_Interval : 待ち時間 (mSec)

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK終了
    //    1 : NG終了
    //-------------------------------------------------------
    int16_Return = Write_Command_AQM1602(&STC_uint8_JobNum_I2C,
                                         (uint8_t)1, STC_uint8_Data_TX,
                                         (uint32_t)2);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 1: をループ
    }

    if(int16_Return != 0){
      // NG終了
      *puint8_JobNum = 0;  // 処理番号初期化
      // int16_Return : 結果
      break;  // 処理終了
    }


    // 送信データセット
    STC_uint8_Data_TX[0] = 0x40;  // control byte
    STC_uint8_Data_TX[1] = puint8_Data_TX[STC_uint8_Count_TX];  // data byte ; 表示データ


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

  case 2:
    //------------------------------------
    // 表示データ書き込み
    //------------------------------------
    //------------------------------------------------------------------------
    // I2C Master送信
    //------------------------------------------------------------------------
    //引数 :
    // uint8_t *puint8_JobNum : 処理番号

    // uint8_t *puint8_TxBuffer : 送信データが格納されたBufferのポインタ
    // uint16_t uint16_TxNumber : 送信データ数

    //戻り値 :
    //   -1 : 処理中
    //    0 : OK
    //    1 : NG
    //------------------------------------------------------------------------
    int16_Return = I2C1_Master_TxByte(&STC_uint8_JobNum_I2C,
                                      STC_uint8_Data_TX, (uint16_t)2);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 2: をループ
    }

    if(int16_Return != 0){
      // NG終了
      *puint8_JobNum = 0;  // 処理番号初期化
      // int16_Return : 結果
      break;  // 処理終了
    }


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

  case 3:
    //---------------------------------------------------
    // LCD AQM1602 のビジーチェック
    //---------------------------------------------------
    // 引数:
    // uint8_t *puint8_JobNum : 処理番号が格納される変数のポインタ

    // 戻り値:
    //   -1 : 処理中
    //    0 : OK
    //    1 : NG
    //---------------------------------------------------
    int16_Return = Check_Busy_AQM1602(&STC_uint8_JobNum_I2C);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : case 3: をループ
    }

    if(int16_Return != 0){
      // NG終了
      *puint8_JobNum = 0;  // 処理番号初期化
      // int16_Return : 結果
      break;  // 処理終了
    }


    STC_uint8_Count_TX++;  // 送信回数カウンタ インクリメント

    // 送信回数判定
    if(STC_uint8_Count_TX < uint8_Number_TX){
      // 指定された送信回数に達していない。

      // 送信データセット
      STC_uint8_Data_TX[1] = puint8_Data_TX[STC_uint8_Count_TX];  // data byte ; 表示データ

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


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

  default:
    *puint8_JobNum = 0;
    int16_Return = 1;
    break;  // NG
  }

  return(int16_Return);
}


  2) Write_Data_AQM1602 の動作

   a) case 0:
     I2C処理番号初期化 と 送信回数カウンタ初期化 を行い、
    送信データバッファ STC_uint8_Data_TX[0] に
    指定された表示アドレスをセットします。

   b) case 1:
     モジュール Write_Command_AQM1602 により
    AQM1602 に 表示アドレスをセットします。

     Write_Command_AQM1602 の処理終了後、
    送信データバッファ STC_uint8_Data_TX に
    control byte と 表示データ をセットします。

   c) case 2:
     I2C通信により送信データバッファのデータを送信します。

   d) case 3:
     モジュール Check_Busy_AQM1602 により、ビジーをチェックします。

     AQM1602 はI2Cインターフェースを使用する場合、ビジーフラグ BF を
    読み込むことができないため、時間待ちで対応しています。

     ビジーチェック終了後、送信回数を判定します。

     送信回数に達していない場合
      STC_uint8_I2C_TX[1] に次の 表示データ をセットして、
     処理番号を 2 にします。

      送信回数に達するまで case 2: と case 3: をループします。

     送信回数に達した場合
      処理番号を 0 にして、処理を終了します。


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



 動作試験用基板 Base-N446RE の説明
  さまざまな、インターフェース基板を接続して動作試験を行うことができます。

Base-N446RE-V1_Dim

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



 動作試験用基板 IF-N446RE-I2C の説明
  I2C通信を行うためのインターフェース基板です。

IF-N446RE-I2C-V1_Dim

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



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




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

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

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