你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32F769I-DISC的可调数字电源

[复制链接]
lugl 发布时间:2025-3-9 17:11

【硬件准备】 1、【EV1WO505B-LVH-00A】评估板。 2、四路继电器 3、STM32F769I-DISC评估板。 4、TFTLCD触摸屏。 【软件开发环境】 1、STM32CubeMX 主要对STM32F769的基础环境进行创建。 2、Vscocde代码编译器。 3、LVGL开源GUI图形界面。 4、Gui-Guider设计工具。 【原理图设计】

image.png

隔离电源模块的原理图:

image.png

根据原理图,需要把EN通过100K的电阻对GND1,低电平时,才可以通过CN1来切换对GND2或者Vout来实现3.3V或者5V的电压输出。

【界面设计】

我使用Gui-Guider工具设计了图形界面如下:

image.png

主要是思路是sw1开控制一组继电器,实现VIN的电源输入通断,通过sw2来实现电压的在线切换。

设计好后,使用Gui-Guider生成代码,复制custom、generated两个文件夹到原来lvgl工程目录下面,并把文件添加进CMakeLists.txt使他们参与编译。

【代码实现】

1、sw1sw2的点击事件,通过判断他的值来对应GPIO进行切换。代码如下:


static void screen_sw_1_event_handler(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    switch (code)
    {
    case LV_EVENT_VALUE_CHANGED:
    {
        lv_obj_t *status_obj = lv_event_get_target(e);
        int status = lv_obj_has_state(status_obj, LV_STATE_CHECKED) ? true : false;
        if (status == true)
        {
            power_switch_control(POWER_ON);
            printf("SW 1 is ON\r\n");
        }
        else
        {
            power_switch_control(POWER_OFF);
            printf("SW 1 is OFF\r\n");
        }
        break;
    }
    default:
        break;
    }
}

static void screen_sw_2_event_handler(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    switch (code)
    {
    case LV_EVENT_VALUE_CHANGED:
    {
        lv_obj_t *status_obj = lv_event_get_target(e);
        int status = lv_obj_has_state(status_obj, LV_STATE_CHECKED) ? true : false;
        if(status == true)
        {
            voltage_switch(VOLTAGE_5V);
            printf("SW 2 is ON\r\n");
        }
        else
        {
            voltage_switch(VOLTAGE_3V3);
            printf("SW 2 is OFF\r\n");
        }
        break;
    }
    default:
        break;
    }
}
/**
 * Create a demo application
 */

void custom_init(lv_ui *ui)
{
    lv_obj_add_event_cb(ui->screen_sw_1, screen_sw_1_event_handler, LV_EVENT_ALL, ui);
    lv_obj_add_event_cb(ui->screen_sw_2, screen_sw_2_event_handler, LV_EVENT_ALL, ui);
    /* Add your codes here */
}

2、编写一个mps.c/h的文件,把相关逻辑写出来,具体代码如下,详细功能在代码中注释:

#include "lvgl.h"
#include "gui_guider.h"
#include <stdio.h>

// 假设ADC句柄已经在别处正确初始化
extern ADC_HandleTypeDef hadc1;
extern lv_ui gui_guider_ui;

// 定义ADC的分辨率(对于12位ADC,分辨率为4096)
#define ADC_RESOLUTION 4096

// 定义参考电压(单位:伏特)
#define REFERENCE_VOLTAGE 3.3f

// 进行ADC采集并转换为保留一位小数的电压值
uint32_t adc_voltage_conversion(void)
{
    uint32_t adc_value;

    // 启动ADC转换
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
        printf("ADC conversion failed.\n");
        // 处理启动失败的情况
        return 0;
    }

    // 等待ADC转换完成
    if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) != HAL_OK)
    {
        printf("ADC conversion timeout.\n");
        // 处理转换失败的情况
        HAL_ADC_Stop(&hadc1);
        return 0;
    }
    // 等待ADC转换完成
    adc_value = HAL_ADC_GetValue(&hadc1);
    printf("ADC value: %d\n", adc_value);
    return adc_value;
}



// 电源开关控制函数
void power_switch_control(PowerStatus status)
{
    if (status == POWER_ON)
    {
        // 高电平开启电源
        HAL_GPIO_WritePin(ON_OFF_GPIO_Port, ON_OFF_Pin, GPIO_PIN_RESET);
    }
    else if (status == POWER_OFF)
    {
        // 低电平关闭电源
        HAL_GPIO_WritePin(ON_OFF_GPIO_Port, ON_OFF_Pin, GPIO_PIN_SET);
    }
}



// 电压转换功能函数
void voltage_switch(Voltage target_voltage)
{
    // 第一步:切换CH引脚
    if (target_voltage == VOLTAGE_5V)
    {
        // 高电平为5V
        HAL_GPIO_WritePin(CH_GPIO_Port, CH_Pin, GPIO_PIN_SET);
    }
    else if (target_voltage == VOLTAGE_3V3)
    {
        // 低电平为3.3V
        HAL_GPIO_WritePin(CH_GPIO_Port, CH_Pin, GPIO_PIN_RESET);
    }

    // 第二步:SWICTH_V拉高10ms再拉低
    HAL_GPIO_WritePin(SWICTH_V_GPIO_Port, SWICTH_V_Pin, GPIO_PIN_RESET);
    HAL_Delay(100); // 延时10ms
    HAL_GPIO_WritePin(SWICTH_V_GPIO_Port, SWICTH_V_Pin, GPIO_PIN_SET);
}

