第5回 デジタル時計にプログラムを書き換える

今回は、

“ロボヨシオ電光掲示板”

のプログラムを変更して作成した“デジタル時計”のご紹介です。

 

マイコンは前回と同じ“PIC16F1827”を使用していて、
内部クロックでカウントしています。
なので、時計としての精度は良くないです。

まだ完成して数日ですが、1日1分ずつくらいずつズレていそうです。
カウント数をプログラム上で補正すれば改善できるかも?
追々検証してみようと思っています。

 

プログラムの概要としては、
・数字の画像データを準備 (上下2段に分けた2つのヘッダーファイル)
・時間に合わせて読み込む配列の値を変更して描画
です。

 

サンプルコードはこちら。

#include <xc.h>
#include <stdio.h>
#include "numup.h"
#include "numdw.h"

#define _XTAL_FREQ 16000000

#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FOSC = INTOSC, FCMEN = OFF 
#pragma config MCLRE = ON, WDTE = OFF, CP = OFF, PWRTE = ON, CLKOUTEN = OFF
#pragma config PLLEN = OFF, WRT = OFF, STVREN = OFF, BORV = LO, LVP = OFF 

//**********************************************************************
///time set///ここで時間をセットしています。
int ts1 = 0;//秒(1の位)
int ts10 = 0; //秒(10の位)
int tm1 = 0; //分(1の位)
int tm10 = 0; //分(10の位)
int th1 = 0; //時(1の位)
int th10 = 0; //時(10の位)
//**********************************************************************



//**********************************************************************
///割り込み処理///
void intrInit(){
    T1CON = 0b00100001;
    TMR1H =(55536 >> 8);
    TMR1L = (55536 & 0x00ff);
    TMR1IF = 0;
    TMR1IE = 1;
    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;
}

void __interrupt() isr(void){
    volatile static int intr_counter;
    GIE = 0;
    if(TMR1IF == 1){
        TMR1H = (55536>>8);
        TMR1L = (55536 & 0x00ff);
        
        intr_counter++;
        if(intr_counter == 100){
            ts1++;
            intr_counter = 0;
            
            if(ts1 == 10){
            ts1 = 0;
            ts10++;
            
                if(ts10 == 6){
                    ts10 = 0;
                    tm1++;
                    
                    if(tm1 == 10){
                        tm1 = 0;
                        tm10++;
                        
                        if(tm10 == 6){
                            tm10 = 0;
                            th1++;
                            
                            if(th1 == 10){
                                th1 = 0;
                                th10++;                                
                                }
                            }
                        }
                    }
                }    
        }
        //24h de 0 reset
        if((th10 == 2)&&(th1 == 4)){
        th1 = 0;
        th10 = 0;
        }
        //LED change(目のLEDを午前と午後で青/赤 点灯色の切り替え)
        if(((th10 == 1)&&(th1 <= 1)) || (th10 == 0)){
        RA1=0;
        RA2=0;
        RA0=1;
        RA3=1;
        }else{
        RA1=1;
        RA2=1;
        RA0=0;
        RA3=0;
        }
        //
        TMR1IF =0;
    }
    GIE = 1;
}
///
//**********************************************************************

//**********************************************************************
void i2c_start();
void i2c_stop();
void i2c_write(unsigned char byte);

void oled_ini(void);
void oled_clr(void);
//**********************************************************************

void main(void)
{
TRISA = 0b00000000;
TRISB = 0b00010010;
PORTA = 0b00000000;
PORTB = 0b00000000;
ANSELA = 0b00000000;
ANSELB = 0b00000000;
OSCCON = 0b01111100;//16MHz
SSP1CON1 = 0b00101000;
SSP1STAT = 0b10000000;
SSP1ADD = 0b00100111;

intrInit();

oled_ini();
oled_clr();

unsigned int k;

//*********************************************************************
    
while(1){
//**********************************************************************
//*start time image draw ready*//
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0xA7); //
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x00); // Horizontal addressing mode
i2c_write(0x21); // Set column address
i2c_write(0x13); // Column start address 0
i2c_write(0x6C); // Column end address 127d
i2c_write(0x22); // Set page address
i2c_write(0x05); // Page start address 0
i2c_write(0x06); // Page end address 7d
i2c_stop();
//*start time image draw*//
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1
for(k=0; k<9; k++)
i2c_write(numup[k][13]);
for(k=0; k<9; k++)
i2c_write(numup[k][12]);
for(k=0; k<9; k++)
i2c_write(numup[k][th10]);
for(k=0; k<9; k++)
i2c_write(numup[k][th1]);
for(k=0; k<9; k++)
i2c_write(numup[k][10]);
for(k=0; k<9; k++)
i2c_write(numup[k][tm10]);
for(k=0; k<9; k++)
i2c_write(numup[k][tm1]);
for(k=0; k<9; k++)
i2c_write(numup[k][11]);
for(k=0; k<9; k++)
i2c_write(numup[k][ts10]);
for(k=0; k<9; k++)
i2c_write(numup[k][ts1]);

////////////////////////////

for(k=0; k<9; k++)
i2c_write(numdw[k][13]);
for(k=0; k<9; k++)
i2c_write(numdw[k][12]);
for(k=0; k<9; k++)
i2c_write(numdw[k][th10]);
for(k=0; k<9; k++)
i2c_write(numdw[k][th1]);
for(k=0; k<9; k++)
i2c_write(numdw[k][10]);
for(k=0; k<9; k++)
i2c_write(numdw[k][tm10]);
for(k=0; k<9; k++)
i2c_write(numdw[k][tm1]);
for(k=0; k<9; k++)
i2c_write(numdw[k][11]);
for(k=0; k<9; k++)
i2c_write(numdw[k][ts10]);
for(k=0; k<9; k++)
i2c_write(numdw[k][ts1]);

