回路図

stopwatch

回路図の説明をします。

ストップウォッチを操作するスイッチは3個で、SW1が【リセットスイッチ】、SW2が【スタートスイッチ】、SW3が【ストップスイッチ】です。

PICマイコンは8bitのPIC16F1933(U1)を使用しています。

7セグメントLED用ドライバはTD62083 (U2) で、8chのダーリントンシンクドライバです。

7セグメントLEDは、4桁カソードコモンタイプを2個使用し、8桁のストップウォッチです。使用するLEDにあわせてR1~R8の抵抗値を決定します。

水晶発振子は、8MHzです。

ソフトウエア

ソースコード

/*
 * File:   stop_watch.c
 * Author: masan
 *
 * Created on 2017/02/19, 19:31
 */

//--------------- ハードウエア -------------------------------------------------
//  RA0(2pin)   in  RESET_SWスイッチ
//  RA1(3pin)   in  START_SWスイッチ
//  RA2(4pin)   in  STOP_SWスイッチ
//  RA3(5pin)   out TEST1 
//  RA4(6pin)   out TEST2
//  RA5(7pin)   out TEST3
//  RA6(10pin)  in  OSC2
//  RA7(9pin)   in  OSC1
//  RB0(21pin)  out 7セグメントLED b
//  RB1(22pin)  out 7セグメントLED f
//  RB2(23pin)  out 7セグメントLED a
//  RB3(24pin)  out 7セグメントLED g
//  RB4(25pin)  out 7セグメントLED c
//  RB5(26pin)  out 7セグメントLED DP
//  RB6(27pin)  out 7セグメントLED d        ICSPCLK
//  RB7(28pin)  out 7セグメントLED e        ICSPDAT
//  RC0(11pin)  out 7セグメント桁表示 s1
//  RC1(12pin)  out 7セグメント桁表示 ms100
//  RC2(13pin)  out 7セグメント桁表示 ms10
//  RC3(14pin)  out 7セグメント桁表示 ms1
//  RC4(15pin)  out 7セグメント桁表示 h1
//  RC5(16pin)  out 7セグメント桁表示 m10
//  RC6(17pin)  out 7セグメント桁表示 m1
//  RC7(18pin)  out 7セグメント桁表示 s10
//  RE3(1pin)   in  MCLR
//  Vdd(20pin)
//  Vss(8pin,19pin)


// PIC16F1933 Configuration Bit Settings

// 'C' source line config statements 

// CONFIG1
#pragma config FOSC = HS        // Oscillator Selection (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config VCAPEN = OFF     // Voltage Regulator Capacitor Enable (All VCAP pin functionality is disabled)
#pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

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

#include <xc.h>

//*************************** 関数 *********************************************
void shutoff_LED(void);                         //LEDをすべて消灯する
void display_LED(void);                         //LED表示する
void display_ready(void);                       //レディ表示
unsigned char trans_7seg(unsigned char data);   //バイナリデータを7セグメントLEDの表示データに変換する
void delay(void);                               //チャタリング防止delay

//************************* クローバル変数設定 **********************************
unsigned char ready_flag = 0;   //1でレディ 0でノーマル
unsigned char start_flag = 0;   //1でスタート 0でストップ
unsigned char ms1_reg = 0;
unsigned char ms10_reg = 0;
unsigned char ms100_reg = 0;
unsigned char s1_reg = 0;
unsigned char s10_reg = 0;
unsigned char m1_reg = 0;
unsigned char m10_reg = 0;
unsigned char h1_reg = 0;
unsigned char display_degit = 0; //LED表示の位置を表す


//***************************** ポートの定義 ***********************************
#define RESET_SW    PORTAbits.RA0       //RESET_SWスイッチ
#define START_SW    PORTAbits.RA1       //START_SWスイッチ
#define STOP_SW     PORTAbits.RA2       //STOP_SWスイッチ
#define degit_ms1   PORTCbits.RC3       //7セグメント桁表示 mSec 1桁       
#define degit_ms10  PORTCbits.RC2       //7セグメント桁表示 mSec 10の桁
#define degit_ms100 PORTCbits.RC1       //7セグメント桁表示 mSec 100の桁
#define degit_s1    PORTCbits.RC0       //7セグメント桁表示 秒 1桁
#define degit_s10   PORTCbits.RC7       //7セグメント桁表示 秒 10の桁
#define degit_m1    PORTCbits.RC6       //7セグメント桁表示 分  1の桁
#define degit_m10   PORTCbits.RC5       //7セグメント桁表示 分  10の桁
#define degit_h1    PORTCbits.RC4       //7セグメント桁表示 時 1桁
#define TEST1       PORTAbits.RA3       //TEST1
#define TEST2       PORTAbits.RA4       //TEST2
#define TEST3       PORTAbits.RA5       //TEST3

//********************** チャタリング防止delay **********************************
//  入力    なし
//  処理    チャタリング防止delay
//  出力    なし
//******************************************************************************
void delay(void){                               //チャタリング防止delay
    unsigned int x,y;
    for(x = 0; x < 500; x++){
//        for(y = 0; y < 5; y++){}
    }
    
}

