LEDフリーラン点滅

システムタイマ(Timer System Service)の
遅延関数を
使った場合

 (→プロジェクトファイル(Harmony Ver.2.04版) ダウンロード


   LEDのフリーラン点滅を システムタイマ(Timer System Service)のコールバック関数を使って行う場合の例を以下に紹介します。
   
<仕様>
 ・ PIC32MZを使用する
 ・ LEDは1sec ON、1sec OFFを繰り返す
 ・ 動作クロックは外部に24MHzの水晶発振器を接続しこれを使用する
 ・ 時間制御は、Harmonyのタイマシステムサービスを使うこと。    
 
<回路図>(→回路図のPDFファイル


 

<外観>
<動作結果>
(画像をクリックすると プログラム動作中の動画がYouTubeで再生します)

     
ディスクリートキバン

(PIC32MZ QFPモジュール組立キット → 購入方法
(QFPモジュール用ユニバーサルキバン → 購入方法

 
PIC32MZ評価ボード(MZ100-A001)

( → 購入方法 )
動作結果の
   動画再生
    



<解説>

  概要
   
 MPLAB Harmonyのシステムサービスライブラリー(System Service Library) の中にタイマシステムサービスライブラリー(Timer System Service Library)というライブラリがあります。時間遅延、周期的呼び出し、ワンショット呼び出しなどの関数が用意されています。(詳細:MPLAB Harmony Help参照)
 MHCでこのシステムサービスライブラリーを使用するを選択するとシステムタイマとよばれるタイマが使えるようになります。タイマの分解能は1msecです。 このシステムタイマのハードウェアタイマとしての詳細はsystem_config.hで確認することができます。 このシステムタイマには、以下のような特徴があります。
  @ ハード的には1個のタイマであるがソフト的に複数のISRを同時に制御できる。
  A 時間遅延をblocking delay(NOPなどの遅延の塊)を使わずにつくることができる。

 Aの応用例として、通信制御、USB制御 及びグラフィック制御を含むアプリケーションがあげられます。これらの制御では、10msec以下の短いサイクルでのタスク処理が要求されます。 アプリケーションが長時間の遅延時間を要求する場合、システムタイマによる遅延時間を利用することにより、短いサイクルでタスク処理時間をこれらの制御に配賦できます。
 
 ■ 使い方 
   システムタイマの使い方には2種類あります。 常時タイムアウトを監視する方法とコールバック関数を使う方法です。
ここでは、常時タイムアウトを監視する方法による遅延時間の作り方について紹介します。

 1.  SYS_TMR_DelayMS (time)関数に 必要な遅延時間 time [msec]をセットします。
 2. 別ステートに移動して.、上記関数の戻り値を SYS_TMR_DelayStatusGet( )でタイムアウトを常時監視します。
 3. システムタイマのタイムアウトを検出したら次のステートに移動します。
         
SYS_TMR_HANDLE tmrHandle;

case APP_ADD_DELAY:
    tmrHandle = SYS_TMR_DelayMS ( 50 );
    state = APP_CHECK_DELAY;
    break;

case APP_CHECK_DELAY:
    if ( SYS_TMR_DelayStatusGet (tmrHandle ) == true )
    {
        state = APP_DELAY_COMPLETE;
    }
    break;

case APP_DELAY_COMPLETE:
    ....
    ....

    break;
 



  


■ プロジェクト作成手順(タイマシステムサービスを使った場合
  はじめてHarmonyの プロジェクトをつくる方も対象に、プロジェクト作成要領について説明します。
   以下は、Harmony v1.08、MPLABX v.3.35 をもとに作成してあります。 (10)のPin Settinsのポート設定の画面がHarmony v.2以降大幅に
  変わりましたのでポート設定画面は v2.04のものに変更してあります。 Harmony v.2.04の時点では、他の部分の変更はありません。
  (最新の Harmony や MPLABX とは、若干異なるところがある可能性がありますので注意してください。)
  (1) Harmony プロジェクト選択
    MPLABXのメニューバーで[File]→[New Project]とすると 下図の[New Project]ダイアログが開きます。[Categories]の[Microchip Embedded]を選んだあと [Projects]の[32bit−MPLAB Harmony Project]を選択して[Next]をクリックします。
     
  (2)  プロジェクトフォルダの作成
  C:\microchip\harmony\v1_08_01\appsフォルダに下にプロジェクトフォルダをつくります。 これ以外のところにプロジェクトフォルダをつくるとコンパイルできなくなることがあります。 今回だけでなく後々他にもたくさんHarmonyのプロジェクトをつくことになるのでここではC:\microchip\harmony\v1_08\apps\_myWork\Test\Basicフォルダの下にプロジェクトフォルダをつくります。
     
  (3)  プロジェクト名、デバイス名 
    ここではプロジェクト名を"04 Led FreeRun System Timer"として、Project Nameに記入します。使用するデバイス名としてPIC32MZ2048EFH100を選択して [Finish]をクリックします。
     
   (4) プロジェクト画面の表示 
    プロジェクト全体の画面があらわれます。 
   
  (5)  プロジェクトのプロパティ設定
    プロジェクトを右クリックしてドロップダウンリストの中から[Properties]を選択します。
   
  (6)  コンパイラの設定
    Project Propertiesのダイアログが開きます。特に理由がなければXC32の最新のコンパイラを選択します。
     
  (7)  シフトJIS選択 
    Categoriesボックスの[General]を選択して、 Encodiongのコンボボックスから[Shift-JIS]を選択します。
   
  (8)   MHCの表示
    右のボックスにMHC(MPLAB Harmony Configurator)の画面が表示されていない場合は、 メニューバーから[Tools] → [Embedded] → [MPLAB Harmony Configurator]をクリックするとMHCの画面が現れます。 
 尚、MHC画面を表示するには左側のプロジェクトWinodowでMHCを開きたいプロジェクトをドロップダウンリストで main project に設定しておく必要があります。
   
  (9)  クロックの設定
    [Clock Diagram]のタブをクリックしてクロック設定の画面を開きます。
 PIC32MZのOSC1ピンに 24MHzの外付け水晶発振器を取り付け、システムクロックが200MHzとなるクロックモジュールの設定を行います。プリプロセッサコマンドで記述すると以下のようになります。

 #pragma config FNOSC = SPLL
 #pragma config POSCMOD = EC
 #pragma config FPLLICLK = PLL_POSC
 #pragma config FPLLIDIV = DIV_3
 #pragma config FPLLMULT = MUL_50
 #pragma config FPLLODIV = DIV_2

 この設定を実現すべくクロックモジュール設定画面で  FNOSC、 POSCMOD、 FPLLICLK、 FPLLIDIV、FPLLMULT、FPLLODIVの各項目のコンボボックスからそれぞれ SPLL、 EC、 PLL_POSC、 DIV_3、 MUL_50、 DIV_2を選択します。
 (下記画面は 画像をクリックすると画像が拡大します)
     
    <追記>
 クロックの設定は以下の MHCのDevice & Project Configuration画面でも設定できます。 
     
  (10)   ポートの設定
    ポートの設定(下記のPin Settingsの画面は Harmony v2.04のものです)
[Pin Settings]のタブを開きます。 Pinの RG15で Function欄を GPIO_OUT に変更します
   
  (11)  システムタイマ選択(Timer System Serviceを選択 )
    MHCの[Option]タブを選択して、ツリーからHarmony Framework Configuration→System Services→Timerを選択します。そして"Use Timer System Services?"のチェックに入れます。 更に、"Interrupt Notification Enabled"にチェックをいれます。後は、デフォルトのままにしておきます。 
     
  (12)  プロジェクト コードの生成
    (Generate Code)ボタンをクリックして、*.hや*.cなどのプロジェクトに関連するファイルを一括で作成します。 MHCを保存するかどうかきいてきますので、特に理由がない場合は SaveボタンをクリックしてMHCを保存します。
   

Generateボタンをクリックしてプロジェクトファイルを一式生成します。

  (13)  変数の宣言 
     プロジェクトファイルが一式できあがりました。クリーンビルドしてここまで問題なくプロジェクトファイルができあがっていることを確認します。

 アプリケーションのコーディングの最初として、app.cの中にシステムタイマのハンドルとLEDの状態フラグの変数を宣言します。

SYS_TMR_HANDLE tmrHandle0;  //システムタイマのハンドル
bool LED;                  //LED ON/OFFの状態フラグ
     
  (14)  処理文記載
     app.cの中にあるAPP_Tasks( )のAPP_STATE_INITステート(LED点灯/消灯ステート)に次の処理をする実行分を書き込みます。
 ・LEDが消灯していたら点灯し、点灯時間1000msecをディレー用システムタイマに書き込み、APP_STATE_SERVICE_TASKS(システム
タイマチェックステート)に移動する
 ・LEDが点灯していたら消灯し、消灯時間1000msecをディレー用システムタイマに書き込み、APP_STATE_SERVICE_TASKS(システム
タイマチェックステート)に移動する 
 case APP_STATE_INIT:    //LED点灯/消灯ステート
        {
             switch(LED)
            {
                case false:
                    LED = true;
                    PLIB_PORTS_PinClear( PORTS_ID_0, PORT_CHANNEL_G, 15 );  //RG15: LED消灯                
 
                    tmrHandle0 = SYS_TMR_DelayMS ( 1000 );      
                                        //ディレー用システムタイマに 1000msecディレーをセット
                    appData.state = APP_STATE_SERVICE_TASKS; 
                                           //システムタイマチェックステートへ
                    break; 
                 
                case true:
                    LED = false;
                    PLIB_PORTS_PinSet( PORTS_ID_0, PORT_CHANNEL_G, 15 );    //RG15: LED点灯
 
                    tmrHandle0 = SYS_TMR_DelayMS ( 1000 );      
                                        //ディレー用システムタイマに 1000msecディレーをセット
                    appData.state = APP_STATE_SERVICE_TASKS;
                                          //システムタイマチェックステートへ
                    break; 
                
                default:
                    break;
            }
            break;
        }



次に、APP_Tasks( )のAPP_STATE_SERVICE_TASKSステート(ディレー用システムタイマチェックステート)に 以下の処理を記載する。
 ・セットしたタイマがセット時間に達したか常時チェックする。
 ・所定の時間に達したらAPP_STATE_INITステート(LED点灯/消灯ステート)に移動する。

 case APP_STATE_SERVICE_TASKS:   //システムタイマチェックステート
        {
            if(SYS_TMR_DelayStatusGet (tmrHandle0 ) == true)        //1000msec経過していないかチェック
                appData.state = APP_STATE_INIT;     //LED点灯/消灯ステートへ       
        
            break;
        }
 画像をクリックすると拡大します。



  (15)  プロジェクトのクリーンビルド
    プロジェクトのクリーンとビルドを行います。
   
   
実行ファイルをデバイスに書き込みます。