#include #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); } }