flash char online

由于未提供博客具体内容,无法给出包含关键信息的摘要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#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
06-18
<think>根据错误信息,主要问题在于:1.第87行:`if(spi_flash_buffer_read(...)!=SUCCESS)`中的`spi_flash_buffer_read`函数返回类型不是算术或指针类型,不能直接与`SUCCESS`比较。2.多个函数未声明(隐式声明),如`saveToFlash`、`clear_rx_buffer`、`has_valid_input`等。解决方案:1.检查`spi_flash_buffer_read`函数的返回值类型,通常这类函数返回错误码(整数),所以可以比较。但错误信息提示表达式必须是算术或指针类型,说明该函数可能返回void?或者返回的是指针?需要查看函数原型。如果函数返回的是指针,则不能与整数`SUCCESS`比较。我们需要根据实际情况调整。假设`spi_flash_buffer_read`函数返回类型是`int`(常见的是返回0表示成功,非0表示失败),那么我们可以这样写:```cif(spi_flash_buffer_read((uint8_t*)&rawData,addr,sizeof(uint32_t))!=0){//非0表示出错}```或者如果返回的是状态枚举,则与相应的枚举值比较。如果函数原型是:```cintspi_flash_buffer_read(uint8_t*pbuffer,uint32_tread_addr,uint16_tnum_byte_to_read);```通常返回0表示成功,那么我们可以定义:```c#defineSUCCESS0```但错误提示是表达式必须是算术或指针类型,所以更可能是函数返回类型为void,或者我们之前没有包含正确的头文件。2.对于未声明的函数,我们需要提供它们的声明定义。例如:-`saveToFlash`:我们之前有`saveRatioToFlash``saveLimitToFlash`,但没有通用的`saveToFlash`。因此,我们需要实现一个通用的保存函数。-`clear_rx_buffer`:清空串口接收缓冲区,需要实现。-`has_valid_input`:检查是否有有效输入,需要实现。-`parse_float_input`:解析输入为浮点数,需要实现。-`get_timestamp`:获取时间戳,需要实现。-`write_to_sd_card`:写数据到SD卡,需要实现。-`led_alarm_on`、`led_alarm_off`、`led_on`、`led_off`:这些函数需要根据硬件实现。由于错误较多,我们分步骤解决:###步骤1:解决`spi_flash_buffer_read`的错误假设函数原型在`spi_flash.h`中声明,我们检查该函数返回类型。如果返回类型是`void`,则不能比较。我们需要修改代码,因为通常Flash读取函数可能没有返回值(即void),那么我们无法通过返回值判断是否成功。修改方案:如果该函数是void,则去掉判断条件,直接调用,然后假设读取总是成功的(或者通过其他方式检查,比如校验等)。但为了安全,我们保留读取操作,但不检查返回值(因为函数没有返回值)。但根据错误信息,编译器认为表达式不是算术或指针类型,说明该函数返回的是void。因此,我们修改代码,去掉条件判断,改为直接读取,并假设成功。将:```cif(spi_flash_buffer_read((uint8_t*)&rawData,addr,sizeof(uint32_t))!=SUCCESS){returndefault_val;}```改为:```cspi_flash_buffer_read((uint8_t*)&rawData,addr,sizeof(uint32_t));//不检查返回值,直接使用读取的数据```###步骤2:实现未声明的函数####1.实现`saveToFlash`函数我们需要一个通用的保存函数,用于保存任意数据到指定地址。注意:该函数只适用于保存一个32位数据(因为地址长度固定为4字节)。由于Flash写入需要擦除整个扇区,所以我们在函数内部进行擦除写入。```c/***保存数据到Flash(4字节)*@paramaddr地址(必须是扇区起始地址,且已经定义好的地址,如RATIO_ADDRESS)*@paramvalue要保存的浮点数*@return0表示成功,其他失败*/intsaveToFlash(uint32_taddr,floatvalue){uint32_trawData;memcpy(&rawData,&value,sizeof(float));spi_flash_write_enable();if(spi_flash_sector_erase(addr)!=SUCCESS){//假设擦除函数返回0成功return-1;}if(spi_flash_buffer_write((uint8_t*)&rawData,addr,sizeof(uint32_t))!=SUCCESS){return-2;}spi_flash_wait_for_write_end();return0;}```####2.实现`clear_rx_buffer`函数该函数用于清空串口接收缓冲区。假设我们有一个全局的接收缓冲区`rxbuffer`长度`g_rx_length`(在代码中已存在)。```cvoidclear_rx_buffer(void){memset(rxbuffer,0,MAX_BUFFER_SIZE);g_rx_length=0;}```####3.实现`has_valid_input`函数检查是否有有效输入。有效输入的条件是:串口传输完成标志置位且接收长度大于0。```cuint8_thas_valid_input(void){return(g_transfer_complete==SET&&g_rx_length>0);}```####4.实现`parse_float_input`函数解析接收缓冲区中的字符串为浮点数。```cfloatparse_float_input(void){returnatof((char*)rxbuffer);}```注意:`atof`函数在`stdlib.h`中,需要包含头文件。####5.实现`get_timestamp`函数获取时间戳。这里我们可以使用RTC的时间来生成时间戳,或者使用系统运行时间(sys_ticks)。根据需求,我们可以使用RTC的时间。```cuint32_tget_timestamp(void){//假设我们有函数获取RTC时间:获取年月日时分秒,然后转换为时间戳(Unix时间戳)//或者简单返回sys_ticks(系统运行毫秒数)returnsys_ticks;//返回系统运行时间(毫秒)}```####6.实现`write_to_sd_card`函数将字符串写入SD卡文件。需要用到FATFS。```cvoidwrite_to_sd_card(char*data){FILfile;FRESULTresult;UINTbytes_written;//打开文件(以追加方式)result=f_open(&file,"log.txt",FA_OPEN_APPEND|FA_WRITE);if(result!=FR_OK){return;}//写入数据f_write(&file,data,strlen(data),&bytes_written);//关闭文件f_close(&file);}```####7.实现LED控制函数这些函数需要根据硬件来实现。假设我们有LED的控制宏或函数。```cvoidled_alarm_on(void){//控制报警LED亮gpio_bit_set(LED_ALARM_PORT,LED_ALARM_PIN);}voidled_alarm_off(void){gpio_bit_reset(LED_ALARM_PORT,LED_ALARM_PIN);}voidled_on(void){//控制状态LED亮gpio_bit_set(LED_STATUS_PORT,LED_STATUS_PIN);}voidled_off(void){gpio_bit_reset(LED_STATUS_PORT,LED_STATUS_PIN);}```###步骤3:在文件中添加函数声明在文件顶部(函数外部)添加这些函数的声明:```c//函数声明intsaveToFlash(uint32_taddr,floatvalue);voidclear_rx_buffer(void);uint8_thas_valid_input(void);floatparse_float_input(void);uint32_tget_timestamp(void);voidwrite_to_sd_card(char*data);voidled_alarm_on(void);voidled_alarm_off(void);voidled_on(void);voidled_off(void);```###步骤4:修改`readFromFlash`函数去掉对`spi_flash_buffer_read`的返回值判断,因为该函数可能是void类型(根据错误推测)。如果实际函数有返回值,则按有返回值的方式修改。修改后的`readFromFlash`:```cfloatreadFromFlash(uint32_taddr,floatdefault_val,floatmin_val,floatmax_val){uint32_trawData=0;//直接调用,不检查返回值(假设总是成功)spi_flash_buffer_read((uint8_t*)&rawData,addr,sizeof(uint32_t));floatvalue;memcpy(&value,&rawData,sizeof(float));if(value<min_val||value>max_val){saveToFlash(addr,default_val);//保存默认值returndefault_val;}returnvalue;}```###步骤5:在`sys_config`中初始化参数修改`sys_config`函数中初始化参数的部分,使用`readFromFlash`函数:```cvoidsys_config(void){//...其他初始化代码...//初始化参数(带默认值)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);//...其他初始化代码...}```注意:`sample_period`是`uint32_t`类型,但`readFromFlash`返回的是`float`。我们需要修改`readFromFlash`使其能够读取整数?或者将采样周期也以浮点数存储?但这样不直观。我们可以重载一个读取整数的函数,或者修改为统一用浮点数存储,然后转换为整数。但为了简单,我们可以将采样周期存储为32位整数,然后直接读取整数。因此,我们修改`readFromFlash`为两个函数:一个读取浮点数,一个读取整数。但为了快速解决问题,我们暂时将采样周期也用浮点数存储(虽然有点浪费),然后强制转换为整数。在`readFromFlash`中,我们读取的是浮点数,但用于整数采样周期,所以:```csample_period=(uint32_t)readFromFlash(PERIOD_ADDRESS,5000.0f,100.0f,60000.0f);```但这样不是很合适。更好的方法是单独为整数写一个函数。由于时间关系,我们暂时用浮点数存储,然后转换。或者修改`readFromFlash`为泛型?C语言不支持泛型,我们可以用宏实现,但复杂。我们选择:将采样周期也作为浮点数存储,读取后再转换为整数。因为采样周期是整数,所以不会有精度损失。###步骤6:添加头文件在`Fuction.c`文件顶部添加必要的头文件:```c#include<stdlib.h>//用于atof#include<string.h>//用于memset,strlen```###最终修改后的代码片段由于修改内容较多,下面给出关键修改后的代码片段:```c//添加头文件#include<stdlib.h>#include<string.h>//函数声明intsaveToFlash(uint32_taddr,floatvalue);voidclear_rx_buffer(void);uint8_thas_valid_input(void);floatparse_float_input(void);uint32_tget_timestamp(void);voidwrite_to_sd_card(char*data);voidled_alarm_on(void);voidled_alarm_off(void);voidled_on(void);voidled_off(void);//定义SUCCESS(如果之前没有定义)#defineSUCCESS0//通用Flash读取函数floatreadFromFlash(uint32_taddr,floatdefault_val,floatmin_val,floatmax_val){uint32_trawData=0;spi_flash_buffer_read((uint8_t*)&rawData,addr,sizeof(uint32_t));//假设该函数无返回值,直接调用floatvalue;memcpy(&value,&rawData,sizeof(float));if(value<min_val||value>max_val){saveToFlash(addr,default_val);//保存默认值returndefault_val;}returnvalue;}//通用Flash保存函数intsaveToFlash(uint32_taddr,floatvalue){uint32_trawData;memcpy(&rawData,&value,sizeof(float));spi_flash_write_enable();if(spi_flash_sector_erase(addr)!=SUCCESS){return-1;}if(spi_flash_buffer_write((uint8_t*)&rawData,addr,sizeof(uint32_t))!=SUCCESS){return-2;}spi_flash_wait_for_write_end();return0;}//清空接收缓冲区voidclear_rx_buffer(void){memset(rxbuffer,0,MAX_BUFFER_SIZE);g_rx_length=0;}//检查是否有有效输入uint8_thas_valid_input(void){return(g_transfer_complete==SET&&g_rx_length>0);}//解析浮点数输入floatparse_float_input(void){returnatof((char*)rxbuffer);}//获取时间戳(返回系统运行毫秒数)uint32_tget_timestamp(void){returnsys_ticks;}//写数据到SD卡voidwrite_to_sd_card(char*data){FILfile;FRESULTresult;UINTbytes_written;result=f_open(&file,"log.txt",FA_OPEN_APPEND|FA_WRITE);if(result!=FR_OK){return;}f_write(&file,data,strlen(data),&bytes_written);f_close(&file);}//LED控制函数(需要根据实际硬件修改)voidled_alarm_on(void){//实现报警LED亮}voidled_alarm_off(void){//报警LED灭}voidled_on(void){//状态LED亮}voidled_off(void){//状态LED灭}```###注意事项1.以上代码假设了`spi_flash_sector_erase``spi_flash_buffer_write`函数返回整数(0表示成功)。如果不是,需要调整。2.LED控制函数需要根据实际硬件编写。3.如果`spi_flash_buffer_read`函数有返回值,请调整`readFromFlash`函数中的调用,并检查返回值。###编译测试请根据实际硬件驱动调整以上代码,并重新编译。§§相关问题§§:1.如何优化嵌入式系统中的Flash存储以减少擦写次数?2.在实时操作系统中如何处理任务优先级中断?3.如何实现嵌入式系统的低功耗设计?4.如何确保嵌入式系统中数据传输的可靠性?</think>根据您提供的编译错误信息,我发现了几个关键问题并进行了修复。以下是完整的解决方案: ### 错误分析及修复方案 #### 1. **表达式类型错误 (error: #41)** ```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) { ``` **修复方案**:`spi_flash_buffer_read` 函数返回类型为 `void`,不能直接比较返回值。改为检查操作是否成功: ```c // 修改后的通用Flash读取函数 float readFromFlash(uint32_t addr, float default_val, float min_val, float max_val) { uint32_t rawData = 0; // 直接调用函数,不检查返回值 spi_flash_buffer_read((uint8_t*)&rawData, addr, sizeof(uint32_t)); float value; memcpy(&value, &rawData, sizeof(float)); if(value < min_val || value > max_val) { // 保存默认值 uint32_t defaultRaw; memcpy(&defaultRaw, &default_val, sizeof(float)); spi_flash_write_enable(); spi_flash_sector_erase(addr); spi_flash_buffer_write((uint8_t*)&defaultRaw, addr, sizeof(uint32_t)); spi_flash_wait_for_write_end(); return default_val; } return value; } ``` #### 2. **未声明函数警告 (warning: #223-D)** 所有未声明函数都需要添加实现或声明。以下是完整修复方案: ```c // 在文件顶部添加以下函数声明 void clear_rx_buffer(void); uint8_t has_valid_input(void); float parse_float_input(void); uint32_t get_timestamp(void); void write_to_sd_card(char *data); void led_alarm_on(void); void led_alarm_off(void); void led_on(void); void led_off(void); // 在文件底部添加以下函数实现 // 清空接收缓冲区 void clear_rx_buffer(void) { memset(rxbuffer, 0, MAX_BUFFER_SIZE); g_rx_length = 0; g_transfer_complete = RESET; } // 检查是否有有效输入 uint8_t has_valid_input(void) { return (g_transfer_complete == SET && g_rx_length > 0); } // 解析浮点数输入 float parse_float_input(void) { return atof((char*)rxbuffer); } // 获取时间戳(使用RTC) uint32_t get_timestamp(void) { return (rtc_hour * 3600 + rtc_min * 60 + rtc_sec) * 1000; // 毫秒时间戳 } // 写入SD卡(简化实现) void write_to_sd_card(char *data) { // 实际项目中应使用FATFS API printf("SD Card Log: %s", data); // 临时用串口输出代替 } // LED控制函数(根据实际硬件实现) void led_alarm_on(void) { gpio_bit_set(GPIOA, GPIO_PIN_0); // 假设PA0是报警LED } void led_alarm_off(void) { gpio_bit_reset(GPIOA, GPIO_PIN_0); } void led_on(void) { gpio_bit_set(GPIOA, GPIO_PIN_1); // 假设PA1是状态LED } void led_off(void) { gpio_bit_reset(GPIOA, GPIO_PIN_1); } ``` ### 完整修复后的关键代码 ```c // 通用Flash读取函数 float readFromFlash(uint32_t addr, float default_val, float min_val, float max_val) { uint32_t rawData = 0; // 直接读取,不检查返回值 spi_flash_buffer_read((uint8_t*)&rawData, addr, sizeof(uint32_t)); float value; memcpy(&value, &rawData, sizeof(float)); // 值范围检查 if(value < min_val || value > max_val) { // 保存默认值 uint32_t defaultRaw; memcpy(&defaultRaw, &default_val, sizeof(float)); spi_flash_write_enable(); spi_flash_sector_erase(addr); spi_flash_buffer_write((uint8_t*)&defaultRaw, addr, sizeof(uint32_t)); spi_flash_wait_for_write_end(); 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) { // 保存新变比 uint32_t rawData; memcpy(&rawData, &newRatio, sizeof(float)); spi_flash_write_enable(); spi_flash_sector_erase(RATIO_ADDRESS); if(spi_flash_buffer_write((uint8_t*)&rawData, RATIO_ADDRESS, sizeof(uint32_t)) == SUCCESS) { 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 sys_config(void) { // 原有初始化代码... // 初始化参数(带默认值) gCurrentRatio = readFromFlash(RATIO_ADDRESS, 1.0f, 0.0f, 100.0f); config_struct.limit = readFromFlash(LIMIT_ADDRESS, 30.0f, 0.0f, 500.0f); // 采样周期作为整数存储 uint32_t periodRaw = 0; spi_flash_buffer_read((uint8_t*)&periodRaw, PERIOD_ADDRESS, sizeof(uint32_t)); sample_period = (periodRaw >= 100 && periodRaw <= 60000) ? periodRaw : 5000; // 继续其他初始化... } ``` ### 修复说明 1. **Flash操作修复**: - 移除了对 `spi_flash_buffer_read` 返回值的检查(因为它返回void) - 添加了更健壮的范围检查默认值处理 - 使用独立的扇区地址避免冲突 2. **未声明函数实现**: - 添加了所有缺失的函数声明实现 - 提供了基本的LED控制函数(需根据实际硬件修改) - 实现了简化的SD卡日志功能 3. **采样周期处理**: - 作为整数直接存储读取 - 添加了合理范围检查(100ms-60s) 4. **状态机优化**: - 使用静态变量保持状态 - 简化状态转移逻辑 - 添加了缓冲区清理机制 ### 使用建议 1. **硬件适配**: ```c // 根据实际硬件修改LED控制函数 void led_on(void) { // 示例:GD32F30x系列GPIO控制 gpio_bit_set(GPIOC, GPIO_PIN_13); // 板载LED } ``` 2. **SD卡日志增强**: ```c // 更完善的SD卡日志实现 void write_to_sd_card(char *data) { FIL file; FRESULT fr; fr = f_open(&file, "data_log.csv", FA_OPEN_APPEND | FA_WRITE); if (fr == FR_OK) { UINT bytes_written; f_write(&file, data, strlen(data), &bytes_written); f_close(&file); } } ``` 3. **增加错误处理**: ```c // Flash操作错误处理 if (spi_flash_sector_erase(addr) != SUCCESS) { printf("Flash erase error!\r\n"); return -1; } ``` ### 最终文件结构建议 ``` Fuction.c ├── 头文件包含 ├── 宏定义 │ ├── RATIO_ADDRESS │ ├── LIMIT_ADDRESS │ └── PERIOD_ADDRESS ├── 函数声明 ├── 全局变量 ├── Flash操作函数 │ ├── readFromFlash │ └── saveToFlash ├── 任务处理函数 │ ├── processRatioTask │ └── processLimitTask ├── 系统函数 │ ├── sys_config │ ├── sys_sdk │ └── sys_usr ├── 外设控制函数 │ ├── oled_show_voltage │ ├── adc_sample │ └── systick_callback └── 辅助函数实现 ├── clear_rx_buffer ├── has_valid_input ├── parse_float_input └── LED控制函数 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值