piodma_dht11.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include <stdio.h>
  2. #include "pico/stdlib.h"
  3. #include "hardware/dma.h"
  4. #include "hardware/pio.h"
  5. #include "dht11.pio.h"
  6. #define PIO_SM 0
  7. #define DHT11_SDA 16
  8. #define DHT11_START_PULSE_US (20 * 1000)
  9. #define DHT11_TRANS_SIZE 5
  10. static uint8_t dht11_buff[DHT11_TRANS_SIZE];
  11. static int dma_ch;
  12. dma_channel_config dmac_config;
  13. volatile static uint temperature = 0; // 現在温度
  14. volatile static uint humidity = 0; // 現在湿度
  15. void dma_irq_handler(void)
  16. {
  17. // 割り込みフラグクリア
  18. dma_channel_acknowledge_irq0(dma_ch);
  19. uint8_t checksum = (dht11_buff[0]+dht11_buff[1]+dht11_buff[2]+dht11_buff[3]) & 0xFF;
  20. if( checksum == dht11_buff[4]){
  21. // データ正常
  22. // DHT-11では小数部は切り捨ててしまう
  23. temperature = dht11_buff[2];
  24. humidity = dht11_buff[0];
  25. }
  26. }
  27. // repeating_timerオブジェクト
  28. struct repeating_timer rtimer;
  29. bool update_dht11_data(__unused struct repeating_timer *t)
  30. {
  31. // 念のためRX FIFOをクリアしておく
  32. pio_sm_clear_fifos(pio0, PIO_SM);
  33. // DMA転送をトリガー
  34. dma_channel_set_write_addr(dma_ch, dht11_buff, false);
  35. dma_channel_set_trans_count(dma_ch, DHT11_TRANS_SIZE, true);
  36. // スタートパルス幅をプッシュしてPIOをスタート
  37. pio_sm_put(pio0, 0, DHT11_START_PULSE_US);
  38. return true; // falseを返すとリピート動作が終了
  39. }
  40. int main()
  41. {
  42. stdio_init_all();
  43. // 未使用のDMAチャンネルを得る
  44. dma_ch = dma_claim_unused_channel(true);
  45. // DMA設定情報を取得
  46. dmac_config = dma_channel_get_default_config(dma_ch);
  47. // 転送データサイズの設定
  48. channel_config_set_transfer_data_size(&dmac_config, DMA_SIZE_8);
  49. // 読み出し側インクリメントの可否
  50. channel_config_set_read_increment(&dmac_config, false);
  51. // 書き込み側インクリメントの可否
  52. channel_config_set_write_increment(&dmac_config, true);
  53. // DREQの設定
  54. uint dreq = pio_get_dreq(pio0, PIO_SM, false);
  55. channel_config_set_dreq(&dmac_config, dreq);
  56. // DMAチャンネルの設定
  57. dma_channel_configure(
  58. dma_ch, // DMAチャンネル
  59. &dmac_config, // 設定情報
  60. dht11_buff, // 書き込みアドレス
  61. &pio0_hw->rxf[PIO_SM], // 転送元レジスタアドレス
  62. DHT11_TRANS_SIZE, // 転送データサイズ
  63. false // すぐに開始ならtrue
  64. );
  65. // DMA割り込みを設定
  66. // DMAチャンネルをDMA_IRQ_0にルーティング
  67. dma_channel_set_irq0_enabled(dma_ch, true);
  68. // 割り込みハンドラとして静的関数を登録
  69. irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler);
  70. // DMA_IRQ_0を有効化
  71. irq_set_enabled(DMA_IRQ_0, true);
  72. // DHT-11 PIOの起動
  73. uint offset = pio_add_program(pio0, &dht11_program);
  74. dht11_program_init(pio0, PIO_SM, offset, DHT11_SDA);
  75. pio_sm_set_enabled(pio0, PIO_SM, true);
  76. // タイマー
  77. add_repeating_timer_ms(2*1000, update_dht11_data, NULL, &rtimer);
  78. // メインループ
  79. while(true) {
  80. sleep_ms(2000);
  81. printf("hum = %d %%, temp = %d C\n", humidity, temperature);
  82. }
  83. }