概要
dsPIC33CHシリーズはこれまでのdsPIC33E系とは異なり純粋なタイマーは1系統となり、タイマー・インプットキャプチャ・アウトプットコンペア機能が統合されたSCCPモジュールに変わりました。このTimer1モジュールはマスターコアに1ch、スレーブコアに1ch搭載されています。
TimerモジュールとはCPUの処理とは無関係に時間をカウントしてくれるモジュールの事で、ほぼ全てのマイコンに搭載されている機能です。
今回はTimer1モジュール使用し1msec間隔で割り込みを発生させLEDを反転出力させます。

マイコンを扱う上で「割り込み」は非常に重要となる機能です。
通常メインループをプログラムは実行していますが、割り込みは「何かのイベント」が発生した時に「別のプログラムを実行させる」機能です。
例えば何かのイベントが発生した時に、処理を停止させる必要があるソフトを考えてみます。
(fig.2)のように、「処理C」が異常を検知して処理を停止させる機能だとして、「処理C」の直前にイベントが発生した場合、すぐに停止できるでしょう。しかし処理Aの途中で発生した場合、「処理C」までの期間待機しなければなりません。この時間が致命的となる場合が有ります。

割り込み処理はこうした場合に、「何かのイベントが発生した時」に「別の処理Cを先に実行」し、その実行が終われば元のソフトの実行を継続する仕組みです。

Timer1レジスタ
dsPIC33CHのTimer1関連レジスタは以下のようになっています。
主な使用レジスタは以下の通りです。今回はFP = 90MHz ,プリスケーラ = 1/8 , 周期 = 1kHz なのでPR1 の設定値は
$$PR1 = FP * Prescaler / Period = 90000000/(8 * 1000) = 11250$$
となります。
| レジスタ名 | 機能 | 説明 |
| PR1 | TIMER1 PERIOD REGISTER | タイマーの周期設定 |
| TMR1 | TIMER1 TIMER REGISTER | タイマーの現在値(Read Only) |
| T1CON | TIMER1 CONTROL REGISTER | Timer1の制御設定 |
割り込みレジスタ(抜粋)
dsPIC33CHのTimer1の割り込みレジスタは以下のようになっています。
| レジスタ名 | 説明 | 設定例 |
| IFC0bits.T1IP | Timer1の割り込み優先度 | 0 =最低優先度 ~ 7 =最高優先度 |
| IFC0bits.T1IF | Timer1の割り込みフラグ | 0 = 割り込み無し / 1 = 割り込み有り |
| IEC0bits.T1IE | Timer1の割り込み有効設定 | 0 = 割り込み無効 / 1 = 割り込み有効 |
ハードウェア構成と制御ブロック
フルカラーLEDは以下のピンに割り当てられています。

ソースコード
GPIOの設定とTimerの設定が終わった後に、割り込みを有効にしています。
この後は割り込みを無効にするまで 1kHzの周期毎に「 void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void) 」のルーチンにジャンプし、LEDの状態を反転させた後通常のルーチンに戻ります。
割り込みフラグはソフトでクリアする必要があります(IFS0bits.T1IF = 0u; )
これを行わないと割り込みを抜けた後、再度割り込みルーチンにジャンプしてきますので他の処理が実行できなくなってしまします。
コンフィグレーション設定についてはコンフィグレーション設定に記載しております。
コピーして下記のソースコードの「 //ここにコンフィグレーション設定を挿入する// 」の位置に挿入してください。
クロック設定用関数 vds_Main_Init_Clock_Register(); のソースコードはクロック設定のページに記載しております。
コピーして下記のソースコードの「 //ここにクロック設定ソースをコピペする// 」の位置に挿入してください。
/*--------------------------------------------------------------------------------*/
/* @file LED_GPIO_T1IRPT.c */
/* @brief Timer1周期で割り込み、LED1点滅 */
/* @details GPIO(TRIS,LAT)、Timer(T1CON,PR1) */
/* Interrupt(IPC,IFS,IEC)の使い方を学ぶ */
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/* コンフィグレーション設定*/
/*--------------------------------------------------------------------------------*/
//ここにコンフィグレーション設定を挿入する//
/*--------------------------------------------------------------------------------*/
/* インクルードファイル*/
/*--------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <libpic30.h>
#include "config.h"
/*--------------------------------------------------------------------------------*/
/* 定数定義*/
/*--------------------------------------------------------------------------------*/
#define TIMER1_USER_INTERVAL 1000 /* 1kHz */
#define TIMER1_USER_PR1 (_u2)( FP / (8 * TIMER1_USER_INTERVAL))
/*--------------------------------------------------------------------------------*/
/* クロック設定 */
/*--------------------------------------------------------------------------------*/
//ここにクロック設定ソースを挿入する//
/*--------------------------------------------------------------------------------*/
/* Main関数 */
/*--------------------------------------------------------------------------------*/
int main(int argc, char** argv)
{
/*---------------------------------------------------------------------------*/
/* クロック初期化*/
/*---------------------------------------------------------------------------*/
vds_Main_Init_Clock_Register(); /* クロック初期化 */
/*---------------------------------------------------------------------------*/
/* GPIO初期化*/
/*---------------------------------------------------------------------------*/
TRISEbits.TRISE0 = 0u; /* LED1ピンはデジタル出力ピン */
/*---------------------------------------------------------------------------*/
/* Timer1初期化*/
/*---------------------------------------------------------------------------*/
PR1 = TIMER1_USER_PR1; /* 周期設定 */
T1CON = 0x0000u;
T1CONbits.TCKPS = 1u; /* クロックプリスケーラ選択(1 = 1:8) */
T1CONbits.TCS = 0u; /* クロック源選択(0 = FP) */
T1CONbits.TON = 1u; /* 起動 */
/*---------------------------------------------------------------------------*/
/* Timer1割り込み開始*/
/*---------------------------------------------------------------------------*/
IPC0bits.T1IP = 4u; /* 割り込みレベル */
IFS0bits.T1IF = 0u; /* 割り込みフラグクリア */
IEC0bits.T1IE = 1u; /* 割り込み有効化 */
/*---------------------------------------------------------------------------*/
/* メインルーチン*/
/*---------------------------------------------------------------------------*/
while(1)
{
;
}
}
/*------------------------------------------------------------------------------*/
/* @fn _T1Interrupt(void) */
/* @brief クロックの設定をします */
/* @param[in] 無し*/
/* @param[out] 無し*/
/* @return 無し*/
/* @details 無し */
/*--------------------------------------------------------------------------------*/
void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void)
{
__builtin_btg(&LATE,0u);
/*---------------------------------------------------------------------------*/
/* 割り込みフラグクリア*/
/*---------------------------------------------------------------------------*/
IFS0bits.T1IF = 0u;
}


コメント