パルス幅の計測
AVRの タイマー1 インプットキャプチャ機能を使ってパルス幅の計測。
入力される信号をインプットキャプチャでパルスの立ち上がりから立ち下がりまでの間隔時間をタイマー1で計測します。
インプットキャプチャ機能
外部からの入力の要因のエッジをとらえてタイマーを関連づける機能で、
信号の 立ち上がり、立ち下がり、両方 が選択でき、その入力に応じて割り込み関数などを起動することができる。
またノイズ消去の機能もあります。
AVRにはインプットキャプチャ機能はタイマー0にはない機能で、タイマー1にあります。
これで入力された信号の立ち上がり、立ち下がりを検知
割り込みエッジ選択
(図のような部分が信号の
立ち上がりと立ち下がり)
外部割り込みの IRQ入力信号は
○立ち下がり設定では
ずっとHIGH だったものが
突然
HIGH→LOW になったときが
立ち下がり なので
このとき 割り込みがかかり
割り込み関数が起動します。
立ち下がり後
その後はずっとLow状態でも、
割り込み動作はエッジをとらえた1度だけ。
立ち下がり だけをとらえて反応します。
○立ち上がり設定では
反対に
ずっとLOW だったものが 突然
LOW→HIGH になったときが
立ち上がり なので
このとき 割り込みがかかり
割り込み関数が起動します。
実行するのには、測定すべきパルスの入力が必要です。
測定する波形は別のタイマー=タイマー0 で発生させます。
タイマー0 PWM機能でパルスの波形発生
これで、タイマー1と分周は同じにしてあるので 本来パルス測定幅は OCR0B= 値と同じになる。
プログラム
ファイル名
#include
#include
#include "lcd.h"
#include "myLCDdef.h"
typedef unsigned char uchar;
typedef unsigned short ushort;
#define sbi(PORT,BIT) PORT |= _BV(BIT) //ビット操作のマクロ定義
#define cbi(PORT,BIT) PORT &=~_BV(BIT)
#define PLS_UP 1
#define PLS_DOWN 0
volatile uchar pls_state;
volatile uchar t=0; //立ち上下のフラグ格納変数
volatile uchar i=0 ;
volatile ushort a=0, b=0 ; //パルス幅取り込み変数
volatile ushort disp_count[3], count;
volatile unsigned long temp;
//TMER1 インプットキャプチャ割り込み
ISR(TIMER1_CAPT_vect) { //Tmr1 インプットキャプチャ割り込み関数
//PD6pin プルアップ”なし” PD6=1でキャプチャ
// 短形波の立ち”上がり”~立ち”下がり”間隔を測定
cli(); //割り込み禁止
if( pls_state == PLS_UP ){//立ち上がり
pls_state = PLS_DOWN; //フラグ設定
a = ICR1; //タイマカウンタ値 取り込み
cbi(TCCR1B,ICES1); //立ち下がりに設定 (ICES1=0
}else{ //立ち下がり
pls_state = PLS_UP; //フラグ設定
b = ICR1; //タイマカウンタ値 取り込み
if( a < b ){
count = b - a; } //タイマカウンタ値 取り込み
else{
count = ( 0xFFFF - a ) + b; //オーバーフローをまたいだ時のタイマカウンタ値 取り込み
}
sbi(TCCR1B,ICES1); //立ち上がりに設定 (ICES1=1
disp_count[i] = count;
i+=1;
}
sei(); //割り込み許可
}
int main(){
DDRD = 0xBF; // ポートD#6を入力設定1011 1111 --PD6入力
//タイマ0
TCCR0A = 0x23; // 0011 0011 高速PWMモード (cpmB=OC0B)
TCCR0B = 0x0A; // 0000 1010 1/8 ,Top=OC0A
//タイマ1
TCCR1B = 0x42; //#0100 0010 edge:立ち上がり :分周1/8 #0010
//タイマ1 インプットキャプチャ
TIMSK = _BV(ICIE1); // タイマ1インプットキャプチャ割り込み許可
TCNT0 = 0; // タイマ0の初期値
//PD5から1kDty50%のパルス発生
OCR0A=122; // 周期 1kHz
OCR0B=61; // Dty 50%
//LCD初期化
lcd_init(LCD_DISP_ON);
lcd_clrscr();
//表示変数初期化
i = 0; //測定回数
pls_state = PLS_UP; //キャプチャフラグ
sei(); //割り込み許可
while(i < 3);
//結果表示
lcd_gotoxy(0,0);
lcd_puts("i1=");LCD_dtoutRsgn( 4, disp_count[i] );
}
回路
出力 PWM PD5
入力 インプットキャプチャ PD6
PD5とPD6を接続
ピンPD5からPWMでの波形がでます。
タイマー0 PWM機能でパルスの波形発生 を参照
その信号PD5 をインプットキャプチャ入力ピン PD6へつなげ入力する
合体させ、ピン をつなぐ。
インプットキャプチャ設定
●TIMSK 割り込み設定レジスタ タイマ0,1混在
タイマー1の設定 | タイマー0の設定 | ||||||
オーバー プロー |
コンペア マッチA |
コンペア マッチB |
- | インプット キャプチャ |
コンペア マッチB |
オーバー プロー |
コンペア マッチA |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
TOIE1 | OCIE1A | OCIE1B | - | ICIE1 | OCIE0B | TOIE0 | OCIE0A |
ICF1 : インプットキャプチャ割り込み許可 (インプットキャプチャは タイマー0にはない)
WGM13-10でTOP値に設定の場合 カウンタ値=TOPで このフラグが 1
●TCCR1B タイマ0設定レジスタ
- | - | クロック設定 | |||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1CNC1 | 1CES1 | - | WGM13 | WGM12 | CS12 | CS11 | CS10 |
1CNC1 : インプットキャプチャノイズ消去許可
ここが1設定で、ノイズ消去器を有効に。
ノイズ消去は連続4回同じ入力の場合にその入力を得る。このため4回で1入力となり遅れがでる。
1CES1 : インプットキャプチャ エッジ選択
0:立ち下がり
1:立ち上がり
ここの設定に従ってインプットキャプチャがトリガされると、タイマカウンタ値が インプットキャプチャレジスタ(ICR1)へコピーされる
プログラムの処理
インプットキャプチャ発生の割り込み立ち上がり、下がり時に直接のカウンタ値を取り込む方法です。 (H8のところのRCサーボのリンクsisoさんにある例を参考にさせていただきました)
インプットキャプチャ発生で タイマカウンタ値がICR1に自動的に取り込まれる。
その立ち上がりと立ち下がりの時間を減算して間隔時間を得ます。
タイマー1のカウントではオーバーフローをまたぐことがあります。
オーバーフロー割り込みにも引き継いでカウントする方法も可能ですが、タイマ満タン値から減算して調整しています。
ここでの処理は、最初はインプットキャプチャ割り込みは立ち上がりに設定、
インプットキャプチャ割り込みに入るとフラグで判定し、割り込み設定とフラグを 内部で反対に切り替え、
立ち下がりを受けた処理で、得たタイマー値を減算して立ち上がり、下がり間隔測定時間とします。
4回インプットキャプチャでの測定し終えると、LCDに結果を表示。
- twtter
- google+
- hatena