#include <stdio.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "driver/ledc.h"
/* Chương trình cấu hình interrupt cho một chân của ESP32
Cần thư viện #include “driver/gpio.h */
// Định nghĩa nút nhấn tại GPIO_13 với ký hiệu GPIO_NUM_13
#define BTN_PIN GPIO_NUM_13
void button_config()
{
// ISR = Interrupt Service Routine
gpio_install_isr_service(0);
printf("configuring button\n");
// Reset GPIO_13 về trạng thái bình thường (Tránh khai báo trùng)
gpio_reset_pin(BTN_PIN);
// Thiết lập GPIO_13 la ngõ INPUT
gpio_set_direction(BTN_PIN, GPIO_MODE_INPUT);
/* Thiết lập GPIO_13 trang thái kéo lên Pull-UP;
Nhấn nút = Ngắn mạch: Input nối đất Ground => Input = 0;
Thả nút = Hở mạch: Input nối lên Vcc => input = Vcc */
gpio_pullup_en(BTN_PIN);
// Chọn chế độ ngắt cạnh lên = POS EDGE
gpio_set_intr_type(BTN_PIN, GPIO_INTR_POSEDGE);
// Thêm ISR cho GPIO_13, GPIO_13 trở thành chân Ngắt
gpio_isr_handler_add(BTN_PIN, gpio_isr_handler, NULL);
printf("config complete\n");
}
/* Chương trình ngắt sử dụng hàm định nghĩa sẵn gpio_isr_handler() */
// Biến volatide cho phép thay đổi ngoài chương trình, phù hợp cho ngắt.
volatile bool button_pressed = false;
volatile int tone_var = 0; // 4 Tone types
static void gpio_isr_handler(void* arg)
{
button_pressed = true;
tone_var = tone_var + 1;
if(tone_var >= 4){
tone_var = 0;
}
}
/* Chương trình cấu hình chân OUTPUT cho một chân của ESP32. Cần thư viện #include “driver/gpio.h */
// Định nghĩa OUTPUT cho LED tại GPIO_2 với ký hiệu GPIO_NUM_2
#define LED_PIN GPIO_NUM_2
void led_config()
{
// Reset GPIO_13 về trạng thái bình thường (Tránh khai báo trùng)
gpio_reset_pin(LED_PIN);
// Thiết lập GPIO_13 la ngõ OUPUT
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
}
/* Chương trình cấu hình BUZZER cho một chân của ESP32. Cần thư viện #include “driver/ledc.h */
// Xung PWM tại GPIO_4, ký hiệu GPIO_NUM_4
#define BUZ_PIN GPIO_NUM_4
#define my_speed_mode LEDC_LOW_SPEED_MODE
// 4 Timer src [LEDC_TIMER_0 => LEDC_TIMER_3]
#define my_timer_src LEDC_TIMER_0
// 8 Channel [LEDC_CHANNEL_0 => LEDC_CHANNEL_7]
#define my_channel LEDC_CHANNEL_2
// Resolution [0,(2^13-1)] = [0,8191]
#define my_duty_res LEDC_TIMER_13_BIT
// Dety [0,(0.5*2^13-1)] over [0,4095]
#define LEDC_DUTY 4095
void buzzer_config(int freq_hz)
{
/* Phai ghi đúng thứ tự; Các tham số (ngoài freq_hz) có dạng cấu trụng được định nghĩa trong ledc.h */
// Tạo biến quy định thuộc tính timer
ledc_timer_config_t ledc_timer = {
.speed_mode = my_speed_mode,
.duty_resolution = my_duty_res,
.timer_num = my_timer_src,
.freq_hz = freq_hz,
.clk_cfg = LEDC_AUTO_CLK
};
// Thiết lập timer cho xung PWM
ledc_timer_config(&ledc_timer);
// Tạo biến quy định thuộc tính timer
ledc_channel_config_t ledc_channel = {
.gpio_num = BUZ_PIN,
.speed_mode = my_speed_mode, // Giong voi thiet lap timer
.channel = my_channel,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = my_timer_src, // Giong voi thiet lap timer
//LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)]
.duty = 0, // Set duty to 0%
.hpoint = 0
};
// Thiết lập channel: nối timer và ngõ ra BUZ_PIN
ledc_channel_config(&ledc_channel);
}
/* Chương trình chính sử dụng extern “C” để chạy một chương trình như C viết trên file .cpp */
// Thiết lập thời gian delay cho vòng lặp, cần thư viện freertos/FreeRTOS.h
#define DELAY_TIME 200
extern "C" void app_main()
{
// Thiết lập biến điều khiển Đèn LED: 0 = Tăt, 1 = Sáng
uint8_t led_value = 0;
// Thiết lập chân nút nhấn, và chân LED
button_config();
led_config();
// Vòng lặp vô tận
while (1) {
if (button_pressed) {
printf("* | Tone-type: %d \n", tone_var);
button_pressed = false;
led_value = !led_value;
// Thiết lập sáng tắt ở ngõ ra LED_RED bằng lệnh gpio_set_level()
gpio_set_level(LED_PIN, led_value);
if(tone_var == 1){
/* Thiết lập xung PWM tại ngõ ra BUZ_PIN và phát tín hiệu với tần số tùy ý;
Sử dụng lệnh ledc_set_duty() và ledc_update_duty () để tùy chỉnh CHANNEL đang sử dụng:
- DUTY = 0: không có xung
- DUTY = 50%: có xung */
buzzer_config(1000);
ledc_set_duty(LEDC_LOW_SPEED_MODE,LEDC_CHANNEL_2,LEDC_DUTY);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2);
}else if(tone_var == 2){
buzzer_config(10000);
ledc_set_duty(LEDC_LOW_SPEED_MODE,LEDC_CHANNEL_2,LEDC_DUTY);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2);
}else if(tone_var == 3){
buzzer_config(15000);
ledc_set_duty(LEDC_LOW_SPEED_MODE,LEDC_CHANNEL_2,LEDC_DUTY);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2);
}else{
buzzer_config(1000);
ledc_set_duty(LEDC_LOW_SPEED_MODE,LEDC_CHANNEL_2,0);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2);
}
}
// Thiết lập delay, tránh chạy nhiều. Cần thư viện freertos/FreeRTOS.h
vTaskDelay(DELAY_TIME / portTICK_PERIOD_MS);
}
}