セラロックによるPIC時計

セラロックの精度によるPIC時計をブレッドボード上に組んでみました。

PIC時計(セラロックのみ)

PIC時計(セラロックのみ)


動かし始めたのは23:38で、4:31に誤差を確認しました。
経過時間は293分で、PIC時計は14分遅れました。
誤差は5%近くなります。
セラロックの精度は±0.5%なので、10倍も誤差が大きいので他の要因が大きいのかも知れません。

回路図は以下の通りです。LEDに付けた抵抗はすべて1.2kΩです。

PIC時計(セラロックのみ)

PIC時計(セラロックのみ)

動かしたのは以下のソースコード(動かしたありのままで整理していないので、途中でテスト的に入れた意味のないコードも入っています)。
コンパイラはHI-TECH C PRO Liteモードです。

#include <pic.h>

__CONFIG(XT & WDTDIS & PWRTEN & BOREN & LVPDIS & UNPROTECT);

// タイマーの設定
#define PERIOD	1000000		// period in uS - one second here
#define XTAL	4000000		// crystal frequency - 4MHz

#define IPERIOD	(4 * 1000000 / XTAL)	// Period of instruction clock in uSeconds

#define SCALE    256	// Timer 0 prescaler
#define T0_TICKS 256	// Number of counts for interrupt

#define TICK_PERIOD (SCALE * IPERIOD)	// Period (uSec) of one increment of timer 0

#define	RELOADS	((PERIOD/T0_TICKS)/TICK_PERIOD)

near char reload = 0;

// GLOBALS
unsigned char counter1 = 0;
unsigned char dp;
unsigned char sec = 0;
unsigned char min = 0;
unsigned char hour = 0;
unsigned char selector = 0;

void interrupt timer0_proc(void)
{
	if(reload == 0){
		// effect a change on PORTB whenever our desired period is reached.
		// Note this timing will contain a margin of error.
		reload = RELOADS + 1;
		sec++;
		if (sec > 59) {
			sec = 0;
			min++;
			if (min > 59) {
				min = 0;
				hour++;
				if (hour > 23) {
					hour = 0;
				}
			}
		}
		RB0 = !RB0;
		RB1 = !RB1;
	}
	reload--;
	T0IF = 0;
}

void delay(unsigned char t)
{
	for (unsigned char a = 0; a < t; a++) {
		for (unsigned char b = 0; b < 255; b++) {
		}
	}
}

void selectDigit(unsigned char sel)
{
	switch (sel) {
	case 0:
		RC0 = 0;
		RC1 = 1;
		RC2 = 1;
		RC3 = 1;
		break;
	case 1:
		RC0 = 1;
		RC1 = 0;
		RC2 = 1;
		RC3 = 1;
		break;
	case 2:
		RC0 = 1;
		RC1 = 1;
		RC2 = 0;
		RC3 = 1;
		break;
	case 3:
		RC0 = 1;
		RC1 = 1;
		RC2 = 1;
		RC3 = 0;
		break;
	default:
		RC0 = 1;
		RC1 = 1;
		RC2 = 1;
		RC3 = 1;
		return;
	}
}

void outputDigit(unsigned char val)
{
	switch (val) {
	case 0:
		RD0 = 1;
		RD1 = 1;
		RD2 = 1;
		RD3 = 1;
		RD4 = 1;
		RD5 = 1;
		RD6 = 0;
		break;
	case 1:
		RD0 = 0;
		RD1 = 1;
		RD2 = 1;
		RD3 = 0;
		RD4 = 0;
		RD5 = 0;
		RD6 = 0;
		break;
	case 2:
		RD0 = 1;
		RD1 = 1;
		RD2 = 0;
		RD3 = 1;
		RD4 = 1;
		RD5 = 0;
		RD6 = 1;
		break;
	case 3:
		RD0 = 1;
		RD1 = 1;
		RD2 = 1;
		RD3 = 1;
		RD4 = 0;
		RD5 = 0;
		RD6 = 1;
		break;
	case 4:
		RD0 = 0;
		RD1 = 1;
		RD2 = 1;
		RD3 = 0;
		RD4 = 0;
		RD5 = 1;
		RD6 = 1;
		break;
	case 5:
		RD0 = 1;
		RD1 = 0;
		RD2 = 1;
		RD3 = 1;
		RD4 = 0;
		RD5 = 1;
		RD6 = 1;
		break;
	case 6:
		RD0 = 1;
		RD1 = 0;
		RD2 = 1;
		RD3 = 1;
		RD4 = 1;
		RD5 = 1;
		RD6 = 1;
		break;
	case 7:
		RD0 = 1;
		RD1 = 1;
		RD2 = 1;
		RD3 = 0;
		RD4 = 0;
		RD5 = 0;
		RD6 = 0;
		break;
	case 8:
		RD0 = 1;
		RD1 = 1;
		RD2 = 1;
		RD3 = 1;
		RD4 = 1;
		RD5 = 1;
		RD6 = 1;
		break;
	case 9:
		RD0 = 1;
		RD1 = 1;
		RD2 = 1;
		RD3 = 1;
		RD4 = 0;
		RD5 = 1;
		RD6 = 1;
		break;
	default:
		RD0 = 0;
		RD1 = 0;
		RD2 = 0;
		RD3 = 0;
		RD4 = 0;
		RD5 = 0;
		RD6 = 0;
		break;
	}
}

void outputDP(unsigned char dp)
{
	if (dp) {
		RD7 = 1;
	} else {
		RD7 = 0;
	}
}

int main()
{
	// 時間設定
	hour = 23;
	min = 38;
	// ポートの設定
	TRISB = 0xFC;	// 0, 1 出力
	TRISC = 0xF0;	// 0, 1, 2, 3 出力
	TRISD = 0x00;	// 全部出力
	// ポートの初期化
	RB0 = 1;
	RB1 = 0;
	RC0 = 1;
	RC1 = 1;
	RC2 = 1;
	RC3 = 1;
	// タイマー1の設定
	OPTION = 0b0111;	// prescale by 256
	T0CS = 0;			// select internal clock
	T0IE = 1;			// enable timer interrupt
	GIE = 1;			// enable global interrupts
	while (1) {
		dp = sec % 2;
		selectDigit(99);
		outputDigit(10);
		outputDP(0);
		selectDigit(selector++);
		outputDigit(min % 10);
		outputDP(dp);
		delay(1);

		selectDigit(99);
		outputDigit(10);
		outputDP(0);
		selectDigit(selector++);
		outputDigit(min / 10);
		outputDP(0);
		delay(1);

		selectDigit(99);
		outputDigit(10);
		outputDP(0);
		selectDigit(selector++);
		outputDigit(hour % 10);
		outputDP(0);
		delay(1);

		selectDigit(99);
		outputDigit(10);
		outputDP(0);
		selectDigit(selector++);
		outputDigit(hour / 10);
		outputDP(0);
		delay(1);

		counter1++;
		if (counter1 > 120) {
			counter1 = 0;
		}
		selector = 0;
	}
	return 0;
}
カテゴリー: PIC, プロトタイプ, 作業, 回路 タグ: , , , , , , パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください