mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-22 17:10:28 +00:00
Extended description of the Pulse Counter API and removed redundant comments from the example
This commit is contained in:
@@ -24,195 +24,181 @@
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Functionality of GPIOs used in this example:
|
||||
* - GPIO18 - output pin of a sample 1 Hz pulse generator,
|
||||
* - GPIO4 - pulse input pin,
|
||||
* - GPIO5 - control input pin.
|
||||
*
|
||||
* 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.
|
||||
* Load example, open a serial port to view the message printed on your screen.
|
||||
*
|
||||
* 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.
|
||||
* To do this test, you should connect GPIO18 with GPIO4.
|
||||
* GPIO5 is the control signal, you can leave it floating with internal pull up,
|
||||
* or connect it to ground. If left floating, the count value will be increasing.
|
||||
* If you connect GPIO5 to GND, the count value will be decreasing.
|
||||
*
|
||||
* An interrupt will be triggered when the counter value:
|
||||
* - reaches 'thresh1' or 'thresh0' value,
|
||||
* - reaches 'l_lim' value or 'h_lim' value,
|
||||
* - will be reset to zero.
|
||||
*/
|
||||
#define PCNT_TEST_UNIT PCNT_UNIT_0
|
||||
#define PCNT_H_LIM_VAL 10
|
||||
#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_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*/
|
||||
#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 of a sample 1 Hz pulse generator
|
||||
|
||||
xQueueHandle pcnt_evt_queue; // A queue to handle pulse counter events
|
||||
|
||||
/* A sample structure to pass events from the PCNT
|
||||
* interrupt handler to the main program.
|
||||
*/
|
||||
typedef struct {
|
||||
int unit; /*pulse counter unit*/
|
||||
uint32_t status; /*pulse counter internal status*/
|
||||
int unit; // the PCNT unit that originated an interrupt
|
||||
uint32_t status; // information on the event type that caused the interrupt
|
||||
} pcnt_evt_t;
|
||||
|
||||
static void IRAM_ATTR pcnt_example_intr_handler(void* arg)
|
||||
/* Decode what PCNT's unit originated an interrupt
|
||||
* and pass this information together with the event type
|
||||
* the main program using a queue.
|
||||
*/
|
||||
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))) {
|
||||
for (i = 0; i < PCNT_UNIT_MAX; i++) {
|
||||
if (intr_status & (BIT(i))) {
|
||||
evt.unit = i;
|
||||
/* Save the PCNT event type that caused an interrupt
|
||||
to pass it to the main program */
|
||||
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) {
|
||||
if (HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure LED PWM Controller
|
||||
* to output sample pulses at 1 Hz with duty of about 10%
|
||||
*/
|
||||
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
|
||||
|
||||
// Prepare and then apply the LEDC PWM timer configuration
|
||||
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.timer_num = LEDC_TIMER_1;
|
||||
ledc_timer.bit_num = LEDC_TIMER_10_BIT;
|
||||
ledc_timer.freq_hz = 1; // set output frequency at 1 Hz
|
||||
ledc_timer_config(&ledc_timer);
|
||||
|
||||
// Prepare and then apply the LEDC PWM channel configuration
|
||||
ledc_channel_config_t ledc_channel;
|
||||
ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
ledc_channel.channel = LEDC_CHANNEL_1;
|
||||
ledc_channel.timer_sel = LEDC_TIMER_1;
|
||||
ledc_channel.intr_type = LEDC_INTR_DISABLE;
|
||||
ledc_channel.gpio_num = LEDC_OUTPUT_IO;
|
||||
ledc_channel.duty = 100; // set duty at about 10%
|
||||
ledc_channel_config(&ledc_channel);
|
||||
}
|
||||
|
||||
/* Initialize PCNT functions:
|
||||
* - configure and initialize PCNT
|
||||
* - set up the input filter
|
||||
* - set up the counter events to watch
|
||||
*/
|
||||
static void pcnt_example_init(void)
|
||||
{
|
||||
/* Prepare configuration for the PCNT unit */
|
||||
pcnt_config_t pcnt_config = {
|
||||
/*Set PCNT_INPUT_SIG_IO as pulse input gpio */
|
||||
// Set PCNT input signal and control GPIOs
|
||||
.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*/
|
||||
// What to do on the positive / negative edge of pulse input?
|
||||
.pos_mode = PCNT_COUNT_INC, // Count up on the positive edge
|
||||
.neg_mode = PCNT_COUNT_DIS, // Keep the counter value on the negative edge
|
||||
// What to do when control input is low or high?
|
||||
.lctrl_mode = PCNT_MODE_REVERSE, // Reverse counting direction if low
|
||||
.hctrl_mode = PCNT_MODE_KEEP, // Keep the primary counter mode if high
|
||||
// Set the maximum and minimum limit values to watch
|
||||
.counter_h_lim = PCNT_H_LIM_VAL,
|
||||
/*Set minimum value for decreasing counter*/
|
||||
.counter_l_lim = PCNT_L_LIM_VAL,
|
||||
};
|
||||
/*Initialize PCNT unit */
|
||||
/* Initialize PCNT unit */
|
||||
pcnt_unit_config(&pcnt_config);
|
||||
|
||||
/*Configure input filter value*/
|
||||
/* Configure and enable the input filter */
|
||||
pcnt_set_filter_value(PCNT_TEST_UNIT, 100);
|
||||
/*Enable input filter*/
|
||||
pcnt_filter_enable(PCNT_TEST_UNIT);
|
||||
|
||||
/*Set value for watch point thresh1*/
|
||||
/* Set threshold 0 and 1 values and enable events to watch */
|
||||
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*/
|
||||
/* Enable events on zero, maximum and minimum limit values */
|
||||
pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_ZERO);
|
||||
pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_H_LIM);
|
||||
pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_L_LIM);
|
||||
|
||||
/*Pause counter*/
|
||||
/* Initialize PCNT's counter */
|
||||
pcnt_counter_pause(PCNT_TEST_UNIT);
|
||||
/*Reset counter value*/
|
||||
pcnt_counter_clear(PCNT_TEST_UNIT);
|
||||
/*Register ISR handler*/
|
||||
|
||||
/* Register ISR handler and enable interrupts for PCNT unit */
|
||||
pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, NULL);
|
||||
/*Enable interrupt for PCNT unit*/
|
||||
pcnt_intr_enable(PCNT_TEST_UNIT);
|
||||
/*Resume counting*/
|
||||
|
||||
/* Everything is set up, now go to counting */
|
||||
pcnt_counter_resume(PCNT_TEST_UNIT);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
/*Init LEDC for pulse input signal */
|
||||
/* Initialize LEDC to generate sample pulse signal */
|
||||
ledc_init();
|
||||
/*Init PCNT event queue */
|
||||
|
||||
/* Initialize PCNT event queue and PCNT functions */
|
||||
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)
|
||||
{
|
||||
while (1) {
|
||||
/* Wait for the event information passed from PCNT's interrupt handler.
|
||||
* Once received, decode the event type and print it on the serial monitor.
|
||||
*/
|
||||
res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_PERIOD_MS);
|
||||
if(res == pdTRUE) {
|
||||
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) {
|
||||
if (evt.status & PCNT_STATUS_THRES1_M) {
|
||||
printf("THRES1 EVT\n");
|
||||
}
|
||||
if(evt.status & PCNT_STATUS_THRES0_M) {
|
||||
if (evt.status & PCNT_STATUS_THRES0_M) {
|
||||
printf("THRES0 EVT\n");
|
||||
}
|
||||
if(evt.status & PCNT_STATUS_L_LIM_M) {
|
||||
if (evt.status & PCNT_STATUS_L_LIM_M) {
|
||||
printf("L_LIM EVT\n");
|
||||
}
|
||||
if(evt.status & PCNT_STATUS_H_LIM_M) {
|
||||
if (evt.status & PCNT_STATUS_H_LIM_M) {
|
||||
printf("H_LIM EVT\n");
|
||||
}
|
||||
if(evt.status & PCNT_STATUS_ZERO_M) {
|
||||
if (evt.status & PCNT_STATUS_ZERO_M) {
|
||||
printf("ZERO EVT\n");
|
||||
}
|
||||
} else {
|
||||
@@ -221,4 +207,3 @@ void app_main()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user