esp32-gpio
·
#include <stdio.h>
#include "esp_log.h"
#include "esp_rom_gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#define GPIO_LED 2
#define GPIO_FAN 15
#define GPIO_KEY 4
// 队列
static QueueHandle_t gpio_evt_queue = NULL;
void gpio_init(void) {
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE; // 禁止中断
io_conf.mode = GPIO_MODE_OUTPUT; // 通用推挽
/**
* 1ULL :表示一个64位无符号整数,,,, 00000000 00000000 00000000 ... 00000001
* 支持一次配置多个GPIO :
* .pin_bit_mask = (1ULL << 2) | (1ULL << 4) | (1ULL << 5)
*/
io_conf.pin_bit_mask = (1ULL << GPIO_LED | 1ULL << GPIO_FAN); // 配置gpio引脚
io_conf.pull_down_en = 0; // 禁止下拉
io_conf.pull_up_en = 0; // 禁止上拉
gpio_config(&io_conf);
}
void gpio_in_init(void) {
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_INPUT; // 输入模式
io_conf.pin_bit_mask = (1ULL << GPIO_KEY);
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
}
/**
* 这个函数是自己写的,,名字随便取
* @param arg
* IRAM_ATTR :这个函数放到内部的RAM里面,,, 因为esp32运行代码通常在flash中,,flash擦除,写入,,会很忙,,
* 如果中断来了,,ISR还在flash,,会崩溃
*/
static void IRAM_ATTR gpio_key_interrupt(void* arg) {
uint32_t gpio_num = (uint32_t)arg;
// NULL : 是否有更高优先级任务被唤醒,,告诉系统,发送数据后,是否应该立即切换任务
xQueueSendFromISR(gpio_evt_queue, &gpio_num,NULL);
}
static void gpio_task_example(void* pvParameter) {
uint32_t gpio_num;
while (1) {
// 返回pdPASS :成功接收到队列数据
if (xQueueReceive(gpio_evt_queue, &gpio_num, portMAX_DELAY)) {
// 消抖时间
vTaskDelay(pdMS_TO_TICKS(20));
if (gpio_get_level(gpio_num) == 0) {
// 按下
printf("gpio[%lu] intr,,val is %d \n",gpio_num,gpio_get_level(gpio_num));
gpio_set_level(GPIO_LED,0);
gpio_set_level(GPIO_FAN,0);
}else {
gpio_set_level(GPIO_LED,1);
gpio_set_level(GPIO_FAN,1);
}
xQueueReset(gpio_evt_queue);
}
}
}
void app_main(void)
{
// 把引脚从复位功能(UART,SPI,I2C)切回普通GPIO
// gpio_reset_pin(GPIO_LED);
//
// gpio_set_direction(GPIO_LED,GPIO_MODE_OUTPUT);
gpio_init();
gpio_set_level(GPIO_LED,1);
gpio_set_level(GPIO_FAN,1);
// 输入模式
// gpio_reset_pin(GPIO_KEY);
// gpio_set_direction(GPIO_KEY,GPIO_MODE_INPUT);
// gpio_in_init();
// 按键中断
gpio_reset_pin(GPIO_KEY);
gpio_set_direction(GPIO_KEY, GPIO_MODE_INPUT);
// 任何一个边沿触发
gpio_set_intr_type(GPIO_KEY,GPIO_INTR_ANYEDGE);
// 上拉,,不然浮空,引脚电平会一直变
gpio_set_pull_mode(GPIO_KEY,GPIO_PULLUP_ONLY);
// 创建队列
gpio_evt_queue = xQueueCreate(10,sizeof(uint32_t));
// 创建一个GPIO中断管理服务,,,让esp-idf有能力管理GPIO中断
gpio_install_isr_service(0);
// 注册自己的中断函数
gpio_isr_handler_add(GPIO_KEY,gpio_key_interrupt,(void*)GPIO_KEY);
xTaskCreate(gpio_task_example,"gpio_key",2048,NULL,10,NULL);
while (0) {
if (gpio_get_level(GPIO_KEY)) {
// 高电平
printf("key up \n");
gpio_set_level(GPIO_LED,1);
gpio_set_level(GPIO_FAN,1);
}else {
printf("key down \n");
gpio_set_level(GPIO_LED,0);
gpio_set_level(GPIO_FAN,0);
}
vTaskDelay(pdMS_TO_TICKS(100));
// gpio_set_level(GPIO_LED,0);
// gpio_set_level(GPIO_FAN,0);
//
// // printf("hello world11");
// vTaskDelay(pdMS_TO_TICKS(1000));
//
// gpio_set_level(GPIO_LED,1);
// gpio_set_level(GPIO_FAN,1);
// vTaskDelay(pdMS_TO_TICKS(1000));
}
}
/**
*
* 中断不能写printf等输出,,,否则会导致esp32复位,,, 中断处理程序要尽可能的短
*
*
*esp32支持在中断里面直接处理业务逻辑,,但是不建议,,所以会引入队列,信号量,事件组这些机制
*
*因为中断环境限制很多,, 比如在按键之后想,,打印信息,控制wifi,发送mqtt,,,这些任务耗时较长
*
*中断来了,,,发消息,,让任务去干活
*/
更多推荐



所有评论(0)