// 更新标签显示ADC采集电压值的函数
void update_label_with_voltage(void)
{
    uint32_t value = adc_voltage_conversion();
    float voltage = (float)value * 2 * REFERENCE_VOLTAGE / ADC_RESOLUTION ;

    char voltage_str[6];

    // 将电压值格式化为保留一位小数的字符串
    snprintf(voltage_str, sizeof(voltage_str), "%d.%02d", (int)voltage, (int)(voltage*100)%100);
    printf("ADC voltage: %s\n", voltage_str);
    // 更新标签文本
    lv_label_set_text(gui_guider_ui.screen_label_5, voltage_str);
    lv_obj_invalidate(gui_guider_ui.screen_label_5); // 标记控件需要重绘
}

最后,把update_labe_with_voltage放到主循环里周期调用。

【作品视频介绍】

https://www.bilibili.com/video/BV1eeRhYpEkR/

收藏 评论1 发布时间:2025-3-9 17:11

举报

1个回答
lugl 回答时间:2025-3-9 17:15:05

然后添加mps.c/h,实现对电源的开关、切换与电压显示,代码如下:

#include "lvgl.h"
#include "gui_guider.h"
#include <stdio.h>

// 假设ADC句柄已经在别处正确初始化
extern ADC_HandleTypeDef hadc1;
extern lv_ui gui_guider_ui;

// 定义ADC的分辨率(对于12位ADC,分辨率为4096)
#define ADC_RESOLUTION 4096

// 定义参考电压(单位:伏特)
#define REFERENCE_VOLTAGE 3.3f

// 进行ADC采集并转换为保留一位小数的电压值
uint32_t adc_voltage_conversion(void)
{
    uint32_t adc_value;

    // 启动ADC转换
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
        printf("ADC conversion failed.\n");
        // 处理启动失败的情况
        return 0;
    }

    // 等待ADC转换完成
    if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) != HAL_OK)
    {
        printf("ADC conversion timeout.\n");
        // 处理转换失败的情况
        HAL_ADC_Stop(&hadc1);
        return 0;
    }
    // 等待ADC转换完成
    adc_value = HAL_ADC_GetValue(&hadc1);
    printf("ADC value: %d\n", adc_value);
    return adc_value;
}



// 电源开关控制函数
void power_switch_control(PowerStatus status)
{
    if (status == POWER_ON)
    {
        // 高电平开启电源
        HAL_GPIO_WritePin(ON_OFF_GPIO_Port, ON_OFF_Pin, GPIO_PIN_RESET);
    }
    else if (status == POWER_OFF)
    {
        // 低电平关闭电源
        HAL_GPIO_WritePin(ON_OFF_GPIO_Port, ON_OFF_Pin, GPIO_PIN_SET);
    }
}



// 电压转换功能函数
void voltage_switch(Voltage target_voltage)
{
    // 第一步:切换CH引脚
    if (target_voltage == VOLTAGE_5V)
    {
        // 高电平为5V
        HAL_GPIO_WritePin(CH_GPIO_Port, CH_Pin, GPIO_PIN_SET);
    }
    else if (target_voltage == VOLTAGE_3V3)
    {
        // 低电平为3.3V
        HAL_GPIO_WritePin(CH_GPIO_Port, CH_Pin, GPIO_PIN_RESET);
    }

    // 第二步:SWICTH_V拉高10ms再拉低
    HAL_GPIO_WritePin(SWICTH_V_GPIO_Port, SWICTH_V_Pin, GPIO_PIN_RESET);
    HAL_Delay(100); // 延时10ms
    HAL_GPIO_WritePin(SWICTH_V_GPIO_Port, SWICTH_V_Pin, GPIO_PIN_SET);
}

// 更新标签显示ADC采集电压值的函数
void update_label_with_voltage(void)
{
    uint32_t value = adc_voltage_conversion();
    float voltage = (float)value * 2 * REFERENCE_VOLTAGE / ADC_RESOLUTION ;

    char voltage_str[6];

    // 将电压值格式化为保留一位小数的字符串
    snprintf(voltage_str, sizeof(voltage_str), "%d.%02d", (int)voltage, (int)(voltage*100)%100);
    printf("ADC voltage: %s\n", voltage_str);
    // 更新标签文本
    lv_label_set_text(gui_guider_ui.screen_label_5, voltage_str);
    lv_obj_invalidate(gui_guider_ui.screen_label_5); // 标记控件需要重绘
}

最后把更新函数放到主循环里周期调用就可以实现既有的功能了。

视频介绍:

https://www.bilibili.com/video/BV1eeRhYpEkR/

所属标签

ST中文论坛活动

即日起开启活动话题入口,之后的活动统一都放在此处,欢迎大家的加入!


最新内容

相似分享

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版