pcnt_functions.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #include "freertos/FreeRTOS.h"
  2. #include "freertos/task.h"
  3. #include "freertos/queue.h"
  4. #include "driver/ledc.h"
  5. #include "driver/pcnt.h"
  6. #include "esp_attr.h"
  7. #include "esp_log.h"
  8. #include "config.h"
  9. #include "soc/dport_reg.h"
  10. #ifdef CCFG_PCNT
  11. // Example-code: https://github.com/espressif/esp-idf/blob/master/examples/peripherals/pcnt/pulse_count_event/main/pcnt_event_example_main.c
  12. // Counts full kWh
  13. static uint32_t kWh_Counter = 0;
  14. const int pcntUnit = PCNT_UNIT_0;
  15. float getkWh() {
  16. pcnt_intr_disable(pcntUnit);
  17. volatile int32_t count = DPORT_REG_READ(0x3FF57060);
  18. volatile uint32_t kWh = kWh_Counter;
  19. pcnt_intr_enable(pcntUnit);
  20. return (float)kWh + ((float)count/PULSES_PER_KWH);
  21. }
  22. static void IRAM_ATTR pcnt_example_intr_handler(void *arg)
  23. {
  24. kWh_Counter++;
  25. }
  26. void init_pcnt_unit()
  27. {
  28. /* Prepare configuration for the PCNT unit */
  29. pcnt_config_t pcnt_config = {
  30. // Set PCNT input signal and control GPIOs
  31. .pulse_gpio_num = PCNT_INPUT_SIG_IO,
  32. .ctrl_gpio_num = PCNT_INPUT_CTRL_IO,
  33. .channel = PCNT_CHANNEL_0,
  34. .unit = pcntUnit,
  35. // What to do on the positive / negative edge of pulse input?
  36. .pos_mode = PCNT_COUNT_INC, // Count up on the positive edge
  37. .neg_mode = PCNT_COUNT_DIS, // Keep the counter value on the negative edge
  38. // What to do when control input is low or high?
  39. .lctrl_mode = PCNT_MODE_REVERSE, // Reverse counting direction if low
  40. .hctrl_mode = PCNT_MODE_KEEP, // Keep the primary counter mode if high
  41. // Set the maximum and minimum limit values to watch
  42. .counter_h_lim = PULSES_PER_KWH,
  43. .counter_l_lim = 0,
  44. };
  45. /* Initialize PCNT unit */
  46. pcnt_unit_config(&pcnt_config);
  47. // How to read a periphial-register:
  48. //uint32_t c = p_pcnt_obj->hal.dev.hw.conf_unit[unit];
  49. //printf("Reg: %08x\n",(uint32_t)DPORT_REG_READ(0x3FF57000));
  50. /* Configure and enable the input filter */
  51. pcnt_set_filter_value(pcntUnit, 100);
  52. pcnt_filter_enable(pcntUnit);
  53. /* Enable int on high count limit */
  54. pcnt_event_enable(pcntUnit, PCNT_EVT_H_LIM);
  55. /* Initialize PCNT's counter */
  56. pcnt_counter_pause(pcntUnit);
  57. pcnt_counter_clear(pcntUnit);
  58. /* Install interrupt service and add isr callback handler */
  59. pcnt_isr_service_install(0);
  60. pcnt_isr_handler_add(pcntUnit, pcnt_example_intr_handler, (void *)pcntUnit);
  61. /* Everything is set up, now go to counting */
  62. pcnt_counter_resume(pcntUnit);
  63. }
  64. #else
  65. void init_pcnt_unit() { }
  66. float getkWh() { return 0.0f; }
  67. #endif