当前位置: 首页 > news >正文

基于STM32与influxDB的电力监控系统-3

一、目标:

       修改 main.c 文件,实现通过 KEY1 切换三个界面:主界面(数据页面)、电流电压波形界面和 FATFS 界面。

二、修改步骤:

  1. 增加一个页面定义,例如PAGE_FATFS,将原来的两个页面扩展为三个。

  2. 修改按键处理部分,按KEY1依次切换三个页面。

  3. 在循环中,根据当前页面显示不同的内容。当切换到FATFS页面时,显示FATFS相关的信息(类似于main_fatfs.c中的内容)。

  4. 由于FATFS页面需要初始化SD卡和挂载文件系统,我们需要将main_fatfs.c中的初始化代码移植过来,但要注意避免重复初始化。

  5. 考虑到内存和代码结构,我们可能需要将FATFS相关的变量和函数整合到main.c中。

三、具体修改:

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/malloc/malloc.h"  /* 添加内存管理头文件 */
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"
#include "./BSP/KEY/key.h"
#include "./BSP/SDMMC/spi_sdcard.h"
#include "./BSP/NORFLASH/norflash.h"
#include "./FATFS/exfuns/exfuns.h"
#include <math.h>#define ADC_DMA_BUF_SIZE        100 * 2      /* ADC DMA采集 BUF大小, 每个通道100次采样 */
uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE];   /* ADC DMA BUF */extern uint8_t g_adc_dma_sta;               /* DMA传输状态标志, 0,未完成; 1, 已完成 *//* 传感器参数定义 */
#define VREF        3.3f                    /* ADC参考电压3.3V */
#define ADC_RES     4096.0f                 /* 12位ADC分辨率 *//* 电流互感器参数 (ZMCT103C) */
#define CURRENT_RATIO       1000.0f         /* 变比1000:1 */
#define CURRENT_SENSITIVITY 0.1f            /* 灵敏度调节系数,根据实际校准调整 *//* 电压互感器参数 (ZMPT101B) */
#define VOLTAGE_RATIO       1000.0f         /* 变比1000:1000 */
#define VOLTAGE_SENSITIVITY 0.01f           /* 灵敏度调节系数,根据实际校准调整 *//* 页面定义 */
#define PAGE_DATA           0               /* 数据页面 */
#define PAGE_WAVE           1               /* 波形页面 */
#define PAGE_FATFS          2               /* FATFS页面 *//* 波形显示参数优化 */
#define WAVE_HEIGHT         80              /* 每个波形区域高度 */
#define WAVE_WIDTH          300             /* 波形显示区域宽度 */
#define WAVE_OFFSET_X       10              /* 波形显示区域X偏移 */
#define WAVE_OFFSET_Y       40              /* 波形显示区域Y偏移 */
#define WAVE_POINTS         150             /* 波形显示点数(减少点数提高性能) */
#define WAVE_UPDATE_INTERVAL 3              /* 每3次DMA采集更新一次波形 *//* 全局变量 */
uint8_t g_current_page = PAGE_DATA;         /* 当前页面 */
uint16_t g_wave_buffer[2][WAVE_POINTS];     /* 波形数据缓冲区 */
uint16_t g_wave_index = 0;                  /* 波形数据索引 */
uint8_t g_update_counter = 0;               /* 波形更新计数器 */
uint8_t g_fatfs_initialized = 0;            /* FATFS初始化标志 *//* 函数声明 */
float calculate_rms(uint16_t *data, uint16_t samples, uint8_t channel);
float adc_to_voltage(uint16_t adc_value);
float calculate_current(float voltage_rms);
float calculate_voltage(float voltage_rms);
void display_data_page(float current_rms, float voltage_rms, float current_value, float voltage_value);
void display_wave_page_optimized(void);
void draw_waveform_optimized(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t *data, uint16_t color);
void update_wave_data_optimized(uint16_t *adc_buf, uint16_t buf_size);
void display_fatfs_page(void);
uint8_t init_fatfs(void);int main(void)
{uint16_t i, j;float current_rms, voltage_rms;float current_value, voltage_value;uint8_t key_val;HAL_Init();                                 /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */delay_init(72);                             /* 延时初始化 */usart_init(115200);                         /* 串口初始化为115200 */led_init();                                 /* 初始化LED */lcd_init();                                 /* 初始化LCD */key_init();                                 /* 初始化按键 */adc_nch_dma_init((uint32_t)&g_adc_dma_buf); /* 初始化ADC DMA采集 *//* 初始化波形缓冲区 */for (i = 0; i < WAVE_POINTS; i++){g_wave_buffer[0][i] = 2048;  /* 电流波形数据初始化为中间值 */g_wave_buffer[1][i] = 2048;  /* 电压波形数据初始化为中间值 */}/* 显示初始页面 */lcd_clear(WHITE);lcd_show_string(30, 10, 200, 16, 16, "STM32 SENSOR SYSTEM", RED);lcd_show_string(30, 30, 200, 12, 12, "Current/Voltage Monitor", BLUE);lcd_show_string(50, 220, 200, 16, 16, "KEY1:Switch Page", BLUE);adc_dma_enable(ADC_DMA_BUF_SIZE);   /* 启动ADC DMA采集 */while (1){/* 按键扫描 */key_val = key_scan(0);if (key_val == KEY1_PRES)       /* KEY1按下 */{g_current_page = (g_current_page + 1) % 3;   /* 循环切换三个页面 */lcd_clear(WHITE);lcd_show_string(30, 10, 200, 16, 16, "STM32 SENSOR SYSTEM", RED);lcd_show_string(30, 30, 200, 12, 12, "Current/Voltage Monitor", BLUE);lcd_show_string(50, 220, 200, 16, 16, "KEY1:Switch Page", BLUE);/* 如果切换到FATFS页面且未初始化,则进行初始化 */if (g_current_page == PAGE_FATFS && !g_fatfs_initialized){if (init_fatfs() == 0){g_fatfs_initialized = 1;}}}if (g_adc_dma_sta == 1){/* 只在数据页面和波形页面处理ADC数据 */if (g_current_page == PAGE_DATA || g_current_page == PAGE_WAVE){/* 处理两个通道的数据 */for(j = 0; j < 2; j++)  /* 遍历2个通道 */{/* 计算RMS值 */float rms_value = calculate_rms(g_adc_dma_buf, ADC_DMA_BUF_SIZE / 2, j);if (j == 0)  /* 电流传感器通道 */{current_rms = rms_value;current_value = calculate_current(current_rms);}else if (j == 1)  /* 电压传感器通道 */{voltage_rms = rms_value;voltage_value = calculate_voltage(voltage_rms);}}/* 优化波形更新:控制更新频率 */g_update_counter++;if (g_update_counter >= WAVE_UPDATE_INTERVAL){update_wave_data_optimized(g_adc_dma_buf, ADC_DMA_BUF_SIZE);g_update_counter = 0;}}/* 根据当前页面显示内容 */if (g_current_page == PAGE_DATA){display_data_page(current_rms, voltage_rms, current_value, voltage_value);}else if (g_current_page == PAGE_WAVE){display_wave_page_optimized();  /* 使用优化后的波形显示 */}else if (g_current_page == PAGE_FATFS){display_fatfs_page();           /* 显示FATFS页面 */}g_adc_dma_sta = 0;                      /* 清除DMA采集完成状态标志 *//* 只在数据页面和波形页面继续ADC采集 */if (g_current_page == PAGE_DATA || g_current_page == PAGE_WAVE){adc_dma_enable(ADC_DMA_BUF_SIZE);       /* 启动下一次ADC DMA采集 */}}LED0_TOGGLE();delay_ms(10);  /* 减少延时,提高响应速度 */}
}/*** @brief       初始化FATFS* @param       无* @retval      0:成功 1:失败*/
uint8_t init_fatfs(void)
{uint8_t res = 0;/* 初始化NORFLASH */norflash_init();/* 初始化内存管理 */my_mem_init(SRAMIN);/* 检测SD卡 */if (sd_init()){lcd_show_string(30, 130, 200, 16, 16, "SD Card Error!", RED);return 1;}/* 初始化exfuns */exfuns_init();/* 挂载SD卡 */f_mount(fs[0], "0:", 1);/* 挂载FLASH */res = f_mount(fs[1], "1:", 1);if (res == 0X0D)   /* FLASH磁盘,FAT文件系统错误,重新格式化FLASH */{lcd_show_string(30, 130, 200, 16, 16, "Flash Disk Formatting...", RED);res = f_mkfs("1:", 0, 0, FF_MAX_SS);   /* 格式化FLASH */if (res == 0){f_setlabel((const TCHAR *)"1:ALIENTEK");  /* 设置Flash磁盘的名字为:ALIENTEK */}else{lcd_show_string(30, 130, 200, 16, 16, "Flash Disk Format Error ", RED);return 1;}}return 0;
}/*** @brief       显示FATFS页面* @param       无* @retval      无*/
void display_fatfs_page(void)
{static uint8_t first_display = 1;uint32_t total, free;if (first_display){lcd_fill(0, 50, 239, 200, WHITE);lcd_show_string(30, 60, 200, 16, 16, "FATFS FILE SYSTEM", RED);first_display = 0;}/* 获取SD卡容量信息 */if (exfuns_get_free("0", &total, &free) == 0){lcd_show_string(30, 80, 200, 16, 16, "SD Card Status: OK", BLUE);lcd_show_string(30, 100, 200, 16, 16, "SD Total Size:     MB", BLUE);lcd_show_string(30, 120, 200, 16, 16, "SD Free Size:     MB", BLUE);lcd_show_num(30 + 13 * 8, 100, total >> 10, 5, 16, BLUE);   /* 显示SD卡总容量 MB */lcd_show_num(30 + 13 * 8, 120, free >> 10, 5, 16, BLUE);    /* 显示SD卡剩余容量 MB */}else{lcd_show_string(30, 80, 200, 16, 16, "SD Card Status: ERROR", RED);}/* 显示页面标识 */lcd_show_string(100, 180, 200, 16, 16, "FATFS PAGE", RED);
}/*** @brief       显示数据页面* @param       current_rms: 电流RMS值* @param       voltage_rms: 电压RMS值* @param       current_value: 电流计算值* @param       voltage_value: 电压计算值* @retval      无*/
void display_data_page(float current_rms, float voltage_rms, float current_value, float voltage_value)
{static uint8_t first_display = 1;if (first_display){/* 清除数据区域 */lcd_fill(0, 50, 239, 200, WHITE);/* 显示电流传感器信息 */lcd_show_string(30, 60, 200, 12, 12, "CURRENT SENSOR:", BLUE);lcd_show_string(30, 75, 200, 12, 12, "ADC_CH0_RMS:", BLUE);lcd_show_string(30, 90, 200, 12, 12, "CURRENT: 0.000A", BLUE);/* 显示电压传感器信息 */lcd_show_string(30, 110, 200, 12, 12, "VOLTAGE SENSOR:", BLUE);lcd_show_string(30, 125, 200, 12, 12, "ADC_CH1_RMS:", BLUE);lcd_show_string(30, 140, 200, 12, 12, "VOLTAGE: 000.0V", BLUE);/* 显示页面标识 */lcd_show_string(100, 180, 200, 16, 16, "DATA PAGE", RED);first_display = 0;}/* 显示ADC RMS值 */lcd_fill(102, 75, 150, 87, WHITE);lcd_show_xnum(102, 75, (uint16_t)current_rms, 4, 12, 0, BLUE);lcd_fill(102, 125, 150, 137, WHITE);lcd_show_xnum(102, 125, (uint16_t)voltage_rms, 4, 12, 0, BLUE);/* 显示电流值 */lcd_fill(78, 90, 150, 102, WHITE);if (current_value < 10.0f)  /* 显示格式: X.XXX A */{lcd_show_xnum(78, 90, (uint16_t)current_value, 1, 12, 0, BLUE);   /* 整数部分 */float decimal_current = (current_value - (uint16_t)current_value) * 1000;   /* 小数部分 */lcd_show_xnum(90, 90, (uint16_t)decimal_current, 3, 12, 0X80, BLUE);      /* 小数部分 */lcd_show_string(114, 90, 200, 12, 12, "A", BLUE);}/* 显示电压值 */lcd_fill(78, 140, 150, 152, WHITE);if (voltage_value < 1000.0f)  /* 显示格式: XXX.X V */{lcd_show_xnum(78, 140, (uint16_t)voltage_value, 3, 12, 0, BLUE);    /* 整数部分 */float decimal_voltage = (voltage_value - (uint16_t)voltage_value) * 10;      /* 小数部分 */lcd_show_xnum(102, 140, (uint16_t)decimal_voltage, 1, 12, 0X80, BLUE);      /* 小数部分 */lcd_show_string(114, 140, 200, 12, 12, "V", BLUE);}
}/*** @brief       优化后的波形页面显示* @param       无* @retval      无*/
void display_wave_page_optimized(void)
{static uint8_t first_display = 1;if (first_display){/* 清除波形区域 */lcd_fill(0, 50, 239, 200, WHITE);/* 绘制电流波形区域 */lcd_draw_rectangle(WAVE_OFFSET_X, WAVE_OFFSET_Y, WAVE_OFFSET_X + WAVE_WIDTH, WAVE_OFFSET_Y + WAVE_HEIGHT, BLACK);lcd_show_string(WAVE_OFFSET_X + 5, WAVE_OFFSET_Y + 5, 100, 12, 12, "CURRENT (CH0)", RED);/* 绘制电压波形区域 */lcd_draw_rectangle(WAVE_OFFSET_X, WAVE_OFFSET_Y + WAVE_HEIGHT + 10, WAVE_OFFSET_X + WAVE_WIDTH, WAVE_OFFSET_Y + 2 * WAVE_HEIGHT + 10, BLACK);lcd_show_string(WAVE_OFFSET_X + 5, WAVE_OFFSET_Y + WAVE_HEIGHT + 15, 100, 12, 12, "VOLTAGE (CH1)", GREEN);/* 显示页面标识 */lcd_show_string(100, 190, 200, 16, 16, "WAVE PAGE", RED);first_display = 0;}/* 绘制波形 */draw_waveform_optimized(WAVE_OFFSET_X + 2, WAVE_OFFSET_Y + 15, WAVE_WIDTH - 4, WAVE_HEIGHT - 20, g_wave_buffer[0], RED);draw_waveform_optimized(WAVE_OFFSET_X + 2, WAVE_OFFSET_Y + WAVE_HEIGHT + 25, WAVE_WIDTH - 4, WAVE_HEIGHT - 20, g_wave_buffer[1], GREEN);
}/*** @brief       优化后的波形绘制函数* @param       x,y: 起始坐标* @param       width,height: 波形区域宽高* @param       data: 波形数据* @param       color: 波形颜色* @retval      无*/
void draw_waveform_optimized(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t *data, uint16_t color)
{uint16_t i, prev_x, prev_y, curr_x, curr_y;/* 清空波形区域 */lcd_fill(x, y, x + width, y + height, WHITE);/* 绘制坐标轴 */lcd_draw_hline(x, y + height/2, width, GRAY);  /* 水平中线 *//* 计算显示步长(根据点数调整) */uint16_t step = 1;if (WAVE_POINTS > width){step = WAVE_POINTS / width;if (step < 1) step = 1;}/* 查找数据范围用于自动缩放 */uint16_t data_min = 4095;uint16_t data_max = 0;for (i = 0; i < WAVE_POINTS; i += step){if (data[i] < data_min) data_min = data[i];if (data[i] > data_max) data_max = data[i];}/* 确保有足够的动态范围 */if (data_max - data_min < 100){data_min = (data_min > 100) ? data_min - 100 : 0;data_max = (data_max < 4095 - 100) ? data_max + 100 : 4095;}/* 绘制波形 */prev_x = x;prev_y = y + height - ((data[0] - data_min) * height / (data_max - data_min));/* 限制Y坐标在显示区域内 */if (prev_y < y) prev_y = y;if (prev_y > y + height) prev_y = y + height;for (i = step; i < WAVE_POINTS && (i * width / WAVE_POINTS) < width; i += step){curr_x = x + (i * width) / WAVE_POINTS;/* 将ADC值映射到显示高度 */curr_y = y + height - ((data[i] - data_min) * height / (data_max - data_min));/* 限制Y坐标在显示区域内 */if (curr_y < y) curr_y = y;if (curr_y > y + height) curr_y = y + height;/* 绘制线段 */lcd_draw_line(prev_x, prev_y, curr_x, curr_y, color);prev_x = curr_x;prev_y = curr_y;}
}/*** @brief       优化后的波形数据更新函数* @param       adc_buf: ADC DMA缓冲区* @param       buf_size: 缓冲区大小* @retval      无*/
void update_wave_data_optimized(uint16_t *adc_buf, uint16_t buf_size)
{uint16_t i, current_val, voltage_val;uint16_t samples_to_process = 20;  /* 每次处理20个样本 *//* 从DMA缓冲区提取原始波形数据 */for (i = 0; i < samples_to_process && i < buf_size / 2; i += 2){/* 提取电流和电压的原始ADC值 */current_val = adc_buf[2 * i];      /* 通道0:电流 */voltage_val = adc_buf[2 * i + 1];  /* 通道1:电压 *//* 移动波形数据(滚动显示) */for (uint16_t j = 0; j < WAVE_POINTS - 1; j++){g_wave_buffer[0][j] = g_wave_buffer[0][j + 1];g_wave_buffer[1][j] = g_wave_buffer[1][j + 1];}/* 添加新数据到缓冲区末尾 */g_wave_buffer[0][WAVE_POINTS - 1] = current_val;g_wave_buffer[1][WAVE_POINTS - 1] = voltage_val;}
}/*** @brief       计算ADC值的RMS(有效值)* @param       data: ADC数据数组* @param       samples: 采样点数* @param       channel: 通道号* @retval      RMS值*/
float calculate_rms(uint16_t *data, uint16_t samples, uint8_t channel)
{uint32_t sum = 0;uint16_t i;/* 计算直流分量(平均值) */for (i = 0; i < samples; i++){sum += data[2 * i + channel];}float dc_offset = (float)sum / samples;/* 计算交流分量的RMS */float ac_sum = 0;for (i = 0; i < samples; i++){float ac_value = (float)data[2 * i + channel] - dc_offset;ac_sum += ac_value * ac_value;}return sqrtf(ac_sum / samples);
}/*** @brief       ADC值转换为电压值* @param       adc_value: ADC值* @retval      电压值(V)*/
float adc_to_voltage(uint16_t adc_value)
{return (float)adc_value * VREF / ADC_RES;
}/*** @brief       计算电流值* @param       voltage_rms: 电压RMS值* @retval      电流值(A)*/
float calculate_current(float voltage_rms)
{float voltage = adc_to_voltage(voltage_rms);/* 电流计算:电压值 × 变比倒数 × 灵敏度系数 */return voltage * (1.0f / CURRENT_RATIO) * CURRENT_SENSITIVITY;
}/*** @brief       计算电压值* @param       voltage_rms: 电压RMS值* @retval      电压值(V)*/
float calculate_voltage(float voltage_rms)
{float voltage = adc_to_voltage(voltage_rms);/* 电压计算:电压值 × 变比 × 灵敏度系数 */return voltage * VOLTAGE_RATIO * VOLTAGE_SENSITIVITY;
}

