第14回藍橋杯マイコン基礎問題の解法解説

14回目の藍橋杯マイコン基礎問題は、実際に取り組んでみると確かに難易度が高いと感じました。

システム構成と初期設定

#include <reg52.h>
#include "ds1302.h"
#include "onewire.h"

#define HC573_CHANNEL(ch) (P2 = (P2 & 0x1F) | (ch << 5))

unsigned char ds1302_data[7] = {0x50, 0x50, 0x23, 0x31, 0x03, 0x05, 0x22};
unsigned int temp_value = 0;
unsigned char led_state = 0xFF;

void init_peripherals() {
    HC573_CHANNEL(0);
    P0 = 0xFF;
    HC573_CHANNEL(4);
    HC573_CHANNEL(0);
    P0 = 0x00;
    HC573_CHANNEL(5);
    
    // DS1302初期化
    Write_Ds1302_Byte(0x8E, 0x00);
    for(int i=0; i<7; i++) {
        Write_Ds1302_Byte(0x80 + i*2, ds1302_data[i]);
    }
    Write_Ds1302_Byte(0x8E, 0x80);
    
    // DS18B20初期化
    init_ds18b20();
    Write_DS18B20(0xCC);
    Write_DS18B20(0x44);
}

タイマー処理と割り込み制御

void init_timers() {
    TMOD = 0x06;  // タイマー1を8bit自動リロードモード
    TH1 = TL1 = 0xFF;
    TR1 = 1;
    
    TH0 = TL0 = 0xFF;
    TR0 = 1;
    
    EA = 1;
    ET0 = ET1 = 1;
}

unsigned int timer0_count = 0;
void timer0_isr() interrupt 1 {
    timer0_count++;
}

unsigned char timer1_count = 0;
void timer1_isr() interrupt 3 {
    if(++timer1_count == 200) {
        // 100msごとの処理
        timer1_count = 0;
        // センサー値更新フラグ設定
    }
    
    // 50usごとのディスプレイ更新
    if(timer1_count % 40 == 0) {
        update_display();
    }
}

主要な実装ポイント

  • 555タイマー: 適切な周波数設定のためにRB3の調整が必要
  • 光センサ: 値の安定化のために1ms遅延と割り込み処理を追加
  • DS18B20: 3桁での温度管理に注意
  • DS1302: 1秒ごとに割り込みで時刻を取得
  • LED制御: 状態変化に応じてビット演算を使用

表示処理の最適化

const unsigned char seg_table[] = {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 
    0x82, 0xF8, 0x80, 0x90, 0x88, 0x83
};

void show_digit(unsigned char pos, unsigned char val) {
    HC573_CHANNEL(0);
    P0 = 1 << pos;
    HC573_CHANNEL(6);
    HC573_CHANNEL(0);
    P0 = seg_table[val];
    HC573_CHANNEL(7);
}

void update_display() {
    static unsigned char refresh_pos = 0;
    
    // 全桁消灯
    HC573_CHANNEL(0);
    P0 = 0xFF;
    HC573_CHANNEL(6);
    
    // 表示モードに応じた処理
    switch(display_mode) {
        case 1:  // 時刻表示
            show_digit(refresh_pos, time_data[refresh_pos]);
            break;
        case 2:  // 温度表示
            show_digit(refresh_pos, temp_data[refresh_pos]);
            break;
    }
    
    if(++refresh_pos > 7) refresh_pos = 0;
}

タグ: 8051 ds1302 DS18B20 Embedded-Systems 藍橋杯

7月8日 21:24 投稿