PICマイコンでOLED制御に挑む! 第5回
●第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回
コメントを残す