目次

簡易スクロール・クロック(PIC18F2620)

概要

以前に8×8ドットマトリクスを使用して製作した、簡易レベルメータ(8チャネル×8ドット)を少しだけ改良して、
時刻表示をスクロール表示させる時計を製作しました。

<仕様>

動作原理(ハードウェア)

◎時刻の表示
8×8のドットマトリクスに時刻(時分秒)をスクロール表示させます。
1文字のドット構成は、下図のようになります。

動作原理(ソフトウェア)

◎メイン処理

◎割り込み処理

◎ダイナミック点灯処理

◎スクロール処理

回路図

ソースコード

clock_led_8x8.c
//**********************************************************************
/*
  <簡易スクロール・クロック> 
*/
//**********************************************************************
extern  void    main();
extern  void    init_timer();
extern  void    interrupt();
extern  void    data_set(short p, char *dt);
extern  void    clock_data_set(short hh, short mm, short ss);
extern  void    data_scroll();
extern  long    clock_msec;
extern  short   lock;
//**********************************************************************
#define  LOCK      1
#define  UNLOCK    0
#define  SW_HH_UP  PORTA.B0
#define  SW_MM_UP  PORTA.B1
#define  SW_PAUSE  PORTA.B2
//**********************************************************************
char    view_data[8];
char    clock_data[48];
char    data_0[] = {
        0b01111100,
        0b01000100,
        0b01111100,
        0b00000000
};
char    data_1[] = {
        0b00100000,
        0b01111100,
        0b00000000,
        0b00000000
};
char    data_2[] = {
        0b01011100,
        0b01010100,
        0b01110100,
        0b00000000
};
char    data_3[] = {
        0b01010100,
        0b01010100,
        0b01111100,
        0b00000000
};
char    data_4[] = {
        0b01110000,
        0b00010000,
        0b01111100,
        0b00000000
};
char    data_5[] = {
        0b01110100,
        0b01010100,
        0b01011100,
        0b00000000
};
char    data_6[] = {
        0b01111100,
        0b01010100,
        0b01011100,
        0b00000000
};
char    data_7[] = {
        0b01110000,
        0b01000000,
        0b01111100,
        0b00000000
};
char    data_8[] = {
        0b01111100,
        0b01010100,
        0b01111100,
        0b00000000
};
char    data_9[] = {
        0b01110100,
        0b01010100,
        0b01111100,
        0b00000000
};
char    data_space[] = {
        0b00000000,
        0b00000000,
        0b00000000,
        0b00000000
};
char    data_colon[] = {
        0b00000000,
        0b00101000,
        0b00000000,
        0b00000000
};
char    *data_num_table[] = {
        data_0,
        data_1,
        data_2,
        data_3,
        data_4,
        data_5,
        data_6,
        data_7,
        data_8,
        data_9
};
//**********************************************************************
//■■■データセット関数■■■ 
void    data_set(short p, char *dt)
{
        memcpy(&clock_data[p * 4], dt, 4);
}
//**********************************************************************
//■■■時刻データセット関数■■■ 
void    clock_data_set(short hh, short mm, short ss)
{
        data_set(0, data_space);
        data_set(1, data_space);
        data_set(2, data_num_table[Dec2Bcd(hh) >> 4]);
        data_set(3, data_num_table[Dec2Bcd(hh) & 0x0F]);
        data_set(4, data_colon);
        data_set(5, data_num_table[Dec2Bcd(mm) >> 4]);
        data_set(6, data_num_table[Dec2Bcd(mm) & 0x0F]);
        data_set(7, data_colon);
        data_set(8, data_num_table[Dec2Bcd(ss) >> 4]);
        data_set(9, data_num_table[Dec2Bcd(ss) & 0x0F]);
        data_set(10, data_space);
        data_set(11, data_space);
}
//**********************************************************************
//■■■データスクロール関数■■■ 
short   scroll_pnt = 0;
void    data_scroll()
{
        memcpy(view_data, &clock_data[scroll_pnt], 8);
        scroll_pnt++;
        if (scroll_pnt == 41) {
                scroll_pnt = 0;
        }
}
//**********************************************************************
//■■■メイン関数■■■ 
void    main()
{
        short   cnt, hh, mm, ss;
        long    tmp;
        //クロックを8MHzに設定します。 
        OSCCON.IRCF2 = 1;
        OSCCON.IRCF1 = 1;
        OSCCON.IRCF0 = 1;
        //
        TRISA = 0b11111111;
        TRISB = 0b00000000;
        TRISC = 0b00000000;
        //A/D変換を使用しません。 
        ADCON1.PCFG3 = 1;
        ADCON1.PCFG2 = 1;
        ADCON1.PCFG1 = 1;
        ADCON1.PCFG0 = 1;
        //TIMERを設定(1msec周期)します。 
        init_timer();
        // 割り込みを許可します。 
        INTCON.PEIE = 1;
        INTCON.GIE = 1;
        //
        while (1) {
                tmp = clock_msec / 1000;
                hh = tmp / 3600;
                mm = (tmp % 3600) / 60;
                ss = tmp % 60;
                //
                if (SW_HH_UP == 0) {
                        hh++;
                        ss = 0;
                        if (hh == 12) {
                                hh = 0;
                        }
                        lock = LOCK;
                        clock_msec = (((long)hh * 3600) + ((long)mm * 60) + (long)ss) * 1000;
                        lock = UNLOCK;
                        scroll_pnt = 8;
                }
                if (SW_MM_UP == 0) {
                        mm++;
                        ss = 0;
                        if (mm == 60) {
                                mm = 0;
                        }
                        lock = LOCK;
                        clock_msec = (((long)hh * 3600) + ((long)mm * 60) + (long)ss) * 1000;
                        lock = UNLOCK;
                        scroll_pnt = 20;
                }
                //
                clock_data_set(hh, mm, ss);
                if (SW_PAUSE == 1) {
	                data_scroll();
	        }
                //
                Delay_ms(200);
        }
}
//**********************************************************************
//■■■タイマー初期化関数■■■ 
void    init_timer()
{
        T2CON.T2CKPS1 = 0;
        T2CON.T2CKPS0 = 0;
        T2CON.T2OUTPS3 = 1;
        T2CON.T2OUTPS2 = 1;
        T2CON.T2OUTPS1 = 1;
        T2CON.T2OUTPS0 = 1;
        TMR2 = 0;
        PIE1.TMR2IE = 1;
        PIR1.TMR2IF = 0;
        PR2 = 125;        //125=1msec/((1sec/8MHz)*4*16PS)
        T2CON.TMR2ON = 1;
}
//**********************************************************************
//■■■割り込み関数■■■ 
short   bar = 0;
long    clock_msec = 0;
short   lock = UNLOCK;
void    interrupt()
{
        if (PIR1.TMR2IF == 1) {
                PIR1.TMR2IF = 0;
                //
                switch (bar) {
                case 0:
                        PORTB = view_data[0];
                        PORTC = 0b11111110;
                        bar++;
                        break;
                case 1:
                        PORTB = view_data[1];
                        PORTC = 0b11111101;
                        bar++;
                        break;
                case 2:
                        PORTB = view_data[2];
                        PORTC = 0b11111011;
                        bar++;
                        break;
                case 3:
                        PORTB = view_data[3];
                        PORTC = 0b11110111;
                        bar++;
                        break;
                case 4:
                        PORTB = view_data[4];
                        PORTC = 0b11101111;
                        bar++;
                        break;
                case 5:
                        PORTB = view_data[5];
                        PORTC = 0b11011111;
                        bar++;
                        break;
                case 6:
                        PORTB = view_data[6];
                        PORTC = 0b10111111;
                        bar++;
                        break;
                case 7:
                        PORTB = view_data[7];
                        PORTC = 0b01111111;
                        bar = 0;
                        break;
                }
                //
                if (lock == UNLOCK) {
                        clock_msec++;
                        if (clock_msec == 43200000) {
                                clock_msec = 0;
                        }
                }
        }
} 
//**********************************************************************

動作確認

9時23分26秒をスクロール表示しているところです。

如何でしょうか?

クロックには、PIC内蔵の8MHzを使用しているので、あまり高い精度は望めません。
しかし、OSCTUNEレジスタの値を変更して、キャリブレーションを行えば、市販されている安価な時計と同等の精度が得られるのではないでしょうか。

著作権表示 copyright notice

このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。詳細
This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.Details