From 286ff98b8ec180cdc39ebe9136d30131e51e1bce Mon Sep 17 00:00:00 2001 From: guishenking Date: Fri, 20 Mar 2026 21:09:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lhl_flash.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++ lhl_lowpower.h | 22 +++++ lhl_systemclock.h | 31 +++++++ lhl_watchdog.h | 10 +++ main.c | 26 ++++++ 5 files changed, 306 insertions(+) create mode 100644 lhl_flash.c create mode 100644 lhl_lowpower.h create mode 100644 lhl_systemclock.h create mode 100644 lhl_watchdog.h create mode 100644 main.c diff --git a/lhl_flash.c b/lhl_flash.c new file mode 100644 index 0000000..eea00ff --- /dev/null +++ b/lhl_flash.c @@ -0,0 +1,217 @@ +#include "../main/SystemInclude.h" + +/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +USER_PARAMS_ADDR 参数数据保存区,对应EEPROM的 0x10-0x6C0 区间 +参数页说明:将 u16 MBReg[336]; u16 WordReg[128]; u32 DWordReg[64]; + 总共 1712bytes 依次连续存储到USER_PARAMS_ADDR为起始地址的页; + +CORRECT_DATA_ADDR 默认校准页保存区,对应EEPROM的 0x1000-及以后按照内码量设计的区间 + += = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/ +//写参数数据保存区-临时缓冲区 +u8 param_buffer[TOTAL_PARAM_SIZE] __attribute__((aligned(4))); //4字节对齐 + +void update_param_bufferFromFlash(void)// +{ + memcpy(param_buffer, (void*)USER_PARAMS_ADDR, TOTAL_PARAM_SIZE); +} + +//写参数数据保存区-将临时缓冲区param_buffer数据存入flash ------------------ +static void WriteAllParamToFlash(void) +{ + //擦除 Flash 页(USER_PARAMS_ADDR 是页起始) + if(LHL_FLASH_Erase(USER_PARAMS_ADDR, USER_PARAMS_ADDR, LHL_LNG_TIMEOUT) != LHL_OK) + { + while(1); + } + //按 32-bit word 写入 必须 4-byte 对齐 + u16 word_count = (TOTAL_PARAM_SIZE + 3)>>2; // 向上取整 转换为32位数据的个数 + + LHL_FLASH_Program( USER_PARAMS_ADDR, (uint32_t*)param_buffer, word_count, LHL_LNG_TIMEOUT ); +} + + +//写参数数据保存区-双字节保存区 +u16 WriteShortParameterToFlash(u16 parameterAdr) +{ + //访问双字节数据保存区------------------------------------------------------------------ +// if((parameterAdr >=REG_MEM_ADDR_START) && (parameterAdr < REG_INT_DWORD_MEM_ADDR_START)) +// {} + u8 *p = param_buffer; + + tempL.Byte[2] = CRC8(tempL.Byte, 2);//计算新值校验码 + + p += parameterAdr; + //更新变量 + p[0] = tempL.Byte[0]; + p[1] = tempL.Byte[1]; + p[2] = tempL.Byte[2]; + + //写param_buffer到Flash + WriteAllParamToFlash(); + + tempL.Word[0] = ReadShortParameterFromFlash(parameterAdr,WordDefault[ADR_WORD_IDX(parameterAdr)][DEFAULT]); + tempL.Byte[2] = 0; + // 注意:此时不用更新 WordReg[index] + // 因为上层会用返回值来更新:*WRSource = 返回值; + return tempL.Word[0]; //上层会用此值更新 WordReg[I] +} + + +//写参数数据保存区-四字节保存区 +u32 WriteLongParameterToFlash(u16 parameterAdr) +{ +// if( (parameterAdr >=REG_INT_DWORD_MEM_ADDR_START)&& parameterAdr <= REG_INT_DWORD_MEM_ADDR_END) +// { } + tempDev.Byte[4] = CRC8(tempDev.Byte, 4);//计算新值校验码 + + //更新变量 + u8 *p = param_buffer; + p += (parameterAdr ); + p[0] = tempDev.Byte[0]; + p[1] = tempDev.Byte[1]; + p[2] = tempDev.Byte[2]; + p[3] = tempDev.Byte[3]; + p[4] = tempDev.Byte[4]; + + //写param_buffer到Flash + WriteAllParamToFlash(); + + tempDev.DWord[0] = ReadLongParameterFromFlash(parameterAdr,WordDefault[ADR_DWORD_IDX(parameterAdr)][DEFAULT]); + tempDev.Byte[4] = 0; + + return tempDev.DWord[0]; +} + + + +//写校准页保存区 ,二次修正保存区 ,不定长参数数据保存区--------------------------------------------------- +void WriteMultiByteToFlash(u16 address, u8 *wrtData, u16 dataLenth, u8 flashAdr) +{ + (void)flashAdr; // 没有多个Flash + //默认校准曲线--------------------------------------------------------------- + if(address >= CALI_DATA1_ADDR)//要写入的地址为原eeprom的校准区 + { + //0.转换成Flash地址 + u32 ADDR = (u32)(address - CALI_DATA1_ADDR); + ADDR = ADDR + CORRECT_DATA_ADDR; + //判断是否新一页,擦除新页准备写入 + if((ADDR&0x0FFF) == 0x000) LHL_FLASH_Erase(ADDR,ADDR,LHL_LNG_TIMEOUT);//ADDR跨页即ADDR为页首地址 + if(ADDR >(CORRECT_DATA_ADDR+ CALIB_STORED_SIZE) ) MBBuf.BusError = SLAVE_DEVICE_FAILURE;//溢出 + //写校准进入Flash + LHL_FLASH_Program(ADDR,(u32 *)wrtData,dataLenth>>2 ,LHL_LNG_TIMEOUT); + } + //校准曲线2--------------------------------------------------------------- + //CALI_DATA2_ADDR CORRECT_DATA2_ADDR CALIB_STORED_SIZE2 + //校准曲线3--------------------------------------------------------------- + //CALI_DATA3_ADDR CORRECT_DATA3_ADDR CALIB_STORED_SIZE3 + //二次修正区--------------------------------------------------------------- +// else if() +// { +// USER_DCOEF_TAG_ADDR +// } + //写入多个到参数数据保存区------------------------------------------------------------------ + else if((address >=REG_MEMORY_ADDR) && (address <= REG_INT_DWORD_MEM_ADDR_END)) + { + + + + + wrtData[dataLenth] = CRC8(wrtData, dataLenth);//计算新值校验码 + //更新变量 + u8 *p = param_buffer; + p += address; + /*for(u8 i = 0 ; i < dataLenth+1 ; i ++) + { + p[i] = wrtData[i]; + }*/ + //每两个字节交换 + for (int i = 0; i < dataLenth; i += 2) { + p[i] = wrtData[i + 1]; //低地址 + p[i + 1] = wrtData[i]; //高地址 + } + p[dataLenth]= wrtData[dataLenth];//CRC直接复制 + + WriteAllParamToFlash(); + } + + +} + + + + + + + + + + + +//读双字节数据保存区------------------------------------------------------------------ +u16 ReadShortParameterFromFlash(u16 parameterAdr , u16 parameterDefault) +{ +// if(parameterAdr >=REG_MEM_ADDR_START && parameterAdr < REG_INT_DWORD_MEM_ADDR_START) +// { } + u32 ADDR = ((u32)parameterAdr + USER_PARAMS_ADDR);// 将EEPROM 参数地址(如 MEM_ADDR_REG_0X30 = 0x10)转为 Flash 物理地址 + + tempL.Word[0] = 0; + memcpy(tempL.Byte,(const void*)ADDR, 3); + + if(tempL.Byte[2] != CRC8(tempL.Byte, 2)) + { + tempL.Word[0] = (u32)parameterDefault; + isReadParameterOK = 0; + } + else + { + tempL.Byte[2] = 0; + isReadParameterOK = 1; + } + + return tempL.Word[0]; + +} +//读四字节数据保存区------------------------------------------------------------------ +u32 ReadLongParameterFromFlash(u16 parameterAdr , u16 parameterDefault) +{ +// if( (parameterAdr >=REG_INT_DWORD_MEM_ADDR_START)&& parameterAdr <= REG_INT_DWORD_MEM_ADDR_END) +// { } + u32 ADDR = (u32)(parameterAdr + USER_PARAMS_ADDR); + tempDev.DWord[0] = 0; + memcpy(tempDev.Byte,(const void*)ADDR, 5); + + if(tempDev.Byte[4] != CRC8(tempDev.Byte, 4)) + { + tempDev.DWord[0] = (u32)parameterDefault; + isReadParameterOK = 0; + } + else + { + isReadParameterOK = 1; + } + return tempDev.DWord[0]; + +} + +//读数据保存区,校准数据保存区------------------------------------------------------------------ +void ReadMultiByteFromFlash(u16 address,u8 *wrtData, u16 dataLenth, u8 flashAdr) +{ + (void)flashAdr; // 没有多个Flash,避免编译器 warning + u32 ADDR; + //读校准数据保存区-------------------------------------------------------- + //由于校准数据地址基准为eeprom的地址,而所有的校准都在该地址后,因此只需要判断这一个即可 + if(address >=CALI_DATA1_ADDR) + { + ADDR =(u32)(address-CALI_DATA1_ADDR ); + ADDR += CORRECT_DATA_ADDR; //转换为Flash地址 + memcpy(wrtData,(const void*)ADDR, dataLenth); + } + //读数据保存区---------------------------------------------------------- + else if((address >=REG_MEMORY_ADDR) && (address <= REG_INT_DWORD_MEM_ADDR_END)) + { + ADDR =((u32)address + USER_PARAMS_ADDR); + memcpy(wrtData,(const void*)ADDR, dataLenth); //不定长参数的校验位是存了的,若判断但是默认值=?未判断 + } +} diff --git a/lhl_lowpower.h b/lhl_lowpower.h new file mode 100644 index 0000000..335b70a --- /dev/null +++ b/lhl_lowpower.h @@ -0,0 +1,22 @@ +#ifndef __LOWPOWER_H__ +#define __LOWPOWER_H__ + +/*================================================*/ +void EnterLowPowerModeWFI(PWR_POWERMODE_t mode); + + +/*================================================*/ +typedef struct{ + PWR_POWERMODE_t lpm_mode; + u8 mcuModeSleeping ; +}__LPM_STA_TypeDef; + +extern __LPM_STA_TypeDef lpmState; + +void LowPowerModeProcess(void); +void SetupLowPowertoWakeupByHandwareTrigger(void); +void ExitLowPowerModeRecoverySysState(void); + + +#endif + diff --git a/lhl_systemclock.h b/lhl_systemclock.h new file mode 100644 index 0000000..49c4112 --- /dev/null +++ b/lhl_systemclock.h @@ -0,0 +1,31 @@ +#ifndef __SYSTEMCLOCK_H_ +#define __SYSTEMCLOCK_H_ + + +typedef enum { + clock_defaultconfig1,//SYSclock=16M AHBclock=16M APB1clock=16M APB2clock=16M + clock_defaultconfig2,//SYSclock=16M AHBclock=8M APB1clock=8M APB2clock=8M + clock_defaultconfig3,//SYSclock=16M AHBclock=8M APB1clock=4M APB2clock=4M + clock_defaultconfig4,//SYSclock=16M AHBclock=8M APB1clock=8M APB2clock=4M + clock_defaultconfig5,//SYSclock=16M AHBclock=8M APB1clock=4M APB2clock=8M + //......更多自定义配置 +}clock_defaultconfig_t; + + +//配置结构体 +typedef struct { + + uint8_t clock_config;//this pram value can be : clock_defaultconfig_t + +} systemclock_config_t; + + +void System_MCO_Config(void); +void SystemClockConfiguration(void); +void disable_interrupts(void); +void enable_interrupts(void); +void ResetSystem(void); + + +void Enable_LSE(void); +#endif \ No newline at end of file diff --git a/lhl_watchdog.h b/lhl_watchdog.h new file mode 100644 index 0000000..da408b9 --- /dev/null +++ b/lhl_watchdog.h @@ -0,0 +1,10 @@ +#ifndef __LHL_WATCHDOG_H__ +#define __LHL_WATCHDOG_H__ + +void SystemIWDGInit(void); +void Stop_WDT(void); +void Clear_WDT(void); + +#endif + + diff --git a/main.c b/main.c new file mode 100644 index 0000000..9d3a20c --- /dev/null +++ b/main.c @@ -0,0 +1,26 @@ +#include "../main/SystemInclude.h" +/****************************************************************************/ +int main(void) +{ + Stop_WDT(); /* 禁用独立看门狗(IWDG) */ + SystemClockConfiguration(); /* 系统时钟初始化 */ + SystemGPIOInit(); /* 初始化GPIO默认状态 */ + StartLPTimer2(327); + lptimer_register_irq_callback(LPTIM2, My_Timer2_Callback); + Key_Power_Init(); + + EnterMainEntry(); // 进入程序主入口 + /*----------用户系统初始化----------*/ + systmeState = 0x00; // 系统状态初始化 + SystemInitProcess(); // 硬件初始化 + + OLED_Init(); + LED_PIN_OUT(); + while(1) + { + SystemPolling(); //系统轮询 + } + return 0; +} + +