PIC12F683を使ってスイッチを活用して入出力制御をする

スイッチ入力の処理について

 入出力は、マイコン制御の基本です。スイッチを押すとLEDが光る制御をしていきます。スイッチの処理は、チャタリングを遅延でカットしたり、フィルター回路で回避したりと様々な方法があるので、色々実施してみてください。

回路の作成

スイッチ入力は、プルアップを採用しました。プルダウンで接続する場合は、プログラムを変更する必要があります。プルアップについては、過去の記事を参考にしてください。回路は、そんなに難しい組み方をしていないので説明は不要かな。

 プルアップについてはこちら>ここクリックしてください

MPLABを使ってプロジェクトを作成

https://e-work-education.com/2021/12/07/project/

簡単な入力プログラムを作成してみよう

 簡単なプログラムを組んで動作確認をしましょう。注意点は、下記のプログラムをコピー&ペーストしても動作しないので注意してください。動作部分のみ切り抜いてあります。
 さて、動作部分ですが、スイッチを押したときと離したときが下記のような動作になります。

 スイッチON:〇●●●
 スイッチOFF:〇〇〇●
  ※LEDのONとOFFを ON:● OFF:〇 で表記しています。
  ※動作の写真を掲載しておきました。

 このプログラムを動作させると、スイッチ回路がおかしいのか、プログラムがおかしのかわかります。私は、初めに誤動作箇所を確認してから進めていきます。個人的には、このようなプログラム動作から始めると良いと思います。

//スイッチを定義して今後SW1とする
#define SW1 GP5
#define Led_ON 1
#define Led_OFF 0
#define SW_ON 0
#define SW_OFF 1 

while(1){
        if(SW1 == SW_ON){
            GPIO = 0b00000111;
        }else{
            GPIO = 0b00000001;
        }
}

プログラムのポイント

 (1)今回のプログラムの出力部分になります。変数「led_data」にLEDの状態を代入しています。(3)と(4)は、その処理をしてい   
   ます。
 (2)スイッチを押すと2進数のカウントをするように変数「cnt」+1加算しています。
 (3)1から7まで増えていきます
 (4)ここは、下図のデータシートにも記載しておりますが、「GP3」は入力のみの端子のため、使用できません。よって、4つ目のLED
   を点灯させるために「GP4」を接続しているため、このような処理をしています。
 (5)if文だけを使ったスイッチ処理。ただ、フィルタ回路や遅延を使っていないので、少しおかしな動作をしますが、スイッチ処理とし
   ては問題ないのかなと思います。次は、回路にフィルタを追加して試す価値がありですね
 (6)この処理は、(5)に戻り重要な働きをしています。

        if(SW1 == SW_ON && g_swflag == SW_OFF){ //(5)
            cnt++;//(2)
            if(cnt>7){
                cnt = 0;
                led_data = 0b00010000;//(4)
            }else{
                led_data=cnt;//(3)
            }
            g_flag = 0;
        }
        g_swflag = SW1;//(6)
    //出力
        GPIO = led_data; //(1)
    }//プログラムここまで

(完成)プログラム

完成版です。ぜひコピペで活用してください

/*
 * File:   sw.c
 * Author: TM-kit
 *
 * Created on 2021/12/22, 23:19
 */


#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown Out Detect (BOR disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)

unsigned int g_cnt=0;
unsigned char g_flag=0;
unsigned char g_swflag=0;
int g_delayTime = 500;

#define _XTAL_FREQ 4000000

//スイッチを定義して今後SW1とする
#define SW1 GP5
#define Led_ON 1
#define Led_OFF 0
#define SW_ON 0
#define SW_OFF 1

static void interrupt time0int (void)
{
    if(INTCONbits.T0IF == 1)
    {
        /*タイマーフラグをリセット*/
        INTCONbits.T0IF = 0;
        TMR0=252;/*1m秒ごと*/
        g_cnt++;
        if(g_cnt>g_delayTime)
        {
            g_flag = 1;

            g_cnt=0;//タイマーカウントのリセット
        }       
        //WRITETIMER0(64536);
    }
    
}

void main(void) {
//変数設定
    unsigned char cnt = 0;
    unsigned char led_data = 0;
    
    
    /*手順1:内部クロックの設定:4MHz*/
    /*データシート:P19,P20*/
    OSCCON=0b01101000;

    /*ポートプルアップを使いたい場合は、このオプションレジスタを0で有効にしておく*/
    /*プリスケーラ:256 */
    OPTION_REG=0b00000111;

    /*手順2:ポートデジタルに設定*/
    /*P33(P35)*/
    /*設定全てデジタル & Fosc/64*/
    ANSEL=0b01100000;

    /*手順2:ポートの入出力の設定 1;入力 0:出力*/
    /*今回の設定:GP3は入力のみなので1を立てておく。また、今回は、反省を活かし入力をGP5とします*/
    /*データシート:P36*/    
    TRISIO=0b00101000;

    /*今回の入力は、GP5なのでそこをプルアップする*/
    //WPUbits.WPU5=1;

    /*ポートのデータは何が入っているかわからないので、消灯できるように0をポートに入れておく*/
    GPIO=0b00000100;

    /*念のためにコンパレータを無効にしておく*/
    CMCON0 = 0b00000111;

    GP0=1;
    TMR0 = 252;
    INTCONbits.T0IE = 1;
    INTCONbits.GIE = 1;
    
//プログラム開始前の初期設定    
    led_data = 1;
    cnt = 0;
    g_delayTime = 500;
    g_flag = 0;
    g_swflag = SW1;
    while(1){
        /*
        if(SW1 == SW_ON){
            GPIO = 0b00000111;
        }else{
            GPIO = 0b00000001;
        }
        */
        
        if(SW1 == SW_ON && g_swflag == SW_OFF){
            cnt++;
            if(cnt>7){
                cnt = 0;
                led_data = 0b00010000;
            }else{
                led_data=cnt;
            }
            g_flag = 0;
        }
        g_swflag = SW1;
    //出力
        GPIO = led_data; 
    }//プログラムここまで
    return;
}

まとめ

入力と出力の回路が完成しました。組み込みマイコンは、ハードウェアでの対応やプログラミングでの対応など工夫次第で解決できることが多いです。色々チャレンジしてみてくださいね。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です