基于STM32与influxDB的电力监控系统-3
一、目标:
修改 main.c
文件,实现通过 KEY1 切换三个界面:主界面(数据页面)、电流电压波形界面和 FATFS 界面。
二、修改步骤:
增加一个页面定义,例如PAGE_FATFS,将原来的两个页面扩展为三个。
修改按键处理部分,按KEY1依次切换三个页面。
在循环中,根据当前页面显示不同的内容。当切换到FATFS页面时,显示FATFS相关的信息(类似于main_fatfs.c中的内容)。
由于FATFS页面需要初始化SD卡和挂载文件系统,我们需要将main_fatfs.c中的初始化代码移植过来,但要注意避免重复初始化。
考虑到内存和代码结构,我们可能需要将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;
}
四、主要修改内容
增加页面定义:
添加了
PAGE_FATFS
页面定义页面切换逻辑改为循环切换三个页面
添加FATFS相关头文件和初始化:
包含了FATFS相关的头文件
添加了FATFS初始化函数
init_fatfs()
添加了FATFS页面显示函数
display_fatfs_page()
优化页面管理:
只在数据页面和波形页面进行ADC数据采集和处理
切换到FATFS页面时暂停ADC采集以节省资源
添加了FATFS初始化标志,避免重复初始化
保持原有功能:
数据页面和波形页面的功能保持不变
ADC采集和波形显示逻辑保持不变