//************ バイナリデータを7セグメントLEDの表示データに変換する **************
//  入力    data
//  処理    バイナリデータを7セグメントLEDの表示データに変換する
//  出力    LED表示データ
//******************************************************************************
unsigned char trans_7seg(unsigned char data){   //バイナリデータを7セグメントLEDの表示データに変換する
    unsigned char x;
    switch(data){
        case 0: x = 0xd7; break; 
        case 1: x = 0x11; break; 
        case 2: x = 0xcd; break;
        case 3: x = 0x5d; break;
        case 4: x = 0x1b; break;
        case 5: x = 0x5e; break;
        case 6: x = 0xde; break;
        case 7: x = 0x17; break;
        case 8: x = 0xdf; break;
        case 9: x = 0x5f; break;    
    }
    return x;
}

//***************** Timer2 割り込み処理 *****************************************
void interrupt ISR(void){
    TEST1 = 1;

    //カウントする
    if(start_flag == 1){
        ms1_reg++;                                              //msec+1   
        if(ms1_reg == 10){                                   
            ms1_reg = 0;    ms10_reg++;                         //10msec+1
            if(ms10_reg == 10){
                ms10_reg = 0;   ms100_reg++;                    //100msec+1
                if(ms100_reg == 10){
                    ms100_reg = 0;  s1_reg++;                   //1sec+1
                    if(s1_reg == 10){
                        s1_reg = 0;     s10_reg++;              //10sec+1
                        if(s10_reg == 6){
                            s10_reg = 0;    m1_reg++;           //1minute+1
                            if(m1_reg == 10){
                                m1_reg = 0;     m10_reg++;      //10minute+1
                                if(m10_reg == 6){
                                    m10_reg = 0;    h1_reg++;   //1hour+1
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    if(ready_flag == 1) display_ready();                //READY 表示
    else                display_LED();                //カウント表示する
    
    PIR1bits.TMR2IF = 0;    //タイマー2割り込みフラグクリア
    TEST1 = 0; 
} 
//******************* READY 表示 ***********************************************
//  入力    s1_reg
//  処理    READYの表示を行う
//  出力    
//******************************************************************************
void display_ready(void){
    //-------------------- レディ表示 ------------------------------
    switch(display_degit){
        case 0: //hour 1の桁
            degit_ms1 = 0;  if(s1_reg == 0) PORTB = 0xdf;  else    PORTB = 0;  degit_h1 = 1;
            display_degit = 1;    
            break;   
        case 1: //Minute 10の桁
            degit_h1 = 0;   if(s1_reg == 1) PORTB = 0x17;  else    PORTB = 0;  degit_m10 = 1;
            display_degit = 2;    
            break;   
        case 2: //Minute 1の桁
            degit_m10 = 0;  if(s1_reg == 2) PORTB = 0xde;  else    PORTB = 0;  degit_m1 = 1;
            display_degit = 3;    
            break;       
        case 3: //Sec 10の桁 
            degit_m1 = 0;   if(s1_reg == 3) PORTB = 0x5e;  else    PORTB = 0;  degit_s10 = 1; 
            display_degit = 4;    
            break;   
        case 4: //Sec 1の桁 
            degit_s10 = 0;  if(s1_reg == 4) PORTB = 0x1b;  else    PORTB = 0;  degit_s1 = 1;
            display_degit = 5;    
            break;   
        case 5: //mSec 100の桁 
            degit_s1 = 0;   if(s1_reg == 5) PORTB = 0x5d;  else    PORTB = 0;  degit_ms100 = 1; 
            display_degit = 6;    
            break;       
        case 6: //mSec 10の桁 
            degit_ms100 = 0;  if(s1_reg == 6) PORTB = 0xcd;  else    PORTB = 0;  degit_ms10 = 1;
            display_degit = 7;    
            break;       
        case 7: //mSec 1の桁      
            degit_ms10 = 0; if(s1_reg == 7) PORTB = 0x11;  else    PORTB = 0;  degit_ms1 = 1;
            display_degit = 0;    
            break;       
    } 
}
//******************* LED 表示 *************************************************
//  入力    display_degit
//  処理    display_degitの桁の表示を行う
//  出力    display_degit
//******************************************************************************
void display_LED(void){
    unsigned x;
    //-------------------- カウント表示 ----------------------------------------
    switch(display_degit){
        case 0: //hour 1の桁
            x = trans_7seg(h1_reg) | 0x20;                              //バイナリデータを7セグメントLEDの表示データに変換する
            degit_ms1 = 0;  PORTB = x;  PORTB = x;   degit_h1 = 1;      //LED 表示
            display_degit = 1;    
            break;   
        case 1: //Minute 10の桁
            x = trans_7seg(m10_reg);                                    //バイナリデータを7セグメントLEDの表示データに変換する
            degit_h1 = 0;   PORTB = x;  PORTB = x;  degit_m10 = 1;      //LED 表示
            display_degit = 2;    
            break;   
        case 2: //Minute 1の桁
            x = trans_7seg(m1_reg) | 0x20;                              //バイナリデータを7セグメントLEDの表示データに変換する
            degit_m10 = 0;  PORTB = x;   PORTB = x;   degit_m1 = 1;     //LED 表示
            display_degit = 3;    
            break;       
        case 3: //Sec 10の桁 
            x = trans_7seg(s10_reg);                                    //バイナリデータを7セグメントLEDの表示データに変換する
            degit_m1 = 0;   PORTB = x;  PORTB = x;  degit_s10 = 1;      //LED 表示
            display_degit = 4;    
            break;   
        case 4: //Sec 1の桁 
            x = trans_7seg(s1_reg) | 0x20;                             //バイナリデータを7セグメントLEDの表示データに変換する
            degit_s10 = 0;    PORTB = x; PORTB = x;   degit_s1 = 1;     //LED 表示
            display_degit = 5;    
            break;   
        case 5: //mSec 100の桁 
            x = trans_7seg(ms100_reg);                                  //バイナリデータを7セグメントLEDの表示データに変換する
            degit_s1 = 0; PORTB = x;    PORTB = x;  degit_ms100 = 1;    //LED 表示
            display_degit = 6;    
            break;       
        case 6: //mSec 10の桁 
            x = trans_7seg(ms10_reg);                                   //バイナリデータを7セグメントLEDの表示データに変換する
            degit_ms100 = 0;  PORTB = x;    PORTB = x;  degit_ms10 = 1; //LED 表示
            display_degit = 7;    
            break;       
        case 7: //mSec 1の桁      
            x = trans_7seg(ms1_reg) | 0x20;                             //バイナリデータを7セグメントLEDの表示データに変換する
            degit_ms10 = 0; PORTB = x;   PORTB = x;   degit_ms1 = 1;    //LED 表示
            display_degit = 0;    
            break;       
    }           
}



//******************* LED 消灯 ************************************************
//  入力    degit_ms1,degit_ms10,degit_ms100,degit_s1,degit_s10,degit_m1,degit_m10,degit_h1
//  処理    LEDをすべて消灯する
//  出力    degit_ms1,degit_ms10,degit_ms100,degit_s1,degit_s10,degit_m1,degit_m10,degit_h1
//******************************************************************************
void shutoff_LED(void){
    degit_ms1 = 0;  degit_ms10 = 0; degit_ms100 = 0;
    degit_s1  = 0;  degit_s10  = 0;
    degit_m1  = 0;  degit_m10  = 0;
    degit_h1  = 0;
}





//******************************************************************************
//************************ メインプログラム *************************************
void main(void) {
    //--- システム クロック設定(32MHz)---
  
    //入出力ポートの設定
    TRISA = 0xc7;   ANSELA = 0;
    TRISB = 0x00;   ANSELB = 0;     
    TRISC = 0x00;
    
    //--- LED 消灯 ---
    shutoff_LED();                         //LEDをすべて消灯する
    
    //--- タイマー2(1mSec)設定 割り込み設定 ---
    T2CONbits.T2CKPS = 3;   //32MHz/4=8MHz 8MHz/64=125kHz
    PR2 = 124;              //125kHz/(124+1)=1kHz(1mSEC)
    T2CONbits.T2OUTPS = 0;  //1:1
    T2CONbits.TMR2ON = 1;   //Timer2 ON
    
    PIR1bits.TMR2IF = 0;    //タイマー2割り込みフラグクリア
    PIE1bits.TMR2IE = 1;    //タイマー2割り込み可
    INTCONbits.GIE = 1;     //割り込み可
    INTCONbits.PEIE = 1;    //周辺機能割り込み可
    
    
    
    //----------- 繰り返し処理 ----------------
    while(1){
        //------------ READY処理(7.92Secを検出) -----------------------
        if(ready_flag == 1 && ms1_reg == 0){
            if(ms10_reg == 2){
                if(ms100_reg == 9){
                    if(s1_reg == 7){
                        if(s10_reg == 0){
                            if(m1_reg == 0){
                                if(m10_reg == 0){
                                    if(h1_reg == 0){
                                        ready_flag =0;                                  //カウントする
                                        ms1_reg = 0;    ms10_reg = 0;   ms100_reg = 0;
                                        s1_reg = 0;     s10_reg = 0;
                                        m1_reg = 0;     m10_reg = 0;
                                        h1_reg = 0;   
                                    }
                                }
                            }           
                        }
                    }
                }
            }
        }

        //------------- キー入力処理 --------------------
        if(RESET_SW == 0){
            ready_flag = 1;                                 //レディにする
            start_flag = 0;                                 //1でスタート 0でストップ
            ms1_reg = 0;    ms10_reg = 0;   ms100_reg = 0;
            s1_reg = 0;     s10_reg = 0;
            m1_reg = 0;     m10_reg = 0;
            h1_reg = 0;   
            delay();                                        //チャタリング防止delay  
        }
        else if(START_SW == 0){
            start_flag = 1;                                 //1でスタート 0でストップ
            delay();                                        //チャタリング防止delay
        }
        else if(STOP_SW == 0){
            start_flag = 0;                                 //1でスタート 0でストップ
            delay();                                        //チャタリング防止delay
        } 
    } 
}