| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /* Pulse counter module - Example
- For other examples please check:
- https://github.com/espressif/esp-idf/tree/master/examples
- This example code is in the Public Domain (or CC0 licensed, at your option.)
- Unless required by applicable law or agreed to in writing, this
- software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- CONDITIONS OF ANY KIND, either express or implied.
- */
- #include <stdio.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/portmacro.h"
- #include "freertos/task.h"
- #include "freertos/queue.h"
- #include "driver/periph_ctrl.h"
- #include "driver/ledc.h"
- #include "driver/gpio.h"
- #include "driver/pcnt.h"
- #include "esp_attr.h"
- #include "esp_log.h"
- #include "soc/gpio_sig_map.h"
- /**
- * TEST CODE BRIEF
- * Use PCNT module to count rising edges generated by LEDC module.
- * GPIO18 is used as output pin, GPIO4 is used as pulse input pin and GPIO5 is used as control input pin
- *
- * Open serial port to view the message printed on your screen
- *
- * To do this test, you should connect GPIO18 with GPIO4
- * GPIO5 is the control signal, you can leave it floating with internal pulled up, or connect it to ground.
- * If you connect gpio5 to GND ,you will found the count value decreasing.
- *
- * When counter value reaches thresh1 or thresh0 value, it will trigger interrupt.
- * When counter value reaches l_lim value or h_lim value, counter value will be reset to zero and trigger interrupt.
- */
- #define PCNT_TEST_UNIT PCNT_UNIT_0
- #define PCNT_H_LIM_VAL 10
- #define PCNT_L_LIM_VAL -10
- #define PCNT_THRESH1_VAL 5
- #define PCNT_THRESH0_VAL -5
- #define PCNT_INPUT_SIG_IO 4 /* Pulse Input GPIO */
- #define PCNT_INPUT_CTRL_IO 5 /* Control GPIO HIGH=count up, LOW=count down */
- #define LEDC_OUTPUT_IO 18 /* Output GPIO */
- xQueueHandle pcnt_evt_queue; /*A queue to handle pulse counter event*/
- typedef struct {
- int unit; /*pulse counter unit*/
- uint32_t status; /*pulse counter internal status*/
- } pcnt_evt_t;
- static void IRAM_ATTR pcnt_example_intr_handler(void* arg)
- {
- uint32_t intr_status = PCNT.int_st.val;
- int i;
- pcnt_evt_t evt;
- portBASE_TYPE HPTaskAwoken = pdFALSE;
- for(i = 0; i < PCNT_UNIT_MAX; i++) {
- if(intr_status & (BIT(i))) {
- evt.unit = i;
- evt.status = PCNT.status_unit[i].val;
- PCNT.int_clr.val = BIT(i);
- /*H LIM EVT*/
- if(PCNT.status_unit[i].h_lim_lat) {
- //do something
- }
- /*L LIM EVT*/
- if(PCNT.status_unit[i].l_lim_lat) {
- //do something
- }
- /*THRES0 EVT*/
- if(PCNT.status_unit[i].thres0_lat) {
- //do something
- }
- /*THRES1 EVT*/
- if(PCNT.status_unit[i].thres1_lat) {
- //do something
- }
- /*ZERO EVT*/
- if(PCNT.status_unit[i].zero_lat) {
- //do something
- }
- xQueueSendFromISR(pcnt_evt_queue, &evt, &HPTaskAwoken);
- if(HPTaskAwoken == pdTRUE) {
- portYIELD_FROM_ISR();
- }
- }
- }
- }
- static void ledc_init(void)
- {
- ledc_channel_config_t ledc_channel;
- /*use LEDC_OUTPUT_IO as output pin*/
- ledc_channel.gpio_num = LEDC_OUTPUT_IO;
- /*LEDC high speed mode */
- ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
- /*use LEDC channel 1*/
- ledc_channel.channel = LEDC_CHANNEL_1;
- /*Disable LEDC interrupt*/
- ledc_channel.intr_type = LEDC_INTR_DISABLE;
- /*Select LEDC timer 1 */
- ledc_channel.timer_sel = LEDC_TIMER_1;
- /*Set duty 100 */
- ledc_channel.duty = 100;
- ledc_channel_config(&ledc_channel); //ledc config
- ledc_timer_config_t ledc_timer;
- /*LEDC timer high speed mode*/
- ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
- /*10 bit PWM*/
- ledc_timer.bit_num = LEDC_TIMER_10_BIT;
- /*Select timer 1*/
- ledc_timer.timer_num = LEDC_TIMER_1;
- /*Set frequency 1 Hz */
- ledc_timer.freq_hz = 1;
- ledc_timer_config(&ledc_timer);
- }
- static void pcnt_example_init(void)
- {
- pcnt_config_t pcnt_config = {
- /*Set PCNT_INPUT_SIG_IO as pulse input gpio */
- .pulse_gpio_num = PCNT_INPUT_SIG_IO,
- /*set PCNT_INPUT_CTRL_IO as control gpio */
- .ctrl_gpio_num = PCNT_INPUT_CTRL_IO,
- /*Choose channel 0 */
- .channel = PCNT_CHANNEL_0,
- /*Choose unit 0 */
- .unit = PCNT_TEST_UNIT,
- /*Set counter and control mode*/
- /*Counter increase for positive edge on pulse input GPIO*/
- .pos_mode = PCNT_COUNT_INC,
- /*Counter decrease for negative edge on pulse input GPIO*/
- .neg_mode = PCNT_COUNT_DIS, //keep the counter value
- /*Counter mode reverse when control input is low level*/
- .lctrl_mode = PCNT_MODE_REVERSE,
- /*Counter mode does not change when control input is high level*/
- .hctrl_mode = PCNT_MODE_KEEP, //when control signal is high,keep the primary counter mode
- /*Set maximum value for increasing counter*/
- .counter_h_lim = PCNT_H_LIM_VAL,
- /*Set minimum value for decreasing counter*/
- .counter_l_lim = PCNT_L_LIM_VAL,
- };
- /*Initialize PCNT unit */
- pcnt_unit_config(&pcnt_config);
- /*Configure input filter value*/
- pcnt_set_filter_value(PCNT_TEST_UNIT, 100);
- /*Enable input filter*/
- pcnt_filter_enable(PCNT_TEST_UNIT);
- /*Set value for watch point thresh1*/
- pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL);
- /*Enable watch point event of thresh1*/
- pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_1);
- /*Set value for watch point thresh0*/
- pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
- /*Enable watch point event of thresh0*/
- pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_0);
- /*Enable watch point event of h_lim*/
- pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_H_LIM);
- /*Enable watch point event of l_lim*/
- pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_L_LIM);
- /*Enable watch point event of zero*/
- pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_ZERO);
- /*Pause counter*/
- pcnt_counter_pause(PCNT_TEST_UNIT);
- /*Reset counter value*/
- pcnt_counter_clear(PCNT_TEST_UNIT);
- /*Register ISR handler*/
- pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, NULL);
- /*Enable interrupt for PCNT unit*/
- pcnt_intr_enable(PCNT_TEST_UNIT);
- /*Resume counting*/
- pcnt_counter_resume(PCNT_TEST_UNIT);
- }
- void app_main()
- {
- /*Init LEDC for pulse input signal */
- ledc_init();
- /*Init PCNT event queue */
- pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t));
- /*Init PCNT functions*/
- pcnt_example_init();
- int16_t count = 0;
- pcnt_evt_t evt;
- portBASE_TYPE res;
- while(1)
- {
- res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_PERIOD_MS);
- if(res == pdTRUE) {
- pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
- printf("Event PCNT unit[%d]; cnt: %d\n", evt.unit, count);
- if(evt.status & PCNT_STATUS_THRES1_M) {
- printf("THRES1 EVT\n");
- }
- if(evt.status & PCNT_STATUS_THRES0_M) {
- printf("THRES0 EVT\n");
- }
- if(evt.status & PCNT_STATUS_L_LIM_M) {
- printf("L_LIM EVT\n");
- }
- if(evt.status & PCNT_STATUS_H_LIM_M) {
- printf("H_LIM EVT\n");
- }
- if(evt.status & PCNT_STATUS_ZERO_M) {
- printf("ZERO EVT\n");
- }
- } else {
- pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
- printf("Current counter value :%d\n", count);
- }
- }
- }
|