186 lines
6.3 KiB
C
186 lines
6.3 KiB
C
|
/* 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/task.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 ouput 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 you 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.
|
||
|
*/
|
||
|
static const char* TAG = "PCNT_TEST";
|
||
|
#define PCNT_TEST_UNIT PCNT_UNIT0
|
||
|
#define PCNT_H_LIM_VAL (10)
|
||
|
#define PCNT_L_LIM_VAL (-10)
|
||
|
#define PCNT_THRESH1_VAL (5)
|
||
|
#define PCNT_THRESH0_VAL (-5)
|
||
|
#define PCNT_INTR_NUM (18)
|
||
|
#define PCNT_INPUT_SIG_IO (4)
|
||
|
#define PCNT_INPUT_CTRL_IO (5)
|
||
|
#define LEDC_OUPUT_IO (18)
|
||
|
|
||
|
void IRAM_ATTR pcnt_intr_handler(void* arg)
|
||
|
{
|
||
|
uint32_t intr_status = PCNT.int_st.val;
|
||
|
int i;
|
||
|
for(i = 0; i < PCNT_UNIT_MAX; i++) {
|
||
|
if(intr_status & (BIT(i))) {
|
||
|
ESP_EARLY_LOGI(TAG, "EVENT[%d] intr\n", i);
|
||
|
PCNT.int_clr.val |= BIT(i);
|
||
|
if(PCNT.status_unit[i].h_lim_lat) {
|
||
|
ESP_EARLY_LOGI(TAG, "H LIM EVT\n");
|
||
|
}
|
||
|
if(PCNT.status_unit[i].l_lim_lat) {
|
||
|
ESP_EARLY_LOGI(TAG, "L LIM EVT\n");
|
||
|
}
|
||
|
if(PCNT.status_unit[i].thres0_lat) {
|
||
|
ESP_EARLY_LOGI(TAG, "THRES0 EVT\n");
|
||
|
}
|
||
|
if(PCNT.status_unit[i].thres1_lat) {
|
||
|
ESP_EARLY_LOGI(TAG, "THRES1 EVT\n");
|
||
|
}
|
||
|
if(PCNT.status_unit[i].zero_lat) {
|
||
|
ESP_EARLY_LOGI(TAG, "ZERO EVT\n");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void ledc_init(void)
|
||
|
{
|
||
|
periph_module_enable(PERIPH_LEDC_MODULE);
|
||
|
ledc_channel_config_t ledc_channel;
|
||
|
/*use GPIO18 as output pin*/
|
||
|
ledc_channel.gpio_num = LEDC_OUPUT_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_init(void)
|
||
|
{
|
||
|
pcnt_config_t pcnt_config = {
|
||
|
/*Set GPIO4 as pulse input gpio */
|
||
|
.pulse_gpio_num = PCNT_INPUT_SIG_IO,
|
||
|
/*set gpio5 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_THRES1, PCNT_THRESH1_VAL);
|
||
|
/*Enable watch point event of thresh1*/
|
||
|
pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES1);
|
||
|
/*Set value for watch point thresh0*/
|
||
|
pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES0, PCNT_THRESH0_VAL);
|
||
|
/*Enable watch point event of thresh0*/
|
||
|
pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES0);
|
||
|
/*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_INTR_NUM, pcnt_intr_handler, NULL);
|
||
|
/*Enable interrupt for PCNT unit*/
|
||
|
pcnt_intr_enable(PCNT_TEST_UNIT);
|
||
|
/*Resume counting*/
|
||
|
pcnt_counter_resume(PCNT_TEST_UNIT);
|
||
|
}
|
||
|
|
||
|
void pcnt_task(void *pvParameter)
|
||
|
{
|
||
|
int16_t count = 0;
|
||
|
while(1)
|
||
|
{
|
||
|
pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
|
||
|
printf("Current counter value :%d\n", count);
|
||
|
vTaskDelay(1000 / portTICK_RATE_MS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void app_main()
|
||
|
{
|
||
|
/*Init LEDC for pulse input signal */
|
||
|
ledc_init();
|
||
|
/*Init PCNT functions*/
|
||
|
pcnt_init();
|
||
|
/*Create task to display PCNT counter value every one second*/
|
||
|
xTaskCreate(&pcnt_task, "pcnt_task", 1024, NULL, 5, NULL);
|
||
|
}
|
||
|
|