Stimulate/main/esp32_s3_szp.c

485 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include "esp32_s3_szp.h"
static const char *TAG = "esp32_s3_szp";
/******************************************************************************/
/*************************** LED ↓ *******************************************/
void LED_init(void)
{
gpio_config_t io_conf = {};
// 配置LDAC
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << LED_PIN);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
gpio_set_level(LED_PIN, 1);
}
/*************************** LED ↑ *******************************************/
/*******************************************************************************/
/******************************************************************************/
/*************************** I2C ↓ *******************************************/
esp_err_t bsp_i2c_init(void)
{
i2c_config_t i2c_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = BSP_I2C_SDA,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = BSP_I2C_SCL,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = BSP_I2C_FREQ_HZ
};
i2c_param_config(BSP_I2C_NUM, &i2c_conf);
return i2c_driver_install(BSP_I2C_NUM, i2c_conf.mode, 0, 0, 0);
}
/*************************** I2C ↑ *******************************************/
/*******************************************************************************/
/******************************************************************************/
/*************************** AD5328BRUZ ↓ ******************************************/
// 全局SPI2设备句柄
spi_device_handle_t handle;
// 初始化SPI总线
esp_err_t init_spi() {
spi_bus_config_t bus_config = {
.miso_io_num = GPIO_NUM_NC, // 不使用MISO
.mosi_io_num = PIN_MOSI, // MOSI引脚
.sclk_io_num = PIN_SCK, // SCK引脚
.quadhd_io_num = GPIO_NUM_NC,
.quadwp_io_num = GPIO_NUM_NC,
};
esp_err_t ret = spi_bus_initialize(SPI_HOST, &bus_config, 0);
if (ret != ESP_OK) {
ESP_LOGE("SPI2", "Failed to initialize SPI bus.");
return ret;
}
return ESP_OK;
}
// 初始化SPI设备AD5328BRUZ
esp_err_t init_spi_device() {
spi_device_interface_config_t dev_config = {
.clock_speed_hz = 1000000, // 1 MHz SPI时钟
.mode = 0, // SPI模式0
.spics_io_num = PIN_CS, // SPI片选引脚
.queue_size = 1, // 队列大小
.flags = SPI_DEVICE_HALFDUPLEX, // 半双工模式
};
esp_err_t ret = spi_bus_add_device(SPI_HOST, &dev_config, &handle);
if (ret != ESP_OK) {
ESP_LOGE("SPI2", "Failed to add SPI device.");
return ret;
}
// 确保设备句柄有效
if (handle == NULL) {
ESP_LOGE("SPI2", "Invalid device handle.");
return ESP_FAIL;
}
return ESP_OK;
}
// 配置LDAC引脚
void configure_ldac() {
gpio_config_t io_conf = {};
// 配置LDAC
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << PIN_LDAC);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
// 配置DAC_EN
io_conf.pin_bit_mask = (1ULL << DAC_EN);
gpio_config(&io_conf);
gpio_set_level(DAC_EN, 1);
}
// 设置LDAC电平
void set_ldac_level(bool level) {
gpio_set_level(PIN_LDAC, level);
}
// 计算并设置指定通道的输出电压
void set_channel_voltage(uint8_t channel, float voltage) {
if (channel > 7) {
ESP_LOGE("DAC", "Invalid channel: %d. Only channels 0-7 are valid.", channel);
return;
}
// 将电压转换为12位数字值
uint16_t dac_value = (uint16_t)((voltage / V_REF) * 4095);
// 准备SPI数据包
uint8_t tx_data[2] = {
((channel & 0x07) << 4) | ((dac_value >> 8) & 0x0F), // 高字节通道位和高4位DAC值
(dac_value & 0xFF) // 低字节低8位DAC值
};
// 向AD5328BRUZ写入数据
spi_transaction_t t = {
.length = 16, // 数据长度 16位
.tx_buffer = tx_data, // 发送缓冲区
.rx_buffer = NULL // 不接收数据
};
esp_err_t ret = spi_device_transmit(handle, &t);
if (ret != ESP_OK) {
ESP_LOGE("SPI", "Failed to send DAC data for channel %d.", channel);
}
}
// 配置AD5328增益和Vref缓冲
void configure_gain_and_vref() {
uint8_t cmd[2] ={0x80,0x00}; // 设置增益为2倍启用Vref缓冲
// 向AD5328BRUZ写入数据
spi_transaction_t t = {
.length = 16, // 数据长度 16位
.tx_buffer = cmd, // 发送缓冲区
.rx_buffer = NULL // 不接收数据
};
esp_err_t ret = spi_device_transmit(handle,&t);
if (ret != ESP_OK) {
ESP_LOGE("SPI", "Failed to configure gain and Vref.");
}
}
void init_ad5328(void)
{
esp_err_t ret;
// 初始化SPI总线
ret = init_spi();
if (ret != ESP_OK) {
ESP_LOGE("SPI2", "SPI initialization failed.");
return;
}
// 初始化SPI设备
ret = init_spi_device();
if (ret != ESP_OK) {
ESP_LOGE("SPI2", "SPI device initialization failed.");
return;
}
// 配置LDAC引脚
configure_ldac();
// 启动LDAC
set_ldac_level(0); // 高电平启动LDAC
configure_gain_and_vref();
set_channel_voltage(0, 1.5f);
set_channel_voltage(1, 1.5f);
set_channel_voltage(2, 1.5f);
set_channel_voltage(3, 1.5f);
set_channel_voltage(4, 1.5f);
set_channel_voltage(5, 1.5f);
set_channel_voltage(6, 1.5f);
set_channel_voltage(7, 1.5f);
ESP_LOGI("SPI2", "SPI and AD5328BRUZ initialized successfully.");
}
/*************************** AD5328BRUZ ↑ *****************************************/
/*******************************************************************************/
/***********************************************************/
/**************** LCD显示屏 ↓ *************************/
// 背光PWM初始化
esp_err_t bsp_display_brightness_init(void)
{
// Setup LEDC peripheral for PWM backlight control
const ledc_channel_config_t LCD_backlight_channel = {
.gpio_num = BSP_LCD_BACKLIGHT,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LCD_LEDC_CH,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = 0,
.duty = 0,
.hpoint = 0,
.flags.output_invert = true
};
const ledc_timer_config_t LCD_backlight_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_10_BIT,
.timer_num = 0,
.freq_hz = 5000,
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&LCD_backlight_timer));
ESP_ERROR_CHECK(ledc_channel_config(&LCD_backlight_channel));
return ESP_OK;
}
// 背光亮度设置
esp_err_t bsp_display_brightness_set(int brightness_percent)
{
if (brightness_percent > 100) {
brightness_percent = 100;
} else if (brightness_percent < 0) {
brightness_percent = 0;
}
ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent);
// LEDC resolution set to 10bits, thus: 100% = 1023
uint32_t duty_cycle = (1023 * brightness_percent) / 100;
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty_cycle));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH));
return ESP_OK;
}
// 关闭背光
esp_err_t bsp_display_backlight_off(void)
{
return bsp_display_brightness_set(0);
}
// 打开背光 最亮
esp_err_t bsp_display_backlight_on(void)
{
return bsp_display_brightness_set(100);
}
// 定义液晶屏句柄
static esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_io_handle_t io_handle = NULL;
static esp_lcd_touch_handle_t tp; // 触摸屏句柄
static lv_disp_t *disp; // 指向液晶屏
static lv_indev_t *disp_indev = NULL; // 指向触摸屏
// 液晶屏初始化
esp_err_t bsp_display_new(void)
{
esp_err_t ret = ESP_OK;
// 背光初始化
ESP_RETURN_ON_ERROR(bsp_display_brightness_init(), TAG, "Brightness init failed");
// 初始化SPI总线
ESP_LOGD(TAG, "Initialize SPI bus");
const spi_bus_config_t buscfg = {
.sclk_io_num = BSP_LCD_SPI_CLK,
.mosi_io_num = BSP_LCD_SPI_MOSI,
.miso_io_num = GPIO_NUM_NC,
.quadwp_io_num = GPIO_NUM_NC,
.quadhd_io_num = GPIO_NUM_NC,
//.max_transfer_sz = BSP_LCD_H_RES * BSP_LCD_V_RES * sizeof(uint16_t),
.max_transfer_sz = BSP_LCD_H_RES * 40 * sizeof(uint16_t),
};
ESP_RETURN_ON_ERROR(spi_bus_initialize(BSP_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed");
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
const esp_lcd_panel_io_spi_config_t io_config = {
.dc_gpio_num = BSP_LCD_DC,
.cs_gpio_num = BSP_LCD_SPI_CS,
.pclk_hz = BSP_LCD_PIXEL_CLOCK_HZ,
.lcd_cmd_bits = LCD_CMD_BITS,
.lcd_param_bits = LCD_PARAM_BITS,
.spi_mode = 2,
.trans_queue_depth = 10,
};
ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &io_handle), err, TAG, "New panel IO failed");
// 初始化液晶屏驱动芯片ST7789
ESP_LOGD(TAG, "Install LCD driver");
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = BSP_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = BSP_LCD_BITS_PER_PIXEL,
};
ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle), err, TAG, "New panel failed");
esp_lcd_panel_reset(panel_handle); // 液晶屏复位
//lcd_cs(0); // 拉低CS引脚
esp_lcd_panel_init(panel_handle); // 初始化配置寄存器
esp_lcd_panel_invert_color(panel_handle, true); // 颜色反转
esp_lcd_panel_swap_xy(panel_handle, true); // 显示翻转
esp_lcd_panel_mirror(panel_handle, true, false); // 镜像
return ret;
err:
if (panel_handle) {
esp_lcd_panel_del(panel_handle);
}
if (io_handle) {
esp_lcd_panel_io_del(io_handle);
}
spi_bus_free(BSP_LCD_SPI_NUM);
return ret;
}
// LCD显示初始化
esp_err_t bsp_lcd_init(void)
{
esp_err_t ret = ESP_OK;
ret = bsp_display_new(); // 液晶屏驱动初始化
lcd_set_color(0x0000); // 设置整屏背景黑色
ret = esp_lcd_panel_disp_on_off(panel_handle, true); // 打开液晶屏显示
ret = bsp_display_backlight_on(); // 打开背光显示
return ret;
}
// 液晶屏初始化+添加LVGL接口
static lv_disp_t *bsp_display_lcd_init(void)
{
/* 初始化液晶屏 */
bsp_display_new(); // 液晶屏驱动初始化
lcd_set_color(0xffff); // 设置整屏背景白色
esp_lcd_panel_disp_on_off(panel_handle, true); // 打开液晶屏显示
/* 液晶屏添加LVGL接口 */
ESP_LOGD(TAG, "Add LCD screen");
const lvgl_port_display_cfg_t disp_cfg = {
.io_handle = io_handle,
.panel_handle = panel_handle,
.buffer_size = BSP_LCD_H_RES * BSP_LCD_DRAW_BUF_HEIGHT, // LVGL缓存大小
.double_buffer = true, // 是否开启双缓存
.hres = BSP_LCD_H_RES, // 液晶屏的宽
.vres = BSP_LCD_V_RES, // 液晶屏的高
.monochrome = false, // 是否单色显示器
/* Rotation的值必须和液晶屏初始化里面设置的 翻转 和 镜像 一样 */
.rotation = {
.swap_xy = true, // 是否翻转
.mirror_x = true, // x方向是否镜像
.mirror_y = false, // y方向是否镜像
},
.flags = {
.buff_dma = true, // 是否使用DMA 注意dma与spiram不能同时为true
.buff_spiram = false, // 是否使用PSRAM 注意dma与spiram不能同时为true
}
};
return lvgl_port_add_disp(&disp_cfg);
}
// 触摸屏初始化
esp_err_t bsp_touch_new(esp_lcd_touch_handle_t *ret_touch)
{
/* Initialize touch */
esp_lcd_touch_config_t tp_cfg = {
.x_max = BSP_LCD_V_RES,
.y_max = BSP_LCD_H_RES,
.rst_gpio_num = GPIO_NUM_NC, // Shared with LCD reset
.int_gpio_num = GPIO_NUM_NC,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 1,
.mirror_x = 1,
.mirror_y = 0,
},
};
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG();
ESP_RETURN_ON_ERROR(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)BSP_I2C_NUM, &tp_io_config, &tp_io_handle), TAG, "");
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_ft5x06(tp_io_handle, &tp_cfg, ret_touch));
return ESP_OK;
}
// 触摸屏初始化+添加LVGL接口
static lv_indev_t *bsp_display_indev_init(lv_disp_t *disp)
{
/* 初始化触摸屏 */
ESP_ERROR_CHECK(bsp_touch_new(&tp));
assert(tp);
/* 添加LVGL接口 */
const lvgl_port_touch_cfg_t touch_cfg = {
.disp = disp,
.handle = tp,
};
return lvgl_port_add_touch(&touch_cfg);
}
// 开发板显示初始化
void bsp_lvgl_start(void)
{
/* 初始化LVGL */
lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
lvgl_port_init(&lvgl_cfg);
/* 初始化液晶屏 并添加LVGL接口 */
disp = bsp_display_lcd_init();
/* 初始化触摸屏 并添加LVGL接口 */
disp_indev = bsp_display_indev_init(disp);
/* 打开液晶屏背光 */
bsp_display_backlight_on();
}
// 显示图片
void lcd_draw_pictrue(int x_start, int y_start, int x_end, int y_end, const unsigned char *gImage)
{
// 分配内存 分配了需要的字节大小 且指定在外部SPIRAM中分配
size_t pixels_byte_size = (x_end - x_start)*(y_end - y_start) * 2;
uint16_t *pixels = (uint16_t *)heap_caps_malloc(pixels_byte_size, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
if (NULL == pixels)
{
ESP_LOGE(TAG, "Memory for bitmap is not enough");
return;
}
memcpy(pixels, gImage, pixels_byte_size); // 把图片数据拷贝到内存
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_end, y_end, (uint16_t *)pixels); // 显示整张图片数据
heap_caps_free(pixels); // 释放内存
}
// 设置液晶屏颜色
void lcd_set_color(uint16_t color)
{
// 分配内存 这里分配了液晶屏一行数据需要的大小
uint16_t *buffer = (uint16_t *)heap_caps_malloc(BSP_LCD_H_RES * sizeof(uint16_t), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
if (NULL == buffer)
{
ESP_LOGE(TAG, "Memory for bitmap is not enough");
}
else
{
for (size_t i = 0; i < BSP_LCD_H_RES; i++) // 给缓存中放入颜色数据
{
buffer[i] = color;
}
for (int y = 0; y < 240; y++) // 显示整屏颜色
{
esp_lcd_panel_draw_bitmap(panel_handle, 0, y, 320, y+1, buffer);
}
free(buffer); // 释放内存
}
}
/*************** LCD显示屏 ↑ *************************/
/***********************************************************/