STM32マイコンによるDS18B20およびDHT11センサのドライバ実装

DS18B20デジタル温度センサの実装

本セクションでは、STM32マイコンのGPIOポートを用いて1-Wireバスプロトコルをソフトウェアでエミュレートし、DS18B20温度センサと通信を行う手順について解説します。取得した温度データはTFT LCDモジュール上にリアルタイムで表示されます。

1-Wireバスプロトコルの概要

1-Wireバスは、クロックとデータの両方を単一の信号線で双方向通信を行うプロトコルです。この仕様により、I/Oポートのリソースを大幅に節約でき、配線も簡素化されます。

DS18B20の通信シーケンス

DS18B20は-55℃から+125℃の測定範囲を持ち、9ビットのデジタル温度値を出力します。通信には以下のタイミング制約が存在します。

  • リセットとプレゼンスパルス: マスターはバスを少なくとも480μs間Lowに保持してリセットパルスを送信します。その後バスを解放し、DS18B20が60~240μs間バスをLowに引っ張ることでプレゼンスパルスを返します。
  • 書き込みタイミング: 「0」を書く場合は60μs間Lowを維持、「1」を書く場合は2μs間Lowにした後即座にHigh(解放)します。各書き込みシーケンスの間には最低1μsの回復時間が必要です。
  • 読み出しタイミング: マスターが最低1μs間Lowにした後、バスを解放します。その後15μs以内にバスの状態をサンプリングすることで、デバイスからの送信データ(0または1)を判定します。

実装コード例:DS18B20へのバイト送信

以下に、1バイトのデータを送信する関数のコード例を示します。変数名やロジック構成を変更し、可読性を向上させています。

void ds18b20_send_byte(uint8_t data_byte)
{
    uint8_t bit_mask;
    
    ds18b20_config_gpio_output(); // ポートを出力モードに設定
    
    for (bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) {
        if (data_byte & bit_mask) {
            // ビットが1の場合の書き込みシーケンス
            ds18b20_write_pin(0);
            delay_us(2);
            ds18b20_write_pin(1); // バス解放
            delay_us(60);
        } else {
            // ビットが0の場合の書き込みシーケンス
            ds18b20_write_pin(0);
            delay_us(60);
            ds18b20_write_pin(1); // バス解放
            delay_us(2);
        }
    }
}

メインルーチンによる温度監視

システム初期化後、メインループ内で温度変換コマンドを送信し、結果を読み取ってLCDに表示します。

int main(void)
{
    uint16_t loop_counter = 0;
    int16_t current_temp;
    
    system_core_init(); // クロックおよび遅延関数の初期化
    nvic_priority_group_config(NVIC_PriorityGroup_2);
    uart_comm_init(115200);
    lcd_panel_init();
    
    lcd_show_text(30, 50, "STM32 PLATFORM");
    lcd_show_text(30, 70, "DS18B20 SENSOR");
    
    // センサの初期化確認
    while (ds18b20_init_sensor()) {
        lcd_show_text(30, 130, "Sensor Init Fail");
        delay_ms(500);
        lcd_clear_area(30, 130, 240, 16);
    }
    
    lcd_show_text(30, 130, "Sensor OK");
    lcd_show_text(30, 150, "Temp:       C");
    
    while (1) {
        // 周期的なデータ更新(約100ms毎)
        if (loop_counter % 10 == 0) {
            current_temp = ds18b20_read_temperature();
            
            if (current_temp < 0) {
                lcd_draw_char(30 + 40, 150, '-', 16);
                current_temp = -current_temp; // 絶対値に変換
            } else {
                lcd_draw_char(30 + 40, 150, ' ', 16);
            }
            
            // 整数部と小数部を表示
            lcd_show_number(30 + 48, 150, current_temp / 10, 2, 16);
            lcd_show_number(30 + 72, 150, current_temp % 10, 1, 16);
        }
        
        delay_ms(10);
        loop_counter++;
        
        // LED点滅処理(ハートビート)
        if (loop_counter >= 20) {
            loop_counter = 0;
            toggle_status_led();
        }
    }
}

DHT11温湿度センサの実装

次に、温度と湿度の両方を測定できるDHT11センサの使用方法について解説します。DS18B20と異なり、DHT11は湿度の検出が可能ですが、測定精度や範囲は限定的です(温度0~50℃、湿度20~90%RH)。

DHT11のデータフォーマット

通信フォーマットは40ビット(5バイト)のデータパケットで構成されています。

  1. 湿度整数部(8ビット)
  2. 湿度小数部(8ビット)
  3. 温度整数部(8ビット)
  4. 温度小数部(8ビット)
  5. チェックサム(8ビット)

チェックサムは最初の4バイトの合計値であり、データの整合性を確認するために使用されます。DHT11はマイコンからの開始信号を受信したときのみ測定を行います。

通信手順

データ転送は、バスを80μs間Highにした後に開始されます。各ビットは50μsのLow期間から始まり、その後のHigh期間の長さ(26~28μsで「0」、70μsで「1」)でデータ値を識別します。

メインルーチンによる温湿度表示

DHT11からのデータ読み出しとLCD表示を行うコード例を以下に示します。

int main(void)
{
    uint8_t timer_tick = 0;
    uint8_t temp_value = 0;
    uint8_t humidity_value = 0;
    
    system_delay_init();
    nvic_set_priority_grouping(NVIC_PriorityGroup_2);
    usart_init(115200);
    led_indicator_init();
    lcd_display_init();
    
    lcd_show_text(30, 50, "STM32 SYSTEM");
    lcd_show_text(30, 70, "DHT11 TEST");
    
    // DHT11初期化待ち
    while (dht11_startup_check()) {
        lcd_show_text(30, 130, "DHT11 Error");
        delay_ms(500);
        lcd_fill_rectangle(30, 130, 239, 146, WHITE);
        delay_ms(500);
    }
    
    lcd_show_text(30, 130, "DHT11 Ready");
    lcd_show_text(30, 150, "Temp:   C");
    lcd_show_text(30, 170, "Humi:   %");
    
    while (1) {
        // 定期的なセンサ読み出し
        if (timer_tick % 10 == 0) {
            // 温度湿度データの取得
            dht11_read_sensor_data(&temp_value, &humidity_value);
            
            // 温度表示
            lcd_show_number(30 + 40, 150, temp_value, 2, 16);
            
            // 湿度表示
            lcd_show_number(30 + 40, 170, humidity_value, 2, 16);
        }
        
        delay_ms(10);
        timer_tick++;
        
        // ステータスLEDのトグル
        if (timer_tick == 20) {
            timer_tick = 0;
            toggle_led();
        }
    }
}

タグ: STM32 DS18B20 DHT11 1-Wire Embedded C

5月26日 13:47 投稿