信号機

信号機

信号機はPIC16F1933を使って、10個の信号機を点灯します。

PIC16F1933のコード

//***************************
//2021_0606
//***************************

#include <xc.h>
#define _XTAL_FREQ 4000000

#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FOSC =INTOSC

#pragma config FCMEN = OFF
#pragma config MCLRE = OFF
#pragma config WDTE = OFF //ON
#pragma config CP = OFF
#pragma config LVP = OFF
#pragma config PWRTE = ON

#define ExtInt	RB0
#define ExtData	RB1

#define RED0 RA0
#define YEL0 RA1
#define GRN0 RA2

#define GRP0 RA3
#define GRP1 RA4
#define GRP2 RA5
#define GRP3 RC0
#define GRP4 RC1
#define GRP5 RC2
#define GRP6 RC3
#define GRP7 RC4
#define GRP8 RC5
#define GRP9 RC6

#define L_GRN 0b100
#define L_YEL 0b010
#define L_RED 0b001

int IntCount;
unsigned char bit_p;
unsigned char receive_data;
unsigned char data_p;
unsigned char RxData[128];
unsigned char send_data;
unsigned char busy;

unsigned char EnableBit[] = {1, 2, 4, 8, 16, 32, 64, 128};

unsigned char yard_req;
unsigned char yard_num;

unsigned char TrainCount;
unsigned char TrainPos[16];
unsigned char SignalPos[8];
unsigned char grp_chg_count;
unsigned char group;
unsigned char signal[10];
unsigned char sync;
unsigned char data_ready;


void signal_LED(unsigned char);
void Disp(void);
void led_off(void);

//********************************************************

void main(void) {
    unsigned char rosen;
    signed char d;
    signed char d_min;
    unsigned char n, p;


    //最高速32MHz
    OSCCONbits.SPLLEN = 1; //×4 PLL
    OSCCONbits.IRCF = 14; //8MHz

    ANSELA = 0; // アナログ入力 AN8からAN13 を無効
    ANSELB = 0; // アナログ入力 AN0からAN7 を無効

    PORTA = 0;
    PORTB = 0;
    PORTC = 0;

    TRISA = 0;
    TRISB = 0x03; // RB0,1 Input
    TRISC = 0;

    OPTION_REG = 0x0f; // WDT,Int Fall, pulup
    OPTION_REGbits.nWPUEN = 1;

    INTE = 1; // RB0 割り込み許可
    GIE = 1; // 割り込み許可

    SignalPos[0] = 1;
    SignalPos[1] = 9;
    SignalPos[2] = 0x10;

    //    SignalPos[0] = 0;
    //    SignalPos[1] = 1;
    //    SignalPos[2] = 2;
    SignalPos[3] = 3;
    SignalPos[4] = 4;
    SignalPos[5] = 5;
    SignalPos[6] = 6;
    SignalPos[7] = 7;
    SignalPos[8] = 8;
    SignalPos[9] = 9;

    __delay_ms(10); // 10msec


    while (1) {

        CLRWDT();

        //列車位置設定
        if (data_ready) {
            data_ready = 0;
            TrainCount = 0;

            for (n = 0; n < 12; n++) {
                p = n * 8;
                if ((RxData[p] & 0xF0) == 0xA0) {
                    TrainPos[TrainCount++] = RxData[p + 6];
                }
            }
        }


        for (p = 0; p < 10; p++) {
            d_min = 7;
            rosen = SignalPos[p] & 0x38;

            for (n = 0; n < TrainCount; n++) {
                if ((TrainPos[n] & 0x38) == rosen) {
                    d = (TrainPos[n] & 7)-(SignalPos[p] & 7);
                    if (SignalPos[p] & 0x80)
                        d = -d; //シグナル向き逆方向
                    if (d < 0)
                        d += 8;
                    if (d < d_min)
                        d_min = d; //最小値を更新
                }
            }

            if (d_min == 2) {
                //黄信号
                signal[p] = L_YEL;

            } else if (d_min > 2) {
                //青信号
                signal[p] = L_GRN;

            } else if (d_min < 2) {
                //赤信号
                signal[p] = L_RED;

            }

            Disp();

        }
    }
}

void __interrupt() ISR_ExtInt(void) {
    unsigned char inp_bit;
    inp_bit = ExtData;

    INTF = 0; // 割り込みフラグクリア

    IntCount++;
    RB4 = 1;

    if (ExtInt == 0) {
        //--- IntCount 0 ---
        IntCount = 0;

        RB5 = 1;
    }

    grp_chg_count++;

    //Group Change
    if (grp_chg_count == 0x50) {
        grp_chg_count = 0;

        if (++group > 9)
            group = 0;

        sync = 1;
    }


    //受信
    //TRISB1 = 1; //PortInput


    data_p = (IntCount - 1) >> 3;
    bit_p = EnableBit[(IntCount - 1) & 0b111];

    RB3 = 1;

    if (inp_bit)
        receive_data |= bit_p;
    else
        receive_data &= ~bit_p;

    if (bit_p == 0x80) {
        RxData[data_p] = receive_data; //DataSet

        if (data_p == 0x60) {
            data_ready = 1;
        }
    }


    PORTB = 0;
    //    RB4 = 0;
    //    RB5 = 0;
}

void Disp() {
    if (sync) {
        sync = 0;
        led_off();
        //signal_LED(signal[group]);
        PORTA |= signal[group];

        switch (group) {
            case 0:
                GRP0 = 0;
                break;
            case 1:
                GRP1 = 0;
                break;
            case 2:
                GRP2 = 0;
                break;
            case 3:
                GRP3 = 0;
                break;
            case 4:
                GRP4 = 0;
                break;
            case 5:
                GRP5 = 0;
                break;
            case 6:
                GRP6 = 0;
                break;
            case 7:
                GRP7 = 0;
                break;
            case 8:
                GRP8 = 0;
                break;
            case 9:
                GRP9 = 0;
                break;
        }

    }
}

void led_off() {
    PORTA = 0b11111000;
    PORTC = 0b1111111;
}