四、主要修改内容

  1. 增加页面定义

    • 添加了 PAGE_FATFS 页面定义

    • 页面切换逻辑改为循环切换三个页面

  2. 添加FATFS相关头文件和初始化

    • 包含了FATFS相关的头文件

    • 添加了FATFS初始化函数 init_fatfs()

    • 添加了FATFS页面显示函数 display_fatfs_page()

  3. 优化页面管理

    • 只在数据页面和波形页面进行ADC数据采集和处理

    • 切换到FATFS页面时暂停ADC采集以节省资源

    • 添加了FATFS初始化标志,避免重复初始化

  4. 保持原有功能

    • 数据页面和波形页面的功能保持不变

    • ADC采集和波形显示逻辑保持不变

http://www.dtcms.com/a/414253.html

相关文章:

  • STM32 程序下载失败的问题原因和解决方法集合!
  • 【读论文】AI笔记(一)9月26日组会前
  • 逻辑的回归——一阶谓词逻辑及其变体在自然语言处理深层语义分析中的作用与前瞻
  • Java EE初阶启程记03---Thread类及常见方法
  • 医疗行业 AI 投毒攻击原理及防护研究
  • PostIn入门到实战(5) - 如何快速导入PostMan数据,实现数据迁移
  • 让别人做网站需要注意什么服务器试用
  • 京东JoyAgent-JDGenie开源多智能体系统如何重塑AI应用落地新范式
  • idea学习日记7: StringBuilder的基本操作
  • MySQL专用服务器自动调优指南
  • Ubuntu24.04 安卓模拟器安装指南
  • 做餐饮网站价格网站建设内部优化
  • AI大模型开发语言排行
  • UMI企业智脑知识与数据管理:企业的智慧宝库
  • B3611 【模板】传递闭包-普及/提高-
  • 网上帮别人做网站深圳网站营销公司
  • 国内完美安装 Rust 环境 + VSCode 编写 Hello World 完整指南(2025 最新)
  • 基于 HTML、CSS 和 JavaScript 的智能图像灰度直方图匹配系统
  • 【自然语言处理与大模型】LlamaIndex快速入门①
  • 基于html2web和deepseek实现单词卡片识记功能的web设计
  • 定制开发开源AI智能名片S2B2C商城小程序在智慧零售价值链重构中的价值研究
  • 虚拟机建设网站猎聘网招聘
  • Uvicorn - Python ASGI Web 服务器
  • Ubuntu硬件性能测试工具
  • DragonBalls_One004
  • LinuxC++——gflags框架入门
  • 开源 C# 快速开发(七)通讯--串口
  • 容器化安装新趋势:云原生到边缘计算
  • 【Linux】深入理解Linux的进程(一)
  • 【JAVA】从入门到放弃-03:IDEA、AI插件、工程结构