i2c_stop();
}

}// main
//**********************************************************************



//**********************************************************************
void oled_ini(void)
{
    i2c_start();
    i2c_write(0x78); // OLED slave address
    i2c_write(0x00); // Control byte Co=0, D/C#=0
    i2c_write(0x8D); // Set charge pump
    i2c_write(0x14); // Enable charge pump
    i2c_write(0x81);
    i2c_write(0x0F);
    i2c_write(0xAF); // Display ON
    i2c_stop();
}
//**********************************************************************

//**********************************************************************
void oled_clr(void)
{
    unsigned int i;

    i2c_start();
    i2c_write(0x78); // OLED slave address
    i2c_write(0x00); // Control byte Co=0, D/C#=0
   i2c_write(0x20); // Set memory addressing mode
    i2c_write(0x00); // Horizontal addressing mode
    i2c_write(0x21); // Set column address
    i2c_write(0x00); // Column start address 0
    i2c_write(0x7F); // Column end address 127d
    i2c_write(0x22); // Set page address
    i2c_write(0x00); // Page start address 0
    i2c_write(0x07); // Page end address 7d
    i2c_stop();

    i2c_start();
    i2c_write(0x78); // OLED slave address
    i2c_write(0x40); // Control byte Co=0, D/C#=1

    for(i=0; i<1024; i++) // 128culomn * 8page
    i2c_write(0xFF); // filled with 0 (OLED clear)

    i2c_stop();

}
//**********************************************************************

//**********************************************************************
void i2c_start()
{
    SSP1CON2bits.SEN = 1;
    while(SSP1CON2bits.SEN);
}
//**********************************************************************

//**********************************************************************
void i2c_stop()
{
    SSP1CON2bits.PEN = 1;
    while(SSP1CON2bits.PEN);
}
//**********************************************************************

//**********************************************************************
void i2c_write(unsigned char byte)
{
    PIR1bits.SSP1IF = 0;
    SSP1BUF = byte;
    while(!PIR1bits.SSP1IF);
    SSP1CON1bits.CKP = 1;
}
//**********************************************************************
const char numup[9][14]=
{
{0x07,0xFF,0xC7,0xC7,0xFF,0x01,0x03,0xE1,0x87,0x07,0xFF,0xFF,0xFF,0x1F},
{0x03,0xF7,0xC3,0xC3,0x3F,0x01,0x01,0xE1,0x03,0x03,0xFF,0xFF,0xFF,0xCF},
{0xE1,0xF3,0xE1,0xE1,0x0F,0x39,0x31,0xF9,0x31,0x71,0xCF,0xFF,0xFF,0xE7},
{0xF1,0x01,0xF1,0x71,0xC3,0x39,0x39,0xF9,0x79,0xF9,0x87,0xFF,0xFF,0xF3},
{0xF1,0x01,0xF1,0x71,0xF3,0x39,0x39,0xF9,0x79,0xF9,0x87,0xFF,0xFF,0x13},
{0xE1,0xFF,0xE1,0x61,0x01,0x39,0x31,0x79,0x31,0x71,0xCF,0xFF,0xFF,0x73},
{0x03,0xFF,0x03,0x03,0x01,0x79,0x63,0x01,0x03,0x03,0xFF,0xFF,0xFF,0x67},
{0x07,0xFF,0x07,0x07,0xFF,0xFF,0xE7,0x01,0x87,0x07,0xFF,0xFF,0xFF,0xCF},
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F}
};
const char numdw[9][14]=
{
{0xE0,0xFF,0x9F,0xE3,0xF0,0xE6,0xE0,0xFF,0xE0,0xE7,0xFF,0xFF,0xFF,0xFC},
{0xC0,0x9F,0x8F,0xC3,0xF0,0xC6,0xC0,0xFF,0xC0,0xC6,0xFF,0xFF,0xFF,0x99},
{0x87,0x9F,0x87,0x87,0xF3,0x8F,0x8E,0xFF,0x8C,0x8C,0xF3,0xFF,0xFF,0x83},
{0x8F,0x80,0x83,0x8E,0xF3,0x9F,0x9F,0x81,0x9E,0x9C,0xE1,0x9F,0xFF,0x87},
{0x8F,0x80,0x91,0x8E,0xF3,0x9F,0x9F,0x80,0x9E,0x9C,0xE1,0x9F,0xFF,0x87},
{0x87,0x9F,0x98,0x86,0x80,0x8E,0x8E,0xFC,0x8C,0x8C,0xF3,0xFF,0xFF,0x87},
{0xC0,0x9F,0x9C,0xC0,0x80,0xC0,0xC0,0xFE,0xC0,0x80,0xFF,0xFF,0xFF,0x83},
{0xE0,0xFF,0x9E,0xE1,0xF3,0xE0,0xE0,0xFF,0xE0,0xC0,0xFF,0xFF,0xFF,0x99},
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC}
};

まだ容量も空きがあるので、
カレンダー機能を付けたりも出来ると思います。

何かの参考にしていただければ幸いです。

 

関連記事はこちらのリンクからどうぞ♪
PICマイコンでOLED制御に挑む! 第1回
PICマイコンでOLED制御に挑む! 第2回
PICマイコンでOLED制御に挑む! 第3回
PICマイコンでOLED制御に挑む! 第4回
PICマイコンでOLED制御に挑む! 第5回