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

MPLABX XC8 PIC16F84A 例題6

$
0
0
 MPLABX XC8 でPIC16F84Aを使って、今まで勉強したことを応用して、ラーメンタイマー(3分タイマー)を作ってみました。

 表示は7セグメントLEDを使い、スタートボタンを押すと3分(3.00表示)から1秒ごとにカウントダウンし、0.00になったら、ピピピ ピピピとブザーを鳴らします。リセットを押すとまた3.00に戻ります。(スタートボタンは、もう一度押すとカウントストップします)

 電源は、電池2本(3V)です。

 回路図です。
イメージ 2

 7セグメントLEDは、超高輝度の3桁のものC-533SRを使い、ダイナミック点灯表示です。ダイナミック点灯と1秒カウントのために、TMR0割り込みを利用して、6.5536msごとに割り込みをかけています。

ブレッドボードです。

イメージ 1

 プログラムです。

/*
 * PICと7セグメントLEDとの接続
 * PIC  LED
 * RB0  A
 * RB1  B
 * RB2  C
 * RB3  D
 * RB4  E
 * RB5  F
 * RB6  G
 * RB7  DP
 * RA0 #1
 * RA1 #2
 * RA2 #3
 *
 * RA3は、START/STOPスイッチ
 * RA4には、BUZZERを接続する。
 * RESETは、MCLR
 */
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 10000000

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (Power-up Timer is enabled)
#pragma config CP = OFF         // Code Protection bit (Code protection disabled)

 unsigned char digit = 1;
 unsigned char counter = 0;
 unsigned char timer_data[3] = {3,0,0};  //3min 00sec
 signed char work0,work1,work2;//timer用作業レジスタ
 unsigned char val = 1; //input value
 unsigned char old_val = 1;
 unsigned char state = 0; //swtch's state 0=stop
 unsigned char cnt1s = 153;// 6.5536×153 = 1002.7ms
 unsigned char T1s = 0;
 
 unsigned char seg_data[10] = {
        // gfedcba      // data for 7segment LED
        0b00111111,     // 0
        0b00000110,     // 1
        0b01011011,     // 2
        0b01001111,     // 3
        0b01100110,     // 4
        0b01101101,     // 5
        0b01111101,     // 6
        0b00000111,     // 7
        0b01111111,     // 8
        0b01101111      // 9
    };
 
 void interrupt isr(void){
    T0IF = 0; // TMR0割り込みクリア
    cnt1s --;
    if(cnt1s == 0){
        cnt1s = 153;//1sカウンタセット
        T1s = 1;//1s経過フラッグを立てる
    }
    digit <<= 1;
    counter ++;
    if(counter >= 3){
        digit = 1;
        counter = 0;
    }
    PORTA =(PORTA & 0xF0) | digit;
   
    if(digit == 1){
        PORTB = seg_data[timer_data[counter]] | 0x80;//digit0ならDPを表示
    }else{
        PORTB = seg_data[timer_data[counter]];
    }
}
 
//BUZZER音 RA4=0でBUZZER ON
 void beep(){
         while(1){
         RA4 = 0;//ピ
         __delay_ms(200);
         RA4 = 1;
         __delay_ms(200);
         RA4 = 0;//ピ
         __delay_ms(200);
         RA4 = 1;
         __delay_ms(200);
         RA4 = 0;//ピ
         __delay_ms(200);
         RA4 = 1;
         __delay_ms(600);
     }
 }
 void main() {    
     TRISA = 0b00001000;  //RA3 INPUT 他OUTPUT
     TRISB = 0x00;  //PORTB ALL OUTPUT
     PORTA = 0x00;  //PORTA clear
     PORTB = 0x00;  //PORTB clear
     RA4 = 1;//BUZZER OFF
    
     //TMR0関係のセットアップ
     OPTION_REG = 0x85;//prescaler 1:32 interrupt time interval 0.4us×64×256=6.5536ms
     TMR0 = 0x00;   //TMR0 clear
     T0IE = 1;      //TMR0 interrupt enable
     GIE = 1;       //general interrupt enable
   
     while(1){
         val = RA3;
         if((val == 0 )&&(old_val == 1)){
             state = 1 - state;
             __delay_ms(20);
         }
         old_val = val;
        
         if(state){
            if(T1s){
                T1s = 0;//1sフラッグクリア
                work0 = timer_data[0];//min
                work1 = timer_data[1];//10sec
                work2 = timer_data[2];//sec
                work2 --;
                if(work2 < 0){
                    work1 --;
                    work2 = 9;
                }
                if(work1 < 0){
                    work0 --;
                    work1 = 5;
                }
                if((work0 == 0)&&(work1 == 0)&&(work2 == 0)){
                    timer_data[2] = 0;
                    beep();//000になったら、ピピピ
                }
                timer_data[0] = work0;
                timer_data[1] = work1;
                timer_data[2] = work2;  
            }
         }
    }
 }

 今回のトラブルシューティング

 タイマーの基本的なプログラムができ、ブザー音ピピピを出すところで、トラブりました。

 RA4の罠です。RA0~RA3とRA4とでは、IOポートの構造が違うのです。

 RA0~RA3がFETのトーテムポール出力になっているのに対して、RA4は、オープンドレイン出力なのです。

 RA4には、電子ブザーを接続しています。出力0の時、ブザーが鳴るよう負論理になります。

 最後に、ダイナミック点灯に割り込みを使っているせいか、ブザー音のピピピがときどき、ピピーになったりします。
 プログラムで改善できると思うのですが、ま愛嬌ってことでご勘弁を。

 PIC16F84(84A)を使ってMPLABXとXC8の基本的なプログラミングの仕方が勉強できました。

 次は、PIC16F628Aを使って、シリアル通信、A/D変換、SPI、I2Cなどの勉強をしたいと思います。

Viewing all articles
Browse latest Browse all 440

Trending Articles