26 |
FM-7 ROM吸出し器の改版 (8) |
タイマーの設定
今回はTimer2を用いて割り込みをかけるので、Timer2の設定を行います。表261.1にある組み合わせであればどれでも良いのですが、ここでは62.5 usecの割込みを入れ、割込みルーチン内で4回の*REFCKを発行するものとします。
まず、図263.1のようにモジュール設定でIntterrupt moduleを選択し(①)、右の画面でTMR2をイネーブル(②)とします。
最後にタイマーの設定を行います。モジュール設定でTMR2を選択(①)します。周期に62.5 usと記入(②)します。プリスケーラ、ポストスケーラとも1:1(③)とします。割込み何回に一回コールバックするかを設定(④)します。
コード生成
これで設定が完了したので、Generateでコード生成を行います。様々なCソースやヘッダファイルが生成されます。例えば、device.cが生成され、その内容は、
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection Bits->INTOSC oscillator: I/O function on CLKIN pin
#pragma config WDTE = OFF // Watchdog Timer Enable->WDT disabled
#pragma config PWRTE = OFF // Power-up Timer Enable->PWRT disabled
#pragma config MCLRE = ON // MCLR Pin Function Select->MCLR/VPP pin function is MCLR
#pragma config CP = OFF // Flash Program Memory Code Protection->Program memory code protection is disabled
#pragma config BOREN = ON // Brown-out Reset Enable->Brown-out Reset enabled
#pragma config CLKOUTEN = OFF // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection->Write protection off
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
#pragma config BORV = LO // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
#pragma config LPBOR = OFF // Low-Power Brown Out Reset->Low-Power BOR is disabled
#pragma config LVP = ON // Low-Voltage Programming Enable->Low-voltage programming enabled
となっています。次にinterrupt_manager.cの内容は、
#include "interrupt_manager.h"
#include "mcc.h"
void __interrupt() INTERRUPT_InterruptManager (void)
{
// interrupt handler
if(INTCONbits.PEIE == 1)
{
if(PIE1bits.TMR2IE == 1 && PIR1bits.TMR2IF == 1)
{
TMR2_ISR();
}
else
{
//Unhandled Interrupt
}
}
else
{
//Unhandled Interrupt
}
}
のように、TMR2_ISR()を呼び出しています。mcc.cは各種初期化関数の集合であり、
#include "mcc.h"
void SYSTEM_Initialize(void)
{
PIN_MANAGER_Initialize();
OSCILLATOR_Initialize();
WDT_Initialize();
TMR2_Initialize();
}
void OSCILLATOR_Initialize(void)
{
// SCS FOSC; IRCF 16MHz_HF;
OSCCON = 0x78;
// SBOREN disabled; BORFS disabled;
BORCON = 0x00;
}
void WDT_Initialize(void)
{
// WDTPS 1:65536; SWDTEN OFF;
WDTCON = 0x16;
}
となっています。pin_manager.cは、
#include "pin_manager.h"
void PIN_MANAGER_Initialize(void)
{
/**
LATx registers
*/
LATA = 0x00;
/**
TRISx registers
*/
TRISA = 0x32;
/**
ANSELx registers
*/
ANSELA = 0x00;
/**
WPUx registers
*/
WPUA = 0x00;
OPTION_REGbits.nWPUEN = 1;
/**
APFCONx registers
*/
APFCON = 0x00;
}
のように、ピン(ポート)の設定です。最後にtmr2.cはtimer2の各種関数の集合であり、左下のNavigatorウインドウに生成された関数一覧が確認できます。ここでは、
- TMR2_CallBack()
- TMR2_DefaultInterruptHandler()
- TMR2_ISR()
- TMR2_Initialize()
- TMR2_InterruptHandler
- TMR2_LoadPeriodRegister(uinit8_t periodVal)
- TMR2_ReadTimer()
- TMR2_SetInterruptHandler(void(*InterruptHandler)()
- TMR2_StartTimer()
- TMR2_StopTimer()
- TMR2_WriteTimer(uint8_t timerVal)
が生成されました。interrupt_managerからTMR2_ISR()がコールされ、そこからTMR2_CallBack()がコールされ、そこではTMR_InterruptHandler()がコールされます。
ISR
以下のコメント部が示すように、TMR2_DefaultInterruptHandlerに割込み処理を書くようです。以下に内容を示します。
void TMR2_DefaultInterruptHandler(void){
// add your TMR2 interrupt custom code
// or set custom function using TMR2_SetInterruptHandler()
}
前稿での割込み処理内容は
もしZ80W=Lなら
- Rfreq=H、Xrefck=Hを出力 //リフレッシュ要求
- Rfgnt=Hを待つ
- Rfreq=H、Xrefck=Lを出力
- Rfreq=H、Xrefck=Hを出力 (3, 4を4回繰り返す)
- Rfreq=L、Xrefck=Hを出力
- リターン
であったので、そのままプログラムします。以下のピン名から始まる各種の関数はマクロとして、生成されたpin_manager.hで定義されています。
void TMR2_DefaultInterruptHandler(void){
if (Z80W_GetValue() == 0) {
XREFCK_SetHigh();
RFREQ_SetHigh();
while (RFGNT_GetValue() == 0);
XREFCK_SetLow(); XREFCK_SetHigh();
XREFCK_SetLow(); XREFCK_SetHigh();
XREFCK_SetLow(); XREFCK_SetHigh();
XREFCK_SetLow(); XREFCK_SetHigh();
RFREQ_SetLow();
}
}
TMR2_Initialize()の内容は、
void TMR2_Initialize(void)
{
// Set TMR2 to the options selected in the User Interface
// PR2 249;
PR2 = 0xF9;
// TMR2 0;
TMR2 = 0x00;
// Clearing IF flag before enabling the interrupt.
PIR1bits.TMR2IF = 0;
// Enabling TMR2 interrupt.
PIE1bits.TMR2IE = 1;
// Set Default Interrupt Handler
TMR2_SetInterruptHandler(TMR2_DefaultInterruptHandler);
// T2CKPS 1:1; T2OUTPS 1:1; TMR2ON on;
T2CON = 0x04;
}
のようになっています。また、main()は、
#include "mcc_generated_files/mcc.h"
/*
Main application
*/
void main(void)
{
// initialize the device
SYSTEM_Initialize();
// When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
// Use the following macros to:
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();
// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();
while (1)
{
// Add your application code
}
}
のように、初期設定がされているため、以下のようにタイマーの開始を追加します。while ループ内の処理はありません。
TMR2_StartTimer();