Quantcast
Channel: JH7UBCブログ
Viewing all articles
Browse latest Browse all 440

PIC16F88 ロータリーエンコーダその2

$
0
0
 MPLABX  XC8環境においてPIC16F88で、ロータリーエンコーダを使うプログラムのテストその2です。

 今回は、PIC16F88のピン状態変化割り込みを利用してロータリーエンコーダの回転方向を判定するプログラムを考えてみます。

 まず、PIC16F88でピン状態変化割り込みを利用できるのは、RB4~RB7で、このうち1つでもピンの状態が変化すれば、RBIFが1になります。

 そこで、RB6とRB7を使うことにし、次のようにロータリーエンコーダを配線します。結果はシリアル通信でTeraTermで表示することにします。nRBPU = 0;として、PORTBはプルアップしておきます。

イメージ 1

 ロータリーエンコーダを回転させるとAとBの状態が変化し割り込みがかかります。チャタリングがありますので、実際にはどのように割り込みが発生するか簡単なプログラムで見てみました。

イメージ 2

 ロータリーエンコーダの1つの変化に対して2~3回の割り込みが発生しています。チャタリングによるものと思われます。チャタリング対策が必要です。

 次に、回転方向を判別する方法です。今回は、ロータリーエンコーダを購入したときについてくる秋月電子の説明書にある方法でやってみます。

 BAの値の前の値を左に1ビットシフトし、現在のBAの値と排他的OR(XOR)をとり、下位2ビットだけを見ると

 時計回りの時は、0か1の値(すなわち<2)をとり、反時計回りの時は2か3の値(すなわち>=2)をとります。
 これを利用して、回転方向を判定することができます。


イメージ 3

 ブレッドボードです。

イメージ 4

 プログラムです。シリアル通信の部分は省略します。前の記事を参照してください。

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "serial.h"
// CONFIG1
#pragma config FOSC = INTOSCIO  //内臓発振器を使う
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CCPMX = RB0
#pragma config CP = OFF
// CONFIG2
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#define ECA RB6 //エンコーダB
#define ECB RB7 //エンコーダA
#define _XTAL_FREQ  8000000
unsigned char curDat = 0;
unsigned char befDat = 0;
unsigned char EA;
unsigned char EB;
signed char count= 0;

void interrupt isr(){
    RBIE = 0;   //RB割り込み禁止
    RBIF = 0;   //RB割り込みフラッグクリア
    __delay_ms(2);
    EA = ECA;
    EB = ECB;
    curDat = EA + (EB<<1);
    if (befDat != curDat){
        unsigned char d = ((befDat<<1)^curDat) & 3; //回転方向判定
        if(d < 2){
            count++;
        }else{
            count--;
        }
        befDat = curDat;
    }
    if(count >= 4){
        printf("RIGHT\r\n");
        count = 0;
    }else if(count <= -4){
        printf("LEFT\r\n");
        count = 0;
    }
     RBIE = 1;   //RB割り込み許可
}

void main() {
    ANSEL = 0x00;       //アナログポートを使わない
    OSCCON = 0b01110000;//内部クロック8MHz
    TRISA = 0b00100000; //RA5はinput 他はoutput
    TRISB = 0b11000100; //RB3.RB6,RB7はinput 他はoutput
    PORTA = 0x00;       //PORTA初期化
    PORTB = 0x00;       //PORTB初期化
    OPTION_REGbits.nRBPU = 0;//PORTB Pull up
    serial_init();      //AUSART設定
    EA = ECA;
    EB = ECB;
    befDat = EA + (EB<<1);
    RBIE = 1;           //RBピン割り込み許可
    GIE = 1;            //全割り込み許可
   
    while(1){           //無限ループ
    }
}

時計回りに回転すると「RIGHT」と反時計回りに回転すると「LEFT」とTeraTermで表示されます。

イメージ 5




Viewing all articles
Browse latest Browse all 440

Trending Articles