Extended description of the Pulse Counter API and removed redundant comments from the example

This commit is contained in:
krzychb
2017-09-22 18:42:17 +02:00
parent 7d436c9a44
commit e69691427c
4 changed files with 269 additions and 154 deletions

View File

@@ -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()
}
}
}