对于电平触发的中断, 当触发电平有效时, 中断状态被清除, 硬件会继续产生中断, 所以电平触发的中断不会丢失. 解决中断丢失的方案就是使用电平触发的中断, 以下的示例代码将在高电平的时候产生一次中断, 与 rising edge 类型中断效果相同.
Code: Select all
const uint64_t INPUT_PIIN_MASK = (1ULL<<GPIO_NUM_34) | (1ULL<<GPIO_NUM_36) | (1ULL<<GPIO_NUM_39);
typedef struct io_isr_param_ {
uint32_t io_tagle;
uint32_t io_number;
uint32_t isr_cnt;
} io_isr_param_t;
uint32_t isr_mode[2] = {GPIO_INTR_HIGH_LEVEL, GPIO_INTR_LOW_LEVEL};
io_isr_param_t io34_param = {
.io_tagle = 0x1,
.io_number = 34,
};
io_isr_param_t io36_param = {
.io_tagle = 0x1,
.io_number = 36,
};
io_isr_param_t io39_param = {
.io_tagle = 0x1,
.io_number = 39,
};
IRAM_ATTR void gpio_isr(void *param)
{
io_isr_param_t *io_param = (io_isr_param_t *)param;
if(io_param->io_tagle) {
//do some thing here;
}
gpio_set_intr_type(io_param->io_number, isr_mode[io_param->io_tagle]);
io_param->io_tagle ^= 0x1;
}
void io_init(void)
{
gpio_config_t io_conf = {
.intr_type = GPIO_PIN_INTR_DISABLE,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = INPUT_PIIN_MASK,
.pull_down_en = 0,
.pull_up_en = 1,
};
//configure GPIO with the given settings
gpio_config(&io_conf);
if(gpio_install_isr_service( 0 ) != ESP_OK) {
printf("ISR install fail\n");
return;
}
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_NUM_34, gpio_isr, (void*) &io34_param);
gpio_isr_handler_add(GPIO_NUM_36, gpio_isr, (void*) &io36_param);
gpio_isr_handler_add(GPIO_NUM_39, gpio_isr, (void*) &io39_param);
gpio_set_intr_type(GPIO_NUM_34, GPIO_INTR_HIGH_LEVEL);
gpio_intr_enable(GPIO_NUM_34);
gpio_set_intr_type(GPIO_NUM_36, GPIO_INTR_HIGH_LEVEL);
gpio_intr_enable(GPIO_NUM_36);
gpio_set_intr_type(GPIO_NUM_39, GPIO_INTR_HIGH_LEVEL);
gpio_intr_enable(GPIO_NUM_39);
}
以上代码可以解决中断丢失的问题, 但是带来的代价是中断次数会加倍(相对于 rising edge 和 falling edge )