GR-SAKURA
GR-KURUMI
GR-COTTON
GR-CITRUS
GR-PEACH
GR-KAEDE
GR-ADZUKI
GR-LYCHEE
GR-ROSE
GR-MANGO(*)
SNShield
Web Compiler
IDE for GR
TOPPERS関連
女子美コラボ
その他
※プロデューサミーティング中
作り方使い方資料
イベント関連
作品記事
体験記事
ライブラリ
ツール
その他・過去ファイル
こんにちは、
私のところに、以下のような現象に悩んでいるという質問が来まして、わかる方がおられましたら、教えてください。
「ハードPWMを使っているピン0,1,5,7,8,11の振る舞いが不可解で調査しています。たとえばピン1のPWMはTPU3を使っているはずなのですが、関係ないはずのMTU0でインプットキャプチャするとPWMが出なくなりまして。」
これの原因を調べられているようですが、解決に至っていないようです。
何か気づいたことがありますでしょうか?情報量が少なくてすみません。
inoのサンプルスケッチを貰いました。// 【サンプルプログラム】 // インプットキャプチャ機能を使うと // 関係無いはずのポートのanalogWirteが出なくなる問題 // 確認環境: GR-CITRUS / IDE for GR 1.03 // このスケッチは、GR-CITRUSの7番ピン (P32/MTIOC0C)でインプットキャプチャして // パルス幅を計測します。タイマ資源はMTU0を使用します。 // 一方、analogWriteで使用するタイマ資源は下記の通りと思われます。 // 0番ピン: MTU1 // 1番ピン: TPU3 // 5番ピン: TPU4 // 7番ピン: TPU0 // 8番ピン: TPU0 // 11番ピン: MTU3 (以上、ハードウェアPWM) // それ以外: TPU2 (ソフトウェアPWM) // しかるに、MTU0を使用してインプットキャプチャすると // ハードウェアPWMのピンのanalogWriteが出力できなくなります。 // このスケッチでは 185行目で 0番ピンにanalogWriteしていますが、 // PWMは出力されません。 // 183行目をコメントアウトしてインプットキャプチャを無効にすると // PWMが出力されます。 // 2018/05/08 Bizan Nishimura #include //#include "rx63n/util.h" #include "rx63n/iodefine.h" #include "rx63n/specific_instructions.h" #include "rx63n/interrupt_handlers.h" // エッジ検出設定 #define PULSE_RISING 0x08 // 立上り検出 #define PULSE_FALLING 0x09 // 立下り検出 #define PWMETER_BUFF_SIZE 32 // パルス幅バッファのサイズ static uint8_t pulse_edge; // エッジ検出設定 static uint16_t cnt1; // パルス開始時刻 static uint16_t cnt2; // パルス終了時刻 static uint16_t buffer[PWMETER_BUFF_SIZE]; // パルス幅バッファ(リングバッファ) static uint8_t rptr; // バッファの読み出しポイント static uint8_t wptr; // バッファの書き込みポイント // MTU0 TGIC0 割り込みハンドラ (インプットキャプチャ) // (名前が TPU6_TGI6C なのはライブラリをいじらずにすませる都合) void INT_Excep_TPU6_TGI6C(void) { uint16_t cnt = MTU0.TGRC; pushi(); // 割り込みステータスを退避 cli(); // 割り込み禁止 // パルスはじまり(立上り)検出 if( pulse_edge == PULSE_RISING ){ pulse_edge = PULSE_FALLING; cnt1 = cnt; // パルス開始時刻 } // パルスおわり(立下り)検出 else{ pulse_edge = PULSE_RISING; cnt2 = cnt; // パルス終了時刻 buffer[wptr] = cnt2 - cnt1; // パルス幅 uint8_t temp = wptr; if(++temp >= PWMETER_BUFF_SIZE) temp = 0; if(temp != rptr) wptr = temp; } popi(); // 割り込みステータスを復元 MTU0.TIORL.BIT.IOC = pulse_edge; // 次のパルスエッジ検出設定 } // パルス幅計測開始 void pwmeter_begin() { pulse_edge = PULSE_RISING; rptr = 0; wptr = 0; pushi(); // 割り込みステータスを退避 cli(); // 割り込み禁止 // ピン機能選択のプロテクトをアンロック MPC.PWPR.BIT.B0WI = 0; MPC.PWPR.BIT.PFSWE = 1; // モジュールストップのプロテクトをアンロック SYSTEM.PRCR.WORD = 0xA502; MSTP(MTU0) = 0; // モジュールストップから起きる MPC.P32PFS.BIT.PSEL = 0x01; // ピン機能 (MTIOC) PORT3.PDR.BIT.B2 = 0; // ポート方向 (input) PORT3.PMR.BIT.B2 = 1; // ポートモード (ペリフェラル) MTU0.TCR.BIT.TPSC = 2; // クロック選択 (1カウント = 1/3usec) MTU0.TIORL.BIT.IOC = pulse_edge; // エッジ検出選択 MTU.TSTR.BIT.CST0 = 0x01; // カウントスタート MTU0.TIER.BIT.TGIEC = 1; // 割り込み許可 IEN(MTU0, TGIC0) = 1; // 割り込み許可 IPR(MTU0, TGIC0) = 1; // 割り込み優先度 // モジュールストップのプロテクトをロック SYSTEM.PRCR.WORD = 0xA500; // ピン機能選択のプロテクトをロック MPC.PWPR.BIT.PFSWE = 0; MPC.PWPR.BIT.B0WI = 1; popi(); // 割り込みステータスを復元 } // 新しいパルス幅計測値があるか? bool pwmeter_available() { bool ret; pushi(); // 割り込みステータスを退避 cli(); // 割り込み禁止 ret = (rptr != wptr); popi(); // 割り込みステータスを復元 return ret; } // バッファされているパルス幅を返す [usec] // 新しいパルス幅計測値が無いとき、0xFFFFを返す uint16_t pwmeter_get() { uint16_t ret; pushi(); // 割り込みステータスを退避 cli(); // 割り込み禁止 if(rptr != wptr){ ret = buffer[rptr]; if(++rptr >= PWMETER_BUFF_SIZE) rptr = 0; }else{ ret = 0xFFFF; } popi(); // 割り込みステータスを復元 if(ret != 0xFFFF) ret /= 3; // カウント値をusecに換算 return ret; } // 最新のパルス幅を返す [usec] // 新しいパルス幅計測値が無いとき、0xFFFFを返す uint16_t pwmeter_getLast() { uint16_t ret; pushi(); // 割り込みステータスを退避 cli(); // 割り込み禁止 if(rptr != wptr){ rptr = (wptr > 0) ? (wptr - 1) : (PWMETER_BUFF_SIZE - 1); ret = buffer[rptr]; if(++rptr >= PWMETER_BUFF_SIZE) rptr = 0; }else{ ret = 0xFFFF; } popi(); // 割り込みステータスを復元 if(ret != 0xFFFF) ret /= 3; // カウント値をusecに換算 return ret; } void setup() { Serial.begin(115200); pwmeter_begin(); // パルス幅計測を開始 analogWrite(0,128); // 出ない! (ハードウェアPWM) analogWrite(2,128); // 出る (ソフトウェアPWM) } void loop() { // パルスを検出したらパルス幅を表示 if(pwmeter_available()){ uint16_t pw = pwmeter_getLast(); Serial.print("PW = "); Serial.println(pw); } delay(10); }