数か月前にソリューションを投稿するのを忘れていたので、ここに...
最後に PPM レシーバーを使用したので、このコードを簡単に編集して単純な PWM を読み取ることができます。
ヘッダー ファイルで、プロジェクトに使用していた 6 チャネル レシーバーの構造を作成しました。これは、多かれ少なかれチャンネルを持つ受信機の必要に応じて変更できます。
#ifndef _PPM_H_
#define _PPM_H_
// Libraries included
#include <stdint.h>
#include <avr/interrupt.h>
struct orangeRX_ppm {
uint16_t ch[6];
};
volatile unsigned char ch_index;
struct orangeRX_ppm ppm;
/* Functions */
void ppm_input_init(void); // Initialise the PPM Input to CTC mode
ISR( TIMER5_CAPT_vect ); // Use ISR to handle CTC interrupt and decode PPM
#endif /* _PPM_H_ */
次に、.cファイルに次のものがありました。
// Libraries included
#include <avr/io.h>
#include <stdint.h>
#include "ppm.h"
/* PPM INPUT
* ---
* ICP5 Pin48 on Arduino Mega
*/
void ppm_input_init(void)
{
DDRL |= ( 0 << PL1 ); // set ICP5 as an input
TCCR5A = 0x00; // none
TCCR5B = ( 1 << ICES5 ) | ( 1 << CS51); // use rising edge as trigger, prescale_clk/8
TIMSK5 = ( 1 << ICIE5 ); // allow input capture interrupts
// Clear timer 5
TCNT5H = 0x00;
TCNT5L = 0x00;
}
// Interrupt service routine for reading PPM values from the radio receiver.
ISR( TIMER5_CAPT_vect )
{
// Count duration of the high pulse
uint16_t high_cnt;
high_cnt = (unsigned int)ICR5L;
high_cnt += (unsigned int)ICR5H * 256;
/* If the duration is greater than 5000 counts then this is the end of the PPM signal
* and the next signal being addressed will be Ch0
*/
if ( high_cnt < 5000 )
{
// Added for security of the array
if ( ch_index > 5 )
{
ch_index = 5;
}
ppm.ch[ch_index] = high_cnt; // Write channel value to array
ch_index++; // increment channel index
}
else
{
ch_index = 0; // reset channel index
}
// Reset counter
TCNT5H = 0;
TCNT5L = 0;
TIFR5 = ( 1 << ICF5 ); // clear input capture flag
}
このコードは、ICP5 が Low から High になるたびに ISR のトリガーを使用します。この ISR では、16 ビットの ICR5 レジスタ "ICR5H<<8|ICR5L" が、ローからハイへの最後の変化から経過したプリスケールされたクロック パルスの数を保持します。通常、このカウントは 2000 us 未満です。カウントが 2500us (5000 カウント) を超える場合、入力は無効であり、次の入力は ppm.ch[0] になるはずです。
オシロスコープで見た PPM の画像を添付しました。

PPM を読み取るこの方法は、論理レベルをチェックするためにピンをポーリングし続ける必要がないため、非常に効率的です。
sei() コマンドを使用して割り込みを有効にすることを忘れないでください。そうしないと、ISR は実行されません。