1 /* Pulse counter module - Example
3 For other examples please check:
4 https://github.com/espressif/esp-idf/tree/master/examples
6 This example code is in the Public Domain (or CC0 licensed, at your option.)
8 Unless required by applicable law or agreed to in writing, this
9 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10 CONDITIONS OF ANY KIND, either express or implied.
13 #include "freertos/FreeRTOS.h"
14 #include "freertos/portmacro.h"
15 #include "freertos/task.h"
16 #include "freertos/queue.h"
17 #include "driver/periph_ctrl.h"
18 #include "driver/ledc.h"
19 #include "driver/gpio.h"
20 #include "driver/pcnt.h"
23 #include "soc/gpio_sig_map.h"
27 * Use PCNT module to count rising edges generated by LEDC module.
28 * GPIO18 is used as output pin, GPIO4 is used as pulse input pin and GPIO5 is used as control input pin
30 * Open serial port to view the message printed on your screen
32 * To do this test, you should connect GPIO18 with GPIO4
33 * GPIO5 is the control signal, you can leave it floating with internal pulled up, or connect it to ground.
34 * If you connect gpio5 to GND ,you will found the count value decreasing.
36 * When counter value reaches thresh1 or thresh0 value, it will trigger interrupt.
37 * When counter value reaches l_lim value or h_lim value, counter value will be reset to zero and trigger interrupt.
39 static const char* TAG = "PCNT_TEST";
40 #define PCNT_TEST_UNIT PCNT_UNIT_0
41 #define PCNT_H_LIM_VAL (10)
42 #define PCNT_L_LIM_VAL (-10)
43 #define PCNT_THRESH1_VAL (5)
44 #define PCNT_THRESH0_VAL (-5)
45 #define PCNT_INTR_NUM (18)
46 #define PCNT_INPUT_SIG_IO (4)
47 #define PCNT_INPUT_CTRL_IO (5)
48 #define LEDC_OUPUT_IO (18)
50 xQueueHandle pcnt_evt_queue; /*A queue to handle pulse counter event*/
54 int unit; /*pulse counter unit*/
55 uint32_t status; /*pulse counter internal status*/
58 void IRAM_ATTR pcnt_intr_handler(void* arg)
60 uint32_t intr_status = PCNT.int_st.val;
63 portBASE_TYPE HPTaskAwoken = pdFALSE;
65 for(i = 0; i < PCNT_UNIT_MAX; i++) {
66 if(intr_status & (BIT(i))) {
68 evt.status = PCNT.status_unit[i].val;
69 PCNT.int_clr.val = BIT(i);
71 if(PCNT.status_unit[i].h_lim_lat) {
75 if(PCNT.status_unit[i].l_lim_lat) {
79 if(PCNT.status_unit[i].thres0_lat) {
83 if(PCNT.status_unit[i].thres1_lat) {
87 if(PCNT.status_unit[i].zero_lat) {
90 xQueueSendFromISR(pcnt_evt_queue, &evt, &HPTaskAwoken);
91 if(HPTaskAwoken == pdTRUE) {
98 static void ledc_init(void)
100 ledc_channel_config_t ledc_channel;
101 /*use GPIO18 as output pin*/
102 ledc_channel.gpio_num = LEDC_OUPUT_IO;
103 /*LEDC high speed mode */
104 ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
105 /*use LEDC channel 1*/
106 ledc_channel.channel = LEDC_CHANNEL_1;
107 /*Disable LEDC interrupt*/
108 ledc_channel.intr_type = LEDC_INTR_DISABLE;
109 /*Select LEDC timer 1 */
110 ledc_channel.timer_sel = LEDC_TIMER_1;
112 ledc_channel.duty = 100;
113 ledc_channel_config(&ledc_channel); //ledc config
115 ledc_timer_config_t ledc_timer;
116 /*LEDC timer high speed mode*/
117 ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
119 ledc_timer.bit_num = LEDC_TIMER_10_BIT;
121 ledc_timer.timer_num = LEDC_TIMER_1;
122 /*Set frequency 1 Hz */
123 ledc_timer.freq_hz = 1;
124 ledc_timer_config(&ledc_timer);
127 static void pcnt_init(void)
129 pcnt_config_t pcnt_config = {
130 /*Set GPIO4 as pulse input gpio */
131 .pulse_gpio_num = PCNT_INPUT_SIG_IO,
132 /*set gpio5 as control gpio */
133 .ctrl_gpio_num = PCNT_INPUT_CTRL_IO,
134 /*Choose channel 0 */
135 .channel = PCNT_CHANNEL_0,
137 .unit = PCNT_TEST_UNIT,
138 /*Set counter and control mode*/
139 /*Counter increase for positive edge on pulse input GPIO*/
140 .pos_mode = PCNT_COUNT_INC,
141 /*Counter decrease for negative edge on pulse input GPIO*/
142 .neg_mode = PCNT_COUNT_DIS, //keep the counter value
143 /*Counter mode reverse when control input is low level*/
144 .lctrl_mode = PCNT_MODE_REVERSE,
145 /*Counter mode does not change when control input is high level*/
146 .hctrl_mode = PCNT_MODE_KEEP, //when control signal is high,keep the primary counter mode
147 /*Set maximum value for increasing counter*/
148 .counter_h_lim = PCNT_H_LIM_VAL,
149 /*Set minimum value for decreasing counter*/
150 .counter_l_lim = PCNT_L_LIM_VAL,
152 /*Initialize PCNT unit */
153 pcnt_unit_config(&pcnt_config);
155 /*Configure input filter value*/
156 pcnt_set_filter_value(PCNT_TEST_UNIT, 100);
157 /*Enable input filter*/
158 pcnt_filter_enable(PCNT_TEST_UNIT);
160 /*Set value for watch point thresh1*/
161 pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL);
162 /*Enable watch point event of thresh1*/
163 pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_1);
164 /*Set value for watch point thresh0*/
165 pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
166 /*Enable watch point event of thresh0*/
167 pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_0);
168 /*Enable watch point event of h_lim*/
169 pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_H_LIM);
170 /*Enable watch point event of l_lim*/
171 pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_L_LIM);
172 /*Enable watch point event of zero*/
173 pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_ZERO);
176 pcnt_counter_pause(PCNT_TEST_UNIT);
177 /*Reset counter value*/
178 pcnt_counter_clear(PCNT_TEST_UNIT);
179 /*Register ISR handler*/
180 pcnt_isr_register(PCNT_INTR_NUM, pcnt_intr_handler, NULL);
181 /*Enable interrupt for PCNT unit*/
182 pcnt_intr_enable(PCNT_TEST_UNIT);
184 pcnt_counter_resume(PCNT_TEST_UNIT);
189 /*Init LEDC for pulse input signal */
191 /*Init PCNT event queue */
192 pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t));
193 /*Init PCNT functions*/
201 res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_RATE_MS);
203 pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
204 printf("Event PCNT unit[%d]; cnt: %d\n", evt.unit, count);
205 if(evt.status & PCNT_STATUS_THRES1_M) {
206 printf("THRES1 EVT\n");
208 if(evt.status & PCNT_STATUS_THRES0_M) {
209 printf("THRES0 EVT\n");
211 if(evt.status & PCNT_STATUS_L_LIM_M) {
212 printf("L_LIM EVT\n");
214 if(evt.status & PCNT_STATUS_H_LIM_M) {
215 printf("H_LIM EVT\n");
217 if(evt.status & PCNT_STATUS_ZERO_M) {
218 printf("ZERO EVT\n");
221 pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
222 printf("Current counter value :%d\n", count);