1.5. ESP32 外设驱动
本章介绍 ESP32 常用外设的驱动方法。
1.5.1. UART 串口
#include "driver/uart.h"
#include "driver/gpio.h"
#define UART_NUM UART_NUM_1
#define TXD_PIN GPIO_NUM_17
#define RXD_PIN GPIO_NUM_16
#define BUF_SIZE 1024
void uart_init(void)
{
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
uart_param_config(UART_NUM, &uart_config);
uart_set_pin(UART_NUM, TXD_PIN, RXD_PIN,
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(UART_NUM, BUF_SIZE * 2, 0, 0, NULL, 0);
}
void uart_send(const char *data)
{
uart_write_bytes(UART_NUM, data, strlen(data));
}
int uart_recv(char *buf, size_t len)
{
return uart_read_bytes(UART_NUM, buf, len, pdMS_TO_TICKS(100));
}
1.5.2. I2C
#include "driver/i2c.h"
#define I2C_MASTER_SCL GPIO_NUM_22
#define I2C_MASTER_SDA GPIO_NUM_21
#define I2C_MASTER_FREQ 100000 // 100 kHz
void i2c_init(void)
{
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA,
.scl_io_num = I2C_MASTER_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ,
};
i2c_param_config(I2C_NUM_0, &conf);
i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
}
esp_err_t i2c_write_reg(uint8_t dev_addr,
uint8_t reg_addr, uint8_t data)
{
uint8_t buf[] = {reg_addr, data};
return i2c_master_write_to_device(
I2C_NUM_0, dev_addr, buf, 2, pdMS_TO_TICKS(100));
}
uint8_t i2c_read_reg(uint8_t dev_addr, uint8_t reg_addr)
{
uint8_t data;
i2c_master_write_read_device(
I2C_NUM_0, dev_addr, ®_addr, 1,
&data, 1, pdMS_TO_TICKS(100));
return data;
}
1.5.3. SPI
#include "driver/spi_master.h"
#define SPI_MOSI GPIO_NUM_23
#define SPI_MISO GPIO_NUM_19
#define SPI_SCLK GPIO_NUM_18
#define SPI_CS GPIO_NUM_5
spi_device_handle_t spi;
void spi_init(void)
{
spi_bus_config_t buscfg = {
.mosi_io_num = SPI_MOSI,
.miso_io_num = SPI_MISO,
.sclk_io_num = SPI_SCLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4096,
};
spi_device_interface_config_t devcfg = {
.clock_speed_hz = 10 * 1000 * 1000, // 10 MHz
.mode = 0,
.spics_io_num = SPI_CS,
.queue_size = 1,
};
spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
spi_bus_add_device(SPI2_HOST, &devcfg, &spi);
}
void spi_transmit(uint8_t *tx, uint8_t *rx, size_t len)
{
spi_transaction_t t = {
.length = len * 8,
.tx_buffer = tx,
.rx_buffer = rx,
};
spi_device_transmit(spi, &t);
}
1.5.4. I2S(音频/I2S 数字音频)
#include "driver/i2s_std.h"
void i2s_init(void)
{
i2s_chan_handle_t tx_handle;
i2s_chan_config_t chan_cfg = {
.id = I2S_NUM_0,
.role = I2S_ROLE_MASTER,
.dma_desc_num = 6,
.dma_frame_num = 240,
};
i2s_std_config_t std_cfg = {
.clk_cfg = {
.sample_rate_hz = 44100,
.clk_src = I2S_CLK_SRC_DEFAULT,
.mclk_multiple = I2S_MCLK_MULTIPLE_256,
},
.slot_cfg = {
.data_bit_width = I2S_DATA_BIT_WIDTH_16BIT,
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO,
.slot_mode = I2S_SLOT_MODE_MONO,
},
.gpio_cfg = {
.mclk = GPIO_NUM_0,
.bclk = GPIO_NUM_4,
.ws = GPIO_NUM_5,
.dout = GPIO_NUM_18,
.din = GPIO_NUM_19,
},
};
i2s_new_channel(&chan_cfg, &tx_handle, NULL);
i2s_channel_init_std_mode(tx_handle, &std_cfg);
i2s_channel_enable(tx_handle);
}
1.5.5. ADC
#include "driver/adc.h"
#include "esp_adc_cal.h"
#define ADC_CHANNEL ADC1_CHANNEL_6 // GPIO34
#define ADC_WIDTH ADC_WIDTH_BIT_12
#define ADC_ATTEN ADC_ATTEN_DB_11 // 0~3.3V
static esp_adc_cal_characteristics_t adc_chars;
void adc_init(void)
{
adc1_config_width(ADC_WIDTH);
adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN);
esp_adc_cal_characterize(
ADC_UNIT_1, ADC_ATTEN, ADC_WIDTH, 3300, &adc_chars);
}
uint32_t adc_read_raw(void)
{
return adc1_get_raw(ADC_CHANNEL);
}
uint32_t adc_read_voltage(void)
{
uint32_t raw = adc1_get_raw(ADC_CHANNEL);
return esp_adc_cal_raw_to_voltage(raw, &adc_chars);
}
小心
ADC2 引脚在 WiFi 启用时不可用(WiFi 驱动占用了 ADC2 的硬件资源)。 使用 ADC 时优先选择 ADC1 通道(GPIO32~39)。