割り込みを利用した1秒カウンターの実装

概要

8051マイコン(AT89C52等)と2桁の7セグメントLED(カソードコモン)を用いて、1秒ごとにカウントアップする簡易ストップウォッチをタイマ割り込みで実現する。

タイマ0を16ビットモードで動作させ、50msごとに割り込みを発生。20回の割り込みで1秒を計測し、カウンタ値を表示する。

ヘッダファイル (head.h)

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char

メイン関数 (main.c)

#include "head.h"

void setup();
void show(uint value);

uint counter = 0;

void main()
{
    setup();
    while(1) {
        show(counter);
    }
}

初期化関数 (setup.c)

#include "head.h"

void setup()
{
    TMOD = 0x01;          // タイマ0、16ビットモード
    TH0  = (65536 - 45872) / 256;   // 50ms用の初期値
    TL0  = (65536 - 45872) % 256;
    EA   = 1;             // 全体割り込み許可
    ET0  = 1;             // タイマ0割り込み許可
    TR0  = 1;             // タイマ0スタート
    P0   = 0xFF;          // セグメント出力(全消灯)
    P1   = 0x00;          // 桁選択(全消灯)
}

割り込みサービスルーチン (timer0.c)

#include "head.h"

extern uint counter;
uint tickCount = 0;

void timer0_isr() interrupt 1
{
    TH0 = (65536 - 45872) / 256;   // 再ロード
    TL0 = (65536 - 45872) % 256;

    tickCount++;
    if (tickCount == 20) {         // 50ms × 20 = 1秒
        tickCount = 0;
        counter++;
        if (counter == 60) {
            counter = 0;
        }
    }
}

表示関数 (display.c)

#include "head.h"

void delay(uint ms);

// カソードコモン用セグメントコード
uchar segCode[] = {
    0x3F, 0x06, 0x5B, 0x4F,
    0x66, 0x6D, 0x7D, 0x07,
    0x7F, 0x6F, 0x77, 0x7C,
    0x39, 0x5E, 0x79, 0x71
};

void show(uint value)
{
    uint tens = value / 10;
    uint ones = value % 10;

    // 10の桁を表示
    P1 = segCode[tens];
    P0 = 0xFE;          // 1桁目(最下位桁)を選択
    delay(1);

    // 1の桁を表示
    P1 = segCode[ones];
    P0 = 0xFD;          // 2桁目を選択
    delay(1);
}

遅延関数 (delay.c)

#include "head.h"

void delay(uint ms)
{
    uint i, j;
    for (i = 0; i < ms; i++) {
        for (j = 0; j < 110; j++);   // 約1ms(11.0592MHzで調整)
    }
}

以上、4つのモジュール(setup, timer0, display, delay)とメイン、ヘッダにより構成される。タイマ割り込みで正確な1秒を生成し、2桁の7セグメントLEDにカウンタ値を動的スキャン表示する。

タグ: C 8051 timer interrupt 7-segment

6月8日 23:33 投稿