/****************************************************************************************************
* @file main.c
* @version V2.0
* @brief ¹¤ÒµÇ¶Èëʽϵͳ - µçѹ¼à²âϵͳ
****************************************************************************************************
*
* ʵÑéÆ½Ì¨: GD32F470VET6
* ¹¦ÄÜ˵Ã÷: µçѹ²É¼¯¡¢´¦Àí¡¢ÏÔʾ¡¢´æ´¢ÏµÍ³
* Ö§³Ö×Լ졢ʱ¼äÉèÖá¢ÅäÖùÜÀí¡¢²ÉÑù¿ØÖÆ¡¢Êý¾Ý´¦ÀíºÍ´æ´¢¹¦ÄÜ
****************************************************************************************************
*/
#include <./SYSTEM/sys/sys.h>
#include <./SYSTEM/usart/usart.h>
#include <./SYSTEM/delay/delay.h>
#include <./BSP/LED/led.h>
#include <./BSP/OLED/oled.h>
#include <./BSP/KEY/key.h>
#include <./BSP/RTC/rtc.h>
#include <./BSP/ADC/adc.h>
#include <./BSP/SDIO/sd_conf.h>
#include <./BSP/NORFLASH/norflash.h>
#include <./FATFS/exfuns/exfuns.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <./BSP/TIMER/timer.h>
/* È«¾Ö±äÁ¿¶¨Òå */
typedef struct {
float ratio; // ±ä±ÈϵÊý
float limit; // µçѹãÐÖµ
uint8_t sample_cycle; // ²ÉÑùÖÜÆÚ(5/10/15)
uint32_t log_file_id; // ÈÕÖ¾ÎļþID
} SystemConfig;
SystemConfig sys_config = {1.0, 100.0, 5, 0}; // ĬÈÏÅäÖÃ
uint8_t sampling_enabled = 0; // ²ÉÑù״̬±êÖ¾
uint8_t sample_count = 0; // µ±Ç°Îļþ²ÉÑù¼ÆÊý
uint8_t encrypt_mode = 0; // ¼ÓÃܴ洢ģʽ
FIL sample_file, overlimit_file, log_file, hide_file; // Îļþ¶ÔÏó
char current_filename[50]; // µ±Ç°ÎļþÃû»º´æ
uint32_t seconds_counter = 0; // Ãë¼ÆÊýÆ÷
uint8_t led_blink_state = 0; // LEDÉÁ˸״̬
uint32_t last_sample_time = 0; // ÉϴβÉÑùʱ¼ä
/* ÔÚÈ«¾Ö±äÁ¿¶¨Ò岿·ÖÌí¼Ó */
uint8_t hide_output_mode = 0; // Òþ²ØÊä³öģʽ±êÖ¾
/* Îļþ´ò¿ª×´Ì¬±êÖ¾ */
uint8_t sample_file_open = 0;
uint8_t overlimit_file_open = 0;
uint8_t log_file_open = 0;
uint8_t hide_file_open = 0;
/* ʱ¼ä½á¹¹Ìå */
typedef struct {
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t week;
} rtc_time_t;
/* º¯ÊýÉùÃ÷ */
void system_self_test(void);
void set_rtc_time(char *datetime);
void read_config_file(void);
void set_ratio(void);
void set_limit(void);
void save_config_to_flash(void);
void read_config_from_flash(void);
void start_sampling(void);
void stop_sampling(void);
void adjust_sample_cycle(uint8_t cycle);
void process_adc_sample(void);
void store_sample_data(float voltage, uint8_t overlimit);
void store_overlimit_data(float voltage);
void store_log_entry(const char *action);
void store_hide_data(uint32_t timestamp, float voltage);
uint32_t datetime_to_unix(rtc_time_t *time);
void encode_voltage(float voltage, uint8_t *buffer);
void oled_display_status(void);
void get_current_time(rtc_time_t *time);
uint32_t get_system_time(void);
/* Ìí¼ÓÒÔÏ´úÂëµ½timer.cÎļþĩβ */
volatile uint32_t timer6_counter = 0; // ¶¨Ê±Æ÷¼ÆÊýÆ÷
volatile uint8_t timer6_sample_flag = 0; // ²ÉÑù±êÖ¾
volatile uint8_t timer6_led_flag = 0; // LEDÉÁ˸±êÖ¾
/* ÔÚÈ«¾Ö±äÁ¿¶¨Ò岿·ÖÌí¼Ó */
volatile uint8_t timer6_time_update_flag = 0; // ʱ¼ä¸üбêÖ¾
/**
* @brief TIMER6ÖжϷþÎñº¯Êý
* @param ÎÞ
* @retval ÎÞ
*/
void TIMER6_IRQHandler(void)
{
if(timer_interrupt_flag_get(TIMER6, TIMER_INT_FLAG_UP) != RESET)
{
timer_interrupt_flag_clear(TIMER6, TIMER_INT_FLAG_UP);
timer6_counter++;
/* 1ÃëLEDÉÁ˸¿ØÖÆ */
if(timer6_counter % 1000 == 0) {
timer6_led_flag = 1;
timer6_time_update_flag = 1; // ÐÂÔöʱ¼ä¸üбêÖ¾
}
/* ²ÉÑùÖÜÆÚ¿ØÖÆ */
if(sampling_enabled && (timer6_counter % (sys_config.sample_cycle * 1000) == 0)) {
timer6_sample_flag = 1;
}
}
}
float oled_voltage;
/**
* @brief ¸üÐÂOLEDʱ¼äÏÔʾ
* @param ÎÞ
* @retval ÎÞ
*/
void update_oled_time(void)
{
uint16_t adcx;
float temp;
rtc_time_t current_time;
get_current_time(¤t_time);
char time_str[12];
sprintf(time_str, "%02d:%02d:%02d",
current_time.hour, current_time.minute, current_time.second);
oled_show_string(0, 0, time_str, 12);
adcx = adc_get_result_average(ADC_ADCX_CHY, 20); /* »ñȡͨµÀCHYµÄת»»Öµ£¬20´Îȡƽ¾ù */
oled_voltage = (float)adcx * (3.3 / 4096); /* ¼ÆËãʵ¼Êµçѹֵ */
char volt_str[16];
sprintf(volt_str, "%.2fV", oled_voltage); /* ¸ñʽ»¯Îª×Ö·û´®£¬±£ÁôÁ½Î»Ð¡Êý */
oled_show_string(0, 16, volt_str, 12); /* ÔÚÖ¸¶¨Î»ÖÃ(0,16)ÏÔʾ×Ö·û´®£¬×ÖÌå´óС12 */
oled_refresh_gram(); /* Ë¢ÐÂÏÔʾ */
oled_refresh_gram();
}
/**
* @brief »ñȡϵͳʱ¼ä£¨ºÁÃ룩
* @param ÎÞ
* @retval µ±Ç°ÏµÍ³Ê±¼ä£¨ºÁÃ룩
*/
uint32_t get_system_time(void) {
static uint32_t counter = 0;
static uint32_t last_tick = 0;
uint32_t current_tick = sys_tick_get();
counter += (current_tick - last_tick);
last_tick = current_tick;
return counter;
}
/**
* @brief »ñÈ¡µ±Ç°Ê±¼ä
* @param time: ʱ¼ä½á¹¹ÌåÖ¸Õë
* @retval ÎÞ
*/
void get_current_time(rtc_time_t *time)
{
uint8_t ampm;
rtc_get_date(&time->year, &time->month, &time->day, &time->week);
rtc_get_time(&time->hour, &time->minute, &time->second, &m);
}
/**
* @brief ϵͳ×Ô¼ì
* @param ÎÞ
* @retval ÎÞ
*/
void system_self_test(void)
{
uint16_t flash_id = norflash_read_id();
uint8_t sd_status = (SD_OK == sdio_sd_init()) ? 1 : 0;
rtc_time_t current_time;
get_current_time(¤t_time);
printf("=====system selftest=====\r\n");
printf("flash.............%s\r\n", (flash_id == GD25Q40) ? "ok" : "error");
printf("TF card............%s\r\n", sd_status ? "ok" : "error");
printf("flash ID:0x%04X\r\n", flash_id);
if(sd_status) {
uint32_t capacity = sd_card_capacity_get() >> 10; // KB
printf("TF card memory:%lu KB\r\n", capacity);
} else {
printf("can not find TF card\r\n");
}
printf("RTC:20%02d-%02d-%02d %02d:%02d:%02d\r\n",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second);
printf("=====system selftest=====\r\n");
}
/**
* @brief ÉèÖÃRTCʱ¼ä
* @param datetime: ʱ¼ä×Ö·û´®(¸ñʽ:2025-01-01 12:00:30)
* @retval ÎÞ
*/
void set_rtc_time(char *datetime)
{
int year, month, day, hour, min, sec;
sscanf(datetime, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &min, &sec);
rtc_set_date(year, month, day, 0); // ÐÇÆÚÉèΪ0
rtc_set_time(hour, min, sec, 0); // AM/PMÉèΪ0 (24Ð¡Ê±ÖÆ)
printf("RTC config success\r\n");
printf("Time:20%02d-%02d-%02d %02d:%02d:%02d\r\n", year, month, day, hour, min, sec);
}
/**
* @brief ¶ÁÈ¡ÅäÖÃÎļþ
* @param ÎÞ
* @retval ÎÞ
*/
void read_config_file(void)
{
FIL file;
FRESULT res;
char line[64];
res = f_open(&file, "config.ini", FA_READ);
if (res != FR_OK) {
printf("config.ini file not found.\r\n");
return;
}
while (f_gets(line, sizeof(line), &file)) {
if (strstr(line, "Ratio")) {
sscanf(line, "Ch0 = %f", &sys_config.ratio);
printf("Ratio = %.1f\r\n", sys_config.ratio);
} else if (strstr(line, "Limit")) {
sscanf(line, "ch0 = %f", &sys_config.limit);
printf("Limit = %.1f\r\n", sys_config.limit);
}
}
f_close(&file);
printf("config read success\r\n");
}
/**
* @brief ÉèÖñä±È
* @param ÎÞ
* @retval ÎÞ
*/
void set_ratio(void)
{
printf("Ratio = %.1f\r\n", sys_config.ratio);
printf("Input value(0-100):\r\n");
/* µÈ´ýÓû§ÊäÈë */
uint8_t key;
char input[16] = {0};
uint8_t index = 0;
while (1) {
key = key_scan(0);
if (key) {
if (key == KEY1_PRES) { // »Ø³µ
float new_ratio = atof(input);
if (new_ratio >= 0 && new_ratio <= 100) {
sys_config.ratio = new_ratio;
printf("Ratio modified success\r\n");
printf("Ratio = %.1f\r\n", sys_config.ratio);
store_log_entry("Ratio modified");
} else {
printf("Ratio invalid\r\n");
printf("Ratio = %.1f\r\n", sys_config.ratio);
}
break;
} else if (key == KEY2_PRES) { // Í˸ñ
if (index > 0) input[--index] = '\0';
} else { // Êý×ÖÊäÈë
if (index < 15) {
input[index++] = '0' + (key - 1);
input[index] = '\0';
}
}
}
delay_ms(10);
}
}
/**
* @brief ÉèÖÃãÐÖµ
* @param ÎÞ
* @retval ÎÞ
*/
void set_limit(void)
{
printf("Limit = %.1f\r\n", sys_config.limit);
printf("Input value(0-500):\r\n");
/* µÈ´ýÓû§ÊäÈë */
uint8_t key;
char input[16] = {0};
uint8_t index = 0;
while (1) {
key = key_scan(0);
if (key) {
if (key == KEY1_PRES) { // »Ø³µ
float new_limit = atof(input);
if (new_limit >= 0 && new_limit <= 500) {
sys_config.limit = new_limit;
printf("Limit modified success\r\n");
printf("Limit = %.1f\r\n", sys_config.limit);
store_log_entry("Limit modified");
} else {
printf("Limit invalid\r\n");
printf("Limit = %.1f\r\n", sys_config.limit);
}
break;
} else if (key == KEY2_PRES) { // Í˸ñ
if (index > 0) input[--index] = '\0';
} else { // Êý×ÖÊäÈë
if (index < 15) {
input[index++] = '0' + (key - 1);
input[index] = '\0';
}
}
}
delay_ms(10);
}
}
/**
* @brief ±£´æÅäÖõ½Flash
* @param ÎÞ
* @retval ÎÞ
*/
void save_config_to_flash(void)
{
printf("ratio = %.1f\r\n", sys_config.ratio);
printf("limit: %.2f\r\n", sys_config.limit);
/* ²Á³ýFlashÉÈÇø²¢Ð´ÈëÅäÖà */
norflash_erase_sector(0);
norflash_write((uint8_t*)&sys_config, 0, sizeof(sys_config));
printf("save parameters to flash\r\n");
store_log_entry("Config saved");
}
/**
* @brief ´ÓFlash¶ÁÈ¡ÅäÖÃ
* @param ÎÞ
* @retval ÎÞ
*/
void read_config_from_flash(void)
{
SystemConfig config;
norflash_read((uint8_t*)&config, 0, sizeof(config));
/* ÑéÖ¤Êý¾ÝÓÐЧÐÔ */
if (config.ratio >= 0 && config.ratio <= 100 &&
config.limit >= 0 && config.limit <= 500) {
sys_config = config;
}
printf("read parameters from flash\r\n");
printf("ratio:%.1f\r\n", sys_config.ratio);
printf("limit:%.2f\r\n", sys_config.limit);
}
/**
* @brief ¿ªÊ¼²ÉÑù
* @param ÎÞ
* @retval ÎÞ
*/
void start_sampling(void)
{
sampling_enabled = 1;
led_blink_state = 1;
LED1(1); // ³õʼµãÁÁ
timer6_counter = 0; // ÖØÖö¨Ê±Æ÷¼ÆÊýÆ÷
timer6_sample_flag = 0;
timer6_led_flag = 0;
timer6_time_update_flag = 0;
/* ³õʼ»¯OLEDÏÔʾ */
rtc_time_t current_time;
get_current_time(¤t_time);
char time_str[12], volt_str[16];
sprintf(time_str, "%02d:%02d:%02d",
current_time.hour, current_time.minute, current_time.second);
sprintf(volt_str, "0.00V"); // ³õʼµçѹֵ
oled_clear();
oled_show_string(0, 0, time_str, 12);
oled_show_string(0, 16, volt_str, 12);
oled_refresh_gram();
/* ÆôÓö¨Ê±Æ÷ */
timer_enable(TIMER6);
printf("Periodic Sampling\r\n");
printf("sample cycle: %ds\r\n", sys_config.sample_cycle);
store_log_entry("Sampling started");
}
/**
* @brief Í£Ö¹²ÉÑù
* @param ÎÞ
* @retval ÎÞ
*/
void stop_sampling(void)
{
sampling_enabled = 0;
LED1(0);
LED2(0);
/* ½ûÓö¨Ê±Æ÷ */
timer_disable(TIMER6);
oled_clear();
oled_show_string(0, 0, "system idle", 12);
oled_refresh_gram();
printf("Periodic Sampling STOP\r\n");
/* ¹Ø±ÕËùÓдò¿ªµÄÎļþ */
if (sample_file_open) {
f_close(&sample_file);
sample_file_open = 0;
}
if (overlimit_file_open) {
f_close(&overlimit_file);
overlimit_file_open = 0;
}
if (hide_file_open) {
f_close(&hide_file);
hide_file_open = 0;
}
store_log_entry("Sampling stopped");
}
/**
* @brief µ÷Õû²ÉÑùÖÜÆÚ
* @param cycle: ²ÉÑùÖÜÆÚ(5/10/15)
* @retval ÎÞ
*/
void adjust_sample_cycle(uint8_t cycle)
{
sys_config.sample_cycle = cycle;
/* ÖØÐÂÅäÖö¨Ê±Æ÷ */
timer_disable(TIMERX_INT);
timer_deinit(TIMERX_INT);
/* ¸ù¾Ý²»Í¬ÖÜÆÚÉèÖö¨Ê±Æ÷ */
// switch(cycle) {
// case 5:
// timerx_int_init(2000-1, 120-1); // 240MHz/(239+1)=1MHz, (999+1)/1MHz=1ms
// break;
// case 10:
// timerx_int_init(1500-1, 120-1); // 10ÃëÖÜÆÚ
// break;
// case 15:
// timerx_int_init(1000-1, 120-1); // 15ÃëÖÜÆÚ
// break;
// }
switch(cycle) {
case 5:
timer_disable(TIMERX_INT);
timer_deinit(TIMERX_INT);
timerx_int_init(1500-1, 120-1); // 5ÃëÖÜÆÚ
break;
case 10:
timer_disable(TIMERX_INT);
timer_deinit(TIMERX_INT);
timerx_int_init(1000-1, 120-1); // 10ÃëÖÜÆÚ
break;
case 15:
timer_disable(TIMERX_INT);
timer_deinit(TIMERX_INT);
timerx_int_init(1000-1, 120-1); // 15ÃëÖÜÆÚ
break;
}
if(sampling_enabled) {
timer_enable(TIMERX_INT);
}
printf("sample cycle adjust: %ds\r\n", cycle);
store_log_entry("Sample cycle adjusted");
/* ±£´æÐÂÖÜÆÚµ½Flash */
save_config_to_flash();
}
/**
* @brief ´¦ÀíADC²ÉÑù
* @param ÎÞ
* @retval ÎÞ
*/
void process_adc_sample(void)
{
rtc_time_t current_time;
get_current_time(¤t_time);
/* ¶ÁÈ¡ADCÖµ²¢×ª»»Îªµçѹ */
// uint16_t adc_value = adc_get_result_average(ADC_ADCX_CHY, 20);
// float voltage = (float)adc_value * (3.3 / 4096) * sys_config.ratio;
//
// /* OLEDÏÔʾ - Ö»¸üеçѹ²¿·Ö */
// char volt_str[16];
// sprintf(volt_str, "%.2fV", voltage);
//
// oled_show_string(0, 16, volt_str, 12);
// oled_refresh_gram();
/* ´®¿ÚÊä³ö */
printf("20%02d-%02d-%02d %02d:%02d:%02d ch0 = %.2fV",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second,
oled_voltage);
/* ³¬ÏÞ¼ì²â */
uint8_t overlimit = 0;
if (oled_voltage > sys_config.limit/10) {
LED2(1);
overlimit = 1;
printf(" OverLimit(%.2f)!", sys_config.limit);
/* ´æ´¢³¬ÏÞÊý¾Ý */
store_overlimit_data(oled_voltage);
}
else if(oled_voltage <= sys_config.limit/10)
{
LED2(0);
}
printf("\r\n");
/* ´æ´¢²ÉÑùÊý¾Ý */
store_sample_data(oled_voltage, overlimit);
/* ´æ´¢¼ÓÃÜÊý¾Ý */
if (encrypt_mode) {
uint32_t unix_time = datetime_to_unix(¤t_time);
store_hide_data(unix_time, oled_voltage);
}
/* Òþ²ØÄ£Ê½Êä³ö */
if (hide_output_mode) {
/* ת»»ÎªUnixʱ¼ä´Á */
uint32_t unix_time = datetime_to_unix(¤t_time);
/* µçѹֵ·Ö½â */
uint16_t integer_part = (uint16_t)oled_voltage;
uint16_t fractional_part = (uint16_t)((oled_voltage - integer_part) * 65536);
/* Éú³ÉÒþ²Ø¸ñʽ×Ö·û´® */
char hide_str[20];
sprintf(hide_str, "%08X%04X%04X", unix_time, integer_part, fractional_part);
/* Ìí¼Ó³¬ÏÞ±ê¼Ç */
if (overlimit) {
printf("%s*\r\n", hide_str);
} else {
printf("%s\r\n", hide_str);
}
}
}
/**
* @brief ´æ´¢²ÉÑùÊý¾Ý
* @param voltage: µçѹֵ
* @param overlimit: ÊÇ·ñ³¬ÏÞ
* @retval ÎÞ
*/
void store_sample_data(float voltage, uint8_t overlimit)
{
/* ÿ10ÌõÊý¾Ý´´½¨ÐÂÎļþ */
if (sample_count == 0 || sample_count >= 10) {
if (sample_file_open) {
f_close(&sample_file);
sample_file_open = 0;
}
rtc_time_t current_time;
get_current_time(¤t_time);
sprintf(current_filename, "sample/sampleData20%02d%02d%02d%02d%02d%02d.txt",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second);
f_mkdir("sample");
if (f_open(&sample_file, current_filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) {
sample_file_open = 1;
}
sample_count = 0;
}
/* дÈëÊý¾Ý */
rtc_time_t current_time;
get_current_time(¤t_time);
char data_line[64];
sprintf(data_line, "20%02d-%02d-%02d %02d:%02d:%02d,%.2f,%d\r\n",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second,
voltage, overlimit);
UINT bw;
if (sample_file_open) {
f_write(&sample_file, data_line, strlen(data_line), &bw);
f_sync(&sample_file);
}
sample_count++;
}
/**
* @brief ´æ´¢³¬ÏÞÊý¾Ý
* @param voltage: µçѹֵ
* @retval ÎÞ
*/
void store_overlimit_data(float voltage)
{
/* ÿ10ÌõÊý¾Ý´´½¨ÐÂÎļþ */
static uint8_t overlimit_count = 0;
if (overlimit_count == 0 || overlimit_count >= 10) {
if (overlimit_file_open) {
f_close(&overlimit_file);
overlimit_file_open = 0;
}
rtc_time_t current_time;
get_current_time(¤t_time);
sprintf(current_filename, "overLimit/overLimit%04d%02d%02d%02d%02d%02d.txt",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second);
f_mkdir("overLimit");
if (f_open(&overlimit_file, current_filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) {
overlimit_file_open = 1;
}
overlimit_count = 0;
}
/* дÈëÊý¾Ý */
rtc_time_t current_time;
get_current_time(¤t_time);
char data_line[64];
sprintf(data_line, "20%02d-%02d-%02d %02d:%02d:%02d,%.2f\r\n",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second,
voltage);
UINT bw;
if (overlimit_file_open) {
f_write(&overlimit_file, data_line, strlen(data_line), &bw);
f_sync(&overlimit_file);
}
overlimit_count++;
}
/**
* @brief ´æ´¢ÈÕÖ¾ÌõÄ¿
* @param action: ²Ù×÷ÃèÊö
* @retval ÎÞ
*/
void store_log_entry(const char *action)
{
static uint8_t log_initialized = 0;
/* Éϵçʱ´´½¨ÐÂÈÕÖ¾Îļþ */
if (!log_initialized) {
sprintf(current_filename, "log/log%lu.txt", sys_config.log_file_id);
f_mkdir("log");
if (f_open(&log_file, current_filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) {
log_file_open = 1;
log_initialized = 1;
}
/* дÈë³õʼÐÅÏ¢ */
if (log_file_open) {
rtc_time_t current_time;
get_current_time(¤t_time);
char header[128];
sprintf(header, "System started at 20%02d-%02d-%02d %02d:%02d:%02d\r\n",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second);
UINT bw;
f_write(&log_file, header, strlen(header), &bw);
f_sync(&log_file);
}
}
/* дÈëÈÕÖ¾ÌõÄ¿ */
if (log_file_open) {
rtc_time_t current_time;
get_current_time(¤t_time);
char log_entry[128];
sprintf(log_entry, "[20%02d-%02d-%02d %02d:%02d:%02d] %s\r\n",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second,
action);
UINT bw;
f_write(&log_file, log_entry, strlen(log_entry), &bw);
f_sync(&log_file);
}
}
/**
* @brief ´æ´¢¼ÓÃÜÊý¾Ý
* @param timestamp: Unixʱ¼ä´Á
* @param voltage: µçѹֵ
* @retval ÎÞ
*/
void store_hide_data(uint32_t timestamp, float voltage)
{
/* ÿ10ÌõÊý¾Ý´´½¨ÐÂÎļþ */
static uint8_t hide_count = 0;
if (hide_count == 0 || hide_count >= 10) {
if (hide_file_open) {
f_close(&hide_file);
hide_file_open = 0;
}
rtc_time_t current_time;
get_current_time(¤t_time);
sprintf(current_filename, "hideData/hideData%04d%02d%02d%02d%02d%02d.txt",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second);
f_mkdir("hideData");
if (f_open(&hide_file, current_filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) {
hide_file_open = 1;
}
hide_count = 0;
}
/* ±àÂëµçѹֵ */
uint8_t voltage_buf[8];
encode_voltage(voltage, voltage_buf);
/* дÈëÊý¾Ý */
char data_line[32];
sprintf(data_line, "%08X", timestamp);
for (int i = 0; i < 8; i++) {
sprintf(data_line + 8 + i*2, "%02X", voltage_buf[i]);
}
strcat(data_line, "\r\n");
UINT bw;
if (hide_file_open) {
f_write(&hide_file, data_line, strlen(data_line), &bw);
f_sync(&hide_file);
}
hide_count++;
}
/**
* @brief ÈÕÆÚʱ¼äתUnixʱ¼ä´Á
* @param time: ÈÕÆÚʱ¼ä½á¹¹Ìå
* @retval Unixʱ¼ä´Á
*/
uint32_t datetime_to_unix(rtc_time_t *time)
{
struct tm t;
t.tm_year = 2000 + time->year - 1900;
t.tm_mon = time->month - 1;
t.tm_mday = time->day;
t.tm_hour = time->hour;
t.tm_min = time->minute;
t.tm_sec = time->second;
t.tm_isdst = -1;
return mktime(&t);
}
/**
* @brief ±àÂëµçѹֵ
* @param voltage: µçѹֵ
* @param buffer: Êä³ö»º³åÇø(8×Ö½Ú)
* @retval ÎÞ
*/
void encode_voltage(float voltage, uint8_t *buffer)
{
uint16_t integer_part = (uint16_t)voltage;
uint16_t fractional_part = (uint16_t)((voltage - integer_part) * 65536);
buffer[0] = (integer_part >> 8) & 0xFF;
buffer[1] = integer_part & 0xFF;
buffer[2] = (fractional_part >> 8) & 0xFF;
buffer[3] = fractional_part & 0xFF;
/* ͬʱ´æ´¢ÔʼÊý¾ÝÓÃÓÚУÑé */
uint32_t raw = *(uint32_t*)&voltage;
buffer[4] = (raw >> 24) & 0xFF;
buffer[5] = (raw >> 16) & 0xFF;
buffer[6] = (raw >> 8) & 0xFF;
buffer[7] = raw & 0xFF;
}
/**
* @brief OLED״̬ÏÔʾ
* @param ÎÞ
* @retval ÎÞ
*/
void oled_display_status(void)
{
if (sampling_enabled) {
rtc_time_t current_time;
get_current_time(¤t_time);
char time_str[12], status[16];
sprintf(time_str, "%02d:%02d:%02d",
current_time.hour, current_time.minute, current_time.second);
sprintf(status, "CYC:%ds", sys_config.sample_cycle);
oled_clear();
oled_show_string(0, 0, time_str, 12);
oled_show_string(0, 16, status, 12);
oled_refresh_gram();
} else {
oled_clear();
oled_show_string(0, 0, "system idle", 12);
oled_refresh_gram();
}
}
/* Ìí¼ÓÈ«¾Ö±äÁ¿ */
extern volatile uint8_t timer6_sample_flag;
extern volatile uint8_t timer6_led_flag;
int main(void)
{
/* Ó²¼þ³õʼ»¯ */
delay_init(240);
usart_init(115200);
led_init();
key_init();
oled_init();
adc_init();
norflash_init();
rtc_config(); // ÐÞ¸ÄΪµ÷ÓÃrtc_config
/* ³õʼ»¯¶¨Ê±Æ÷6 - 1msÖÐ¶Ï */
timerx_int_init(1000-1, 120-1); // 240MHz/(239+1)=1MHz, (999+1)/1MHz=1ms
/* ¹ÒÔØÎļþϵͳ */
FATFS fs;
f_mount(&fs, "0:", 1);
/* ´ÓFlash¼ÓÔØÅäÖÃ */
read_config_from_flash();
printf("=====system init=====\r\n");
printf("Device_ID:2025-CIMC\r\n");
printf("=====system ready=====\r\n");
/* ³õʼ»¯ÈÕÖ¾ */
sys_config.log_file_id++; // ÿ´ÎÉϵçµÝÔö
save_config_to_flash(); // ±£´æÐµÄÎļþID
store_log_entry("System started");
/* ³õʼOLEDÏÔʾ */
oled_display_status();
float last_voltage = 0.0; // ±£´æÉÏÒ»´Î²ÉÑùµÄµçѹֵ
/* Ö÷Ñ»· */
uint8_t key;
while (1) {
/* °´¼ü´¦Àí */
key = key_scan(0);
switch (key) {
case KEY1_PRES: // ²ÉÑùÆôÍ£
if (sampling_enabled) stop_sampling();
else start_sampling();
break;
case KEY2_PRES: // ÖÜÆÚ5s
adjust_sample_cycle(5);
break;
case KEY3_PRES: // ÖÜÆÚ10s
adjust_sample_cycle(10);
break;
case KEY4_PRES: // ÖÜÆÚ15s
adjust_sample_cycle(15);
break;
case WKUP_PRES: // ¼ÓÃÜģʽÇл»
encrypt_mode = !encrypt_mode;
store_log_entry(encrypt_mode ? "Encrypt enabled" : "Encrypt disabled");
break;
}
/* ´®¿ÚÃüÁî´¦Àí */
if (g_usart_rx_sta & 0x8000) {
uint16_t len = g_usart_rx_sta & 0x3fff;
g_usart_rx_buf[len] = '\0';
g_usart_rx_sta = 0;
char *cmd = (char*)g_usart_rx_buf;
if (strcmp(cmd, "test") == 0) {
system_self_test();
}
else if (strncmp(cmd, "RTC Config", 10) == 0) {
set_rtc_time(cmd + 11);
}
else if (strcmp(cmd, "RTC now") == 0) {
rtc_time_t current_time;
get_current_time(¤t_time);
printf("Current Time:20%02d-%02d-%02d %02d:%02d:%02d\r\n",
current_time.year, current_time.month, current_time.day,
current_time.hour, current_time.minute, current_time.second);
}
else if (strcmp(cmd, "conf") == 0) {
read_config_file();
}
else if (strcmp(cmd, "ratio") == 0) {
set_ratio();
}
else if (strcmp(cmd, "limit") == 0) {
set_limit();
}
else if (strcmp(cmd, "config save") == 0) {
save_config_to_flash();
}
else if (strcmp(cmd, "config read") == 0) {
read_config_from_flash();
}
else if (strcmp(cmd, "start") == 0) {
start_sampling();
}
else if (strcmp(cmd, "stop") == 0) {
stop_sampling();
}
else if (strcmp(cmd, "hide") == 0) {
hide_output_mode = 1;
printf("Hide output mode enabled\r\n");
}
else if (strcmp(cmd, "unhide") == 0) {
hide_output_mode = 0;
printf("Hide output mode disabled\r\n");
}
else if (strcmp(cmd, "encrypt") == 0) { // ÐÞ¸ÄÃüÁîÃû±ÜÃâ³åÍ»
encrypt_mode = !encrypt_mode;
printf("Encrypt mode %s\r\n", encrypt_mode ? "enabled" : "disabled");
store_log_entry(encrypt_mode ? "Encrypt enabled" : "Encrypt disabled");
}
}
/* LEDÉÁ˸´¦Àí */
if (timer6_led_flag && sampling_enabled) {
timer6_led_flag = 0;
led_blink_state = !led_blink_state;
LED1(led_blink_state);
}
/* ʱ¼ä¸üд¦Àí */
if (timer6_time_update_flag) {
timer6_time_update_flag = 0;
if (sampling_enabled) {
update_oled_time(); // ÿÃë¸üÐÂʱ¼äÏÔʾ
}
}
/* ²ÉÑù´¦Àí */
if (timer6_sample_flag && sampling_enabled) {
timer6_sample_flag = 0;
process_adc_sample();
}
// /* ²ÉÑù¶¨Ê± */
// if (sampling_enabled) {
// uint32_t current_time = get_system_time();
// if (current_time - last_sample_time >= sys_config.sample_cycle * 1000) {
// last_sample_time = current_time;
// process_adc_sample();
//
// /* LEDÉÁ˸¿ØÖÆ */
// led_blink_state = !led_blink_state;
// LED1(led_blink_state);
// }
// }
delay_ms(1);
}
}修改代码
最新发布