123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- #include <stdio.h>
- #include "pico/stdlib.h"
- #include "hardware/dma.h"
- #include "hardware/pio.h"
- #include "dht11.pio.h"
- #define PIO_SM 0
- #define DHT11_SDA 16
- #define DHT11_START_PULSE_US (20 * 1000)
- #define DHT11_TRANS_SIZE 5
- static uint8_t dht11_buff[DHT11_TRANS_SIZE];
- static int dma_ch;
- dma_channel_config dmac_config;
- volatile static uint temperature = 0; // 現在温度
- volatile static uint humidity = 0; // 現在湿度
- void dma_irq_handler(void)
- {
- // 割り込みフラグクリア
- dma_channel_acknowledge_irq0(dma_ch);
-
- uint8_t checksum = (dht11_buff[0]+dht11_buff[1]+dht11_buff[2]+dht11_buff[3]) & 0xFF;
- if( checksum == dht11_buff[4]){
- // データ正常
- // DHT-11では小数部は切り捨ててしまう
- temperature = dht11_buff[2];
- humidity = dht11_buff[0];
- }
- }
- // repeating_timerオブジェクト
- struct repeating_timer rtimer;
- bool update_dht11_data(__unused struct repeating_timer *t)
- {
- // 念のためRX FIFOをクリアしておく
- pio_sm_clear_fifos(pio0, PIO_SM);
- // DMA転送をトリガー
- dma_channel_set_write_addr(dma_ch, dht11_buff, false);
- dma_channel_set_trans_count(dma_ch, DHT11_TRANS_SIZE, true);
- // スタートパルス幅をプッシュしてPIOをスタート
- pio_sm_put(pio0, 0, DHT11_START_PULSE_US);
- return true; // falseを返すとリピート動作が終了
- }
- int main()
- {
- stdio_init_all();
- // 未使用のDMAチャンネルを得る
- dma_ch = dma_claim_unused_channel(true);
- // DMA設定情報を取得
- dmac_config = dma_channel_get_default_config(dma_ch);
- // 転送データサイズの設定
- channel_config_set_transfer_data_size(&dmac_config, DMA_SIZE_8);
- // 読み出し側インクリメントの可否
- channel_config_set_read_increment(&dmac_config, false);
- // 書き込み側インクリメントの可否
- channel_config_set_write_increment(&dmac_config, true);
- // DREQの設定
- uint dreq = pio_get_dreq(pio0, PIO_SM, false);
- channel_config_set_dreq(&dmac_config, dreq);
- // DMAチャンネルの設定
- dma_channel_configure(
- dma_ch, // DMAチャンネル
- &dmac_config, // 設定情報
- dht11_buff, // 書き込みアドレス
- &pio0_hw->rxf[PIO_SM], // 転送元レジスタアドレス
- DHT11_TRANS_SIZE, // 転送データサイズ
- false // すぐに開始ならtrue
- );
- // DMA割り込みを設定
- // DMAチャンネルをDMA_IRQ_0にルーティング
- dma_channel_set_irq0_enabled(dma_ch, true);
- // 割り込みハンドラとして静的関数を登録
- irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler);
- // DMA_IRQ_0を有効化
- irq_set_enabled(DMA_IRQ_0, true);
-
- // DHT-11 PIOの起動
- uint offset = pio_add_program(pio0, &dht11_program);
- dht11_program_init(pio0, PIO_SM, offset, DHT11_SDA);
- pio_sm_set_enabled(pio0, PIO_SM, true);
- // タイマー
- add_repeating_timer_ms(2*1000, update_dht11_data, NULL, &rtimer);
- // メインループ
- while(true) {
- sleep_ms(2000);
- printf("hum = %d %%, temp = %d C\n", humidity, temperature);
- }
- }
|