PWM 割り込み
先日から、PWMの使い方について調べてきました。今日は、PWM の立ち上がり、立ち下がりで割り込みをとる設定についてです。
PWM割り込みを使う場合、PWMを使うための設定に加えて、以下の設定が必要です。
割り込みハンドラの登録
driverlib/timer.c のAPI、TimerIntRegister()でハンドラ関数を設定します。
割り込みのエッジ設定
TimerA/B、使う方にあわせてGPTMCTLレジスタのTAEVENT、TBEVENTにエッジ種別を設定します。
エッジ種別 | 値 |
---|---|
立ち上がりエッジ | 0x0 |
立ち下がりエッジ | 0x1 |
予約 | 0x2 |
両エッジ | 0x3 |
これは、TimerControlEvent()で設定可能です。
割り込みイネーブル
こちらも使うタイマーにあわせて、TimerAはGPTMTAMRレジスタのTAPWMIE、TimerBはGPTMTBMRレジスタのTABWMIEを1に設定します。
割り込み有効/無効 | 値 |
---|---|
PWM割り込み無効 | 0 |
PWM割り込み有効 | 1 |
こちらは、TimerConfigure()でPWMを設定した場合、即ちTIMER_CFG_A_PWM、TIMER_CFG_B_PWMを設定すると同時に、1が設定されるようになっています。IntMasterEnable() も必要です。
タイマBの割り込みハンドラで、タイマAのPWM dutyを操作するサンプルプログラムを書いてみました。
#include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_timer.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" int sysclk = 0; float ms = 1.0; unsigned long cycle, duty; unsigned char cycleScale, dutyScale; // Timer0 割り込みハンドラ void Timer0IntHandler(void) { // 割り込みステータスクリア unsigned long ulStatus = TimerIntStatus(TIMER0_BASE, true); TimerIntClear(TIMER0_BASE, ulStatus); // Timer0-A の PWM duty を更新 if (ms < 5.0) ms += 0.05; else ms = 1.0; duty = sysclk / 1000 * ms; dutyScale = duty >> 16; duty &= 0xFFFF; TimerPrescaleMatchSet(TIMER0_BASE, TIMER_A, dutyScale); TimerMatchSet(TIMER0_BASE, TIMER_A, duty); } void main(void) { SysCtlClockSet( SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN); sysclk = SysCtlClockGet(); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); TimerConfigure( TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PWM); TimerControlLevel(TIMER0_BASE, TIMER_BOTH, true); // Timer0-B 立ち上がりエッジで割り込みハンドラ Timer0IntHandler を設定 TimerControlEvent(TIMER0_BASE, TIMER_B, TIMER_EVENT_POS_EDGE); TimerIntRegister(TIMER0_BASE, TIMER_B, Timer0IntHandler); GPIOPinConfigure(GPIO_PB6_T0CCP0); GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6); GPIOPinConfigure(GPIO_PB7_T0CCP1); GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_7); cycle = sysclk / 1000 * 20; // Timer0 PWM 周期を 20msec に設定 cycleScale = cycle >> 16; cycle &= 0xFFFF; TimerPrescaleSet(TIMER0_BASE, TIMER_BOTH, cycleScale); TimerLoadSet(TIMER0_BASE, TIMER_BOTH, cycle); duty = sysclk / 1000 * 1; // Timer0-A PWM duty を 1msec に設定 dutyScale = duty >> 16; duty &= 0xFFFF; TimerPrescaleMatchSet(TIMER0_BASE, TIMER_A, dutyScale); TimerMatchSet(TIMER0_BASE, TIMER_A, duty); duty = sysclk / 1000 * 15; // Timer0-B PWM duty を 15msec に設定 dutyScale = duty >> 16; duty &= 0xFFFF; TimerPrescaleMatchSet(TIMER0_BASE, TIMER_B, dutyScale); TimerMatchSet(TIMER0_BASE, TIMER_B, duty); // TIMER_CAPB_EVENT 割り込み有効化 IntMasterEnable(); TimerIntEnable(TIMER0_BASE, TIMER_CAPB_EVENT); TimerEnable(TIMER0_BASE, TIMER_BOTH); while (1) {} }