]> granicus.if.org Git - esp-idf/blob - examples/16_pcnt/main/pcnt_test.c
Merge branch 'master' into feature/btdm_bluedroid
[esp-idf] / examples / 16_pcnt / main / pcnt_test.c
1 /* Pulse counter module - Example
2
3    For other examples please check:
4    https://github.com/espressif/esp-idf/tree/master/examples
5
6    This example code is in the Public Domain (or CC0 licensed, at your option.)
7
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.
11 */
12 #include <stdio.h>
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"
21 #include "esp_attr.h"
22 #include "esp_log.h"
23 #include "soc/gpio_sig_map.h"
24
25 /**
26  * TEST CODE BRIEF
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
29  *
30  * Open serial port to view the message printed on your screen
31  *
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.
35  *
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.
38  */
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)
49
50 xQueueHandle pcnt_evt_queue;  /*A queue to handle pulse counter event*/
51
52
53 typedef struct {
54     int unit;        /*pulse counter unit*/
55     uint32_t status; /*pulse counter internal status*/
56 } pcnt_evt_t;
57
58 void IRAM_ATTR pcnt_intr_handler(void* arg)
59 {
60     uint32_t intr_status = PCNT.int_st.val;
61     int i;
62     pcnt_evt_t evt;
63     portBASE_TYPE HPTaskAwoken = pdFALSE;
64
65     for(i = 0; i < PCNT_UNIT_MAX; i++) {
66         if(intr_status & (BIT(i))) {
67             evt.unit = i;
68             evt.status = PCNT.status_unit[i].val;
69             PCNT.int_clr.val = BIT(i);
70             /*H LIM EVT*/
71             if(PCNT.status_unit[i].h_lim_lat) {
72                 //do something
73             }
74             /*L LIM EVT*/
75             if(PCNT.status_unit[i].l_lim_lat) {
76                 //do something
77             }
78             /*THRES0 EVT*/
79             if(PCNT.status_unit[i].thres0_lat) {
80                 //do something
81             }
82             /*THRES1 EVT*/
83             if(PCNT.status_unit[i].thres1_lat) {
84                 //do something
85             }
86             /*ZERO EVT*/
87             if(PCNT.status_unit[i].zero_lat) {
88                 //do something
89             }
90             xQueueSendFromISR(pcnt_evt_queue, &evt, &HPTaskAwoken);
91             if(HPTaskAwoken == pdTRUE) {
92                 portYIELD_FROM_ISR();
93             }
94         }
95     }
96 }
97
98 static void ledc_init(void)
99 {
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;
111     /*Set duty 100 */
112     ledc_channel.duty = 100;
113     ledc_channel_config(&ledc_channel); //ledc config
114
115     ledc_timer_config_t ledc_timer;
116     /*LEDC timer high speed mode*/
117     ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
118     /*10 bit PWM*/
119     ledc_timer.bit_num = LEDC_TIMER_10_BIT;
120     /*Select timer 1*/
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);
125 }
126
127 static void pcnt_init(void)
128 {
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,
136         /*Choose unit 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,
151     };
152     /*Initialize PCNT unit */
153     pcnt_unit_config(&pcnt_config);
154
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);
159
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);
174
175     /*Pause counter*/
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);
183     /*Resume counting*/
184     pcnt_counter_resume(PCNT_TEST_UNIT);
185 }
186
187 void app_main()
188 {
189     /*Init LEDC for pulse input signal */
190     ledc_init();
191     /*Init PCNT event queue */
192     pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t));
193     /*Init PCNT functions*/
194     pcnt_init();
195
196     int16_t count = 0;
197     pcnt_evt_t evt;
198     portBASE_TYPE res;
199     while(1)
200     {
201         res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_RATE_MS);
202         if(res == pdTRUE) {
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");
207             }
208             if(evt.status & PCNT_STATUS_THRES0_M) {
209                 printf("THRES0 EVT\n");
210             }
211             if(evt.status & PCNT_STATUS_L_LIM_M) {
212                 printf("L_LIM EVT\n");
213             }
214             if(evt.status & PCNT_STATUS_H_LIM_M) {
215                 printf("H_LIM EVT\n");
216             }
217             if(evt.status & PCNT_STATUS_ZERO_M) {
218                 printf("ZERO EVT\n");
219             }
220         } else {
221             pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
222             printf("Current counter value :%d\n", count);
223         }
224     }
225 }
226