#include "Fuction.h"
#define TAEM_NUMBER 2025555625
#define TAEM_ADDRESS 0x000000 //共四字节,存储位置 000000 - 000003
#define SFLASH_ID 0xC84013
#include "Fuction.h"
#define TAEM_NUMBER 2025555625
#define TAEM_ADDRESS 0x000000 //共四字节,存储位置 000000 - 000003
#define SFLASH_ID 0xC84013
extern uint8_t TASK;
extern uint8_t rtc_year, rtc_month, rtc_day, rtc_hour, rtc_min, rtc_sec;
extern int sdk_begin_flag;
uint32_t GD_flash_id = 0;
uint32_t read_team_number = 0;
uint8_t show[] = "system idle";
uint32_t sys_ticks = 0;
volatile uint32_t last_sample_time = 0;
TestStruct test_struct;
ConfigStruct config_struct;
// 定义 gCurrentRatio
float gCurrentRatio = 1.0f;
// 定义 ratioTaskState
uint8_t ratioTaskState = 0;
// 定义 ratioOutputBuffer
uint8_t ratioOutputBuffer[100] = {0};
// 采样控制变量
volatile uint8_t sampling = 0;
volatile uint8_t led_state = 0;
uint32_t sample_period = 5000; // 默认采样周期为 5 秒
#include <stdio.h>
#include "adc.h" // 包含真实的 ADC 驱动头文件
// 定义 limitTaskState
uint8_t limitTaskState = 0;
// 定义 limitOutputBuffer
uint8_t limitOutputBuffer[100] = {0};
/**
* 从Flash读取变比
*/
float readRatioFromFlash(void) {
uint32_t rawData = 0;
spi_flash_buffer_read((uint8_t*)&rawData, 0x00010000, sizeof(uint32_t));
float ratio;
memcpy(&ratio, &rawData, sizeof(float));
return ratio;
}
/**
* 保存变比到Flash
*/
int saveRatioToFlash(float ratio) {
spi_flash_write_enable();
spi_flash_sector_erase(0x00010000);
uint32_t rawData;
memcpy(&rawData, &ratio, sizeof(float));
spi_flash_buffer_write((uint8_t*)&rawData, 0x00010000, sizeof(uint32_t));
spi_flash_wait_for_write_end();
return 0;
}
/**
* 初始化变比参数(系统启动时调用)
*/
void initRatioParameter(void) {
gCurrentRatio = readRatioFromFlash(); // 从Flash读取变比
if (gCurrentRatio < 0.0f || gCurrentRatio > 100.0f) {
gCurrentRatio = 1.0f; // 无效值设为默认
saveRatioToFlash(gCurrentRatio);
}
}
#define RATIO_ADDRESS 0x00010000 // 扇区100 (256KB边界)
#define LIMIT_ADDRESS 0x00020000 // 扇区200 (512KB边界)
#define PERIOD_ADDRESS 0x00030000 // 扇区300 (768KB边界)
// 通用Flash读取函数
float readFromFlash(uint32_t addr, float default_val, float min_val, float max_val) {
uint32_t rawData = 0;
if(spi_flash_buffer_read((uint8_t*)&rawData, addr, sizeof(uint32_t)) != SUCCESS) {
return default_val;
}
float value;
memcpy(&value, &rawData, sizeof(float));
if(value < min_val || value > max_val) {
saveToFlash(addr, default_val); // 保存默认值
return default_val;
}
return value;
}
// 优化任务状态机 - 使用静态变量保持状态
void processRatioTask(void) {
static uint8_t state = 0;
switch(state) {
case 0: // 初始化状态
sprintf((char*)ratioOutputBuffer, "Ratio=%.1f\r\nInput(0-100):", gCurrentRatio);
transmit_data(ratioOutputBuffer, strlen((char*)ratioOutputBuffer));
state = 1;
clear_rx_buffer(); // 清空接收缓冲区
break;
case 1: // 等待输入
if (has_valid_input()) {
float newRatio = parse_float_input();
if (newRatio >= 0.0f && newRatio <= 100.0f) {
if (saveRatioToFlash(newRatio) == 0) {
gCurrentRatio = newRatio;
sprintf((char*)ratioOutputBuffer, "Success! New ratio: %.1f", newRatio);
} else {
sprintf((char*)ratioOutputBuffer, "Flash write error!");
}
} else {
sprintf((char*)ratioOutputBuffer, "Invalid range (0-100)!");
}
transmit_data(ratioOutputBuffer, strlen((char*)ratioOutputBuffer));
state = 0; // 重置状态机
TASK = 0; // 清除任务标志
}
break;
}
}
// 新增采样周期设置功能
void set_sample_period(uint32_t period_ms) {
if (period_ms < 100) period_ms = 100; // 最小100ms
if (period_ms > 60000) period_ms = 60000; // 最大60秒
// 保存到Flash
spi_flash_write_enable();
spi_flash_sector_erase(PERIOD_ADDRESS);
spi_flash_buffer_write((uint8_t*)&period_ms, PERIOD_ADDRESS, sizeof(uint32_t));
spi_flash_wait_for_write_end();
// 更新当前值
sample_period = period_ms;
printf("New sample period: %lums\r\n", sample_period);
}
/**
* 在 OLED 上显示电压值
*/
void oled_show_voltage(float voltage) {
char voltage_str[20];
sprintf(voltage_str, "%.2f V", voltage);
oled_show_string(2, 1, (u8*)voltage_str, 16);
oled_refresh();
}
void log_sample(float voltage) {
static uint32_t count = 0;
if(count % 100 == 0) { // 每100次采样保存一次
char log_entry[50];
sprintf(log_entry, "%lu,%.2f\n", get_timestamp(), voltage);
write_to_sd_card(log_entry);
}
count++;
}
/**
* 真实的 ADC 采样函数
*/
float adc_sample(void) {
// 使用真实的 ADC 采样代码
uint16_t adcValue = adc_get_result(ADC_CHANNEL_0); // 假设使用通道 0
float voltage = (adcValue * 3.3f) / 4096.0f; // 假设 ADC 参考电压为 3.3V
return voltage * gCurrentRatio; // 应用变比
}
/**
* 定时器回调函数,用于控制采样周期
*/
void systick_callback(void) {
sys_ticks++; // 确保 sys_ticks 正在递增
if (sampling) {
if (sys_ticks - last_sample_time >= sample_period / 1000) { // 将毫秒转换为滴答
last_sample_time = sys_ticks;
// 触发采样
float voltage = adc_sample();
printf("ADC Voltage: %.2f V\r\n", voltage);
// 更新 OLED 显示
oled_show_voltage(voltage);
// 检查是否超过阈值
if (voltage > config_struct.limit) {
led_alarm_on(); // 点亮报警 LED
printf("Voltage OverLimit! Limit: %.2f V\r\n", config_struct.limit);
} else {
led_alarm_off(); // 关闭报警 LED
}
// 切换 LED 状态(每秒闪烁一次)
led_state = !led_state;
if (led_state) {
led_on(); // 假设 LED1 用于指示采样状态
} else {
led_off();
}
}
}
}
/**
* 开启 ADC 采样
*/
void start_sample(void) {
if (!sampling) {
sampling = 1;
last_sample_time = sys_ticks; // 重置采样计时器
printf("Sampling started\r\n");
// 更新 OLED 显示
oled_clear();
oled_show_string(0, 0, "sampling", 8);
oled_refresh();
// LED1 按 1s 周期闪烁
led_state = 1;
}
}
/**
* 停止 ADC 采样
*/
void stop_sample(void) {
if (sampling) {
sampling = 0;
printf("Sampling stopped\r\n");
oled_show_string(1, 1, (u8*)"system idle", 16);
oled_refresh();
led_off(); // 关闭指示 LED
}
}
void sys_config(void) {
// 时钟初始化
systick_config();
// 串口初始化
usart_dma_init();
/*--系统上电初始化测试--*/
printf("\n");
printf("====system init====\r\n");
delay_1ms(10);
// RTC初始化
RTC_Init();
// OLED初始化
oled_init();
// Flash初始化
spi_flash_init();
// FATFS初始化
bsp_tfcard_init();
initRatioParameter();
write_uint32_to_flash(TAEM_NUMBER, TAEM_ADDRESS);
delay_1ms(10);
read_team_number = 0;
read_team_number = read_uint32_from_flash(TAEM_ADDRESS);
printf("Device_ID:2025-CIMC-%d \r\n", read_team_number);
printf("====system ready====\r\n");
oled_show_string(1, 1, (u8*)"system idle", 16);
oled_refresh();
// 初始化参数(带默认值)
gCurrentRatio = readFromFlash(RATIO_ADDRESS, 1.0f, 0.0f, 100.0f);
config_struct.limit = readFromFlash(LIMIT_ADDRESS, 30.0f, 0.0f, 500.0f);
sample_period = readFromFlash(PERIOD_ADDRESS, 5000, 100, 60000);
// 初始化ADC
adc_init();
}
/**
* 从Flash读取阈值
*/
float readLimitFromFlash(void) {
uint32_t rawData = 0;
spi_flash_buffer_read((uint8_t*)&rawData, 0x00020000, sizeof(uint32_t));
float limit;
memcpy(&limit, &rawData, sizeof(float));
return limit;
}
/**
* 保存阈值到Flash
*/
int saveLimitToFlash(float limit) {
spi_flash_write_enable();
spi_flash_sector_erase(0x00020000);
uint32_t rawData;
memcpy(&rawData, &limit, sizeof(float));
spi_flash_buffer_write((uint8_t*)&rawData, 0x00020000, sizeof(uint32_t));
spi_flash_wait_for_write_end();
return 0;
}
/**
* 处理阈值设置任务(在主循环中调用)
*/
void processLimitTask(void) {
switch (limitTaskState) {
case 0:
// 状态0:输出提示并等待输入
sprintf((char*)limitOutputBuffer, "Limit=%.1f\r\nInput value(0-500):\r\n", config_struct.limit);
transmit_data(limitOutputBuffer, strlen((char*)limitOutputBuffer));
limitTaskState = 1; // 切换到输入等待状态
// 清空输入缓冲区
memset(rxbuffer, 0, MAX_BUFFER_SIZE);
g_rx_length = 0;
break;
case 1:
// 状态1:检测是否有新输入
if (g_transfer_complete == SET && g_rx_length > 0) {
g_transfer_complete = RESET;
float newLimit;
// 解析输入(添加超时保护)
if (sscanf((char*)rxbuffer, "%f", &newLimit) == 1) {
// 验证输入有效性
if (newLimit >= 0.0f && newLimit <= 500.0f) {
// 有效输入
config_struct.limit = newLimit;
if (saveLimitToFlash(newLimit) == 0) {
sprintf((char*)limitOutputBuffer, "limit modified success\r\nLimit = %.1f\r\n", newLimit);
} else {
sprintf((char*)limitOutputBuffer, "flash write error\r\nLimit=%.1f\r\n", config_struct.limit);
}
} else {
// 无效输入(范围错误)
sprintf((char*)limitOutputBuffer, "limit invalid (0-500 expected)\r\nLimit=%.1f\r\n", config_struct.limit);
}
} else {
// 无效输入(非数字)
sprintf((char*)limitOutputBuffer, "limit invalid (numeric value expected)\r\nLimit=%.1f\r\n", config_struct.limit);
}
// 输出结果并重置状态
transmit_data(limitOutputBuffer, strlen((char*)limitOutputBuffer));
limitTaskState = 2; // 切换到完成状态
}
break;
case 2:
// 状态2:等待任务标志清除
if (TASK != 9) {
limitTaskState = 0; // 重置状态
}
break;
default:
limitTaskState = 0;
break;
}
}
/**
* 初始化阈值参数(系统启动时调用)
*/
void initLimitParameter(void) {
config_struct.limit = readLimitFromFlash(); // 从Flash读取阈值
if (config_struct.limit < 0.0f || config_struct.limit > 500.0f) {
config_struct.limit = 30.0f; // 无效值设为默认
saveLimitToFlash(config_struct.limit);
}
}
void sys_sdk(void) {
switch (TASK) {
case 1:
if (sdk_begin_flag == 1) {
// 设置RTC时间
rtc_setup(rtc_year, rtc_month, rtc_day, rtc_hour, rtc_min, rtc_sec);
sdk_begin_flag = 0;
}
break;
case 3:
if (sdk_begin_flag == 1) {
// Flash自检
GD_flash_id = spi_flash_read_id();
if (GD_flash_id == SFLASH_ID) {
printf("flash.........ok\r\n");
test_struct.flash_status = 1;
} else {
printf("flash.........fail\r\n");
test_struct.flash_status = 0;
}
// TF自检
if (bsp_tfcard_init() == TF_OK) {
printf("TF card.........ok\r\n");
test_struct.tf_card_status = 1;
} else {
printf("TF card.........fail\r\n");
test_struct.tf_card_status = 0;
}
// 输出
if (test_struct.flash_status == 1) {
printf("flash ID: 0x%02X\r\n", GD_flash_id);
} else {
printf("can not find flash\r\n");
}
if (test_struct.tf_card_status == 1) {
test_struct.tf_memory = sd_card_capacity_get();
printf("TF card memory %" PRIu32 "KB\r\n", test_struct.tf_memory);
} else {
printf("can not find TFcard\r\n");
}
rtc_show_time();
printf("====system selftest====\r\n");
sdk_begin_flag = 0;
}
break;
case 4:// ratio
{
processRatioTask();
}
break;
case 5:// start
{
start_sample();
}
break;
case 6:// stop
{
stop_sample();
}
break;
case 7:// config save
{
// 保存配置逻辑可以在这里实现
printf("Config saved\r\n");
}
break;
case 8:// config read
{
// 读取配置逻辑可以在这里实现
printf("Config read\r\n");
}
break;
case 9:// limit
{
processLimitTask();
}
break;
default:
break;
}
}
void sys_usr(void) {
while (1) {
sys_sdk();
}
}出现了Build started: Project: Project
*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
Build target 'CIMC_GD32_fatfs_driver'
compiling Fuction.c...
..\sysFunction\Fuction.c(87): error: #41: expression must have arithmetic or pointer type
if(spi_flash_buffer_read((uint8_t*)&rawData, addr, sizeof(uint32_t)) != SUCCESS) {
..\sysFunction\Fuction.c(95): warning: #223-D: function "saveToFlash" declared implicitly
saveToFlash(addr, default_val); // 保存默认值
..\sysFunction\Fuction.c(109): warning: #223-D: function "clear_rx_buffer" declared implicitly
clear_rx_buffer(); // 清空接收缓冲区
..\sysFunction\Fuction.c(113): warning: #223-D: function "has_valid_input" declared implicitly
if (has_valid_input()) {
..\sysFunction\Fuction.c(114): warning: #223-D: function "parse_float_input" declared implicitly
float newRatio = parse_float_input();
..\sysFunction\Fuction.c(164): warning: #223-D: function "get_timestamp" declared implicitly
sprintf(log_entry, "%lu,%.2f\n", get_timestamp(), voltage);
..\sysFunction\Fuction.c(165): warning: #223-D: function "write_to_sd_card" declared implicitly
write_to_sd_card(log_entry);
..\sysFunction\Fuction.c(198): warning: #223-D: function "led_alarm_on" declared implicitly
led_alarm_on(); // 点亮报警 LED
..\sysFunction\Fuction.c(201): warning: #223-D: function "led_alarm_off" declared implicitly
led_alarm_off(); // 关闭报警 LED
..\sysFunction\Fuction.c(207): warning: #223-D: function "led_on" declared implicitly
led_on(); // 假设 LED1 用于指示采样状态
..\sysFunction\Fuction.c(209): warning: #223-D: function "led_off" declared implicitly
led_off();
..\sysFunction\Fuction.c(243): warning: #223-D: function "led_off" declared implicitly
led_off(); // 关闭指示 LED
..\sysFunction\Fuction.c(478): warning: #1-D: last line of file ends without a newline
}
..\sysFunction\Fuction.c: 12 warnings, 1 error
".\Objects\Project.axf" - 1 Error(s), 12 Warning(s).
Target not created.cuow
最新发布