From 6c9cd5761a1a3bfef1dddea97e7892cea78113b4 Mon Sep 17 00:00:00 2001 From: aiden Date: Fri, 22 May 2026 15:15:10 +0800 Subject: [PATCH] feat: uart cmd to ctrl pec930 --- .../PFC_LLC_2026-05-20_2P2Z_ok/inc/app.h | 75 ++ .../PFC_LLC_2026-05-20_2P2Z_ok/inc/init.h | 2 - .../PFC_LLC_2026-05-20_2P2Z_ok/inc/isr.h | 45 +- .../PFC_LLC_2026-05-20_2P2Z_ok/inc/main.h | 163 ++-- .../PFC_LLC_2026-05-20_2P2Z_ok/src/app.c | 380 ++++++++ .../src/copy_main.c | 40 +- .../PFC_LLC_2026-05-20_2P2Z_ok/src/init.c | 403 ++++---- .../PFC_LLC_2026-05-20_2P2Z_ok/src/isr.c | 21 +- .../PFC_LLC_2026-05-20_2P2Z_ok/src/main.c | 919 ++++++++++-------- 9 files changed, 1279 insertions(+), 769 deletions(-) create mode 100644 pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/app.h create mode 100644 pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/app.c diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/app.h b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/app.h new file mode 100644 index 0000000..c60b674 --- /dev/null +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/app.h @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2026 Wisetop. All Rights Reserved. + */ + +#ifndef __APP_H__ +#define __APP_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "isr.h" +#include "main.h" + + //============================================================================= + // Constant Definition + //============================================================================= + + //============================================================================= + // Macro Definition + //============================================================================= +#define UART_RX_BUF_SIZE 64 +#define UART_SERIAL_BAUD 115200 +#define UART_RX_TIMEOUT_MS 100 + +/* flash*/ +#define FLASH_PROG_ADDR_END sizeof(EFLASH_MEM_Type) +#define FLASH_PROG_ADDR_USER_CALI (FLASH_PROG_ADDR_END - FLASH_1_PAGE_SIZE) // 0x8000-512 + + //============================================================================= + // Structure Definition + //============================================================================= + struct bode_plot_param_t + { + int32_t b0; + int32_t b1; + int32_t b2; + int32_t a1; + int32_t a2; + }; + //============================================================================= + // Global Data Definition + //============================================================================= + static volatile char g_rx_buf[UART_RX_BUF_SIZE]; + static volatile uint32_t g_rx_idx = 0; + static volatile uint32_t g_rx_len = 0; + static volatile int g_rx_ready = 0; + static volatile uint32_t g_rx_last_tick = 0; /* sys_tick when last byte arrived */ + //============================================================================= + // Private Function Definition + //============================================================================= + + //============================================================================= + // Public Function Definition + //============================================================================= + void app(void); + + /* uart and cmd*/ + void uart_init(void); + void uart_rx_handler(void); + int is_rx_frame_ready(void); + int uart_rx_getline(char *pBuf, uint32_t size); + void uart_cmd_parse(char *cmd_buf, uint32_t size); + + /* flash */ + void bode_plot_param_read_from_flash(struct bode_plot_param_t *param, uint32_t addr); + + extern struct bode_plot_param_t bode_plot_param; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/init.h b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/init.h index 0381214..72d300d 100644 --- a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/init.h +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/init.h @@ -22,8 +22,6 @@ void pfc_pwm_config(); // PFC //----------------------------------- void pwm_brake(); -void uart_config(); -void UART_Send_Wait(UART_Type *pHUart, uint16_t value); void tim0_config(); #endif /* INC_INIT_H_ */ diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/isr.h b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/isr.h index 89f3563..1e17a54 100644 --- a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/isr.h +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/isr.h @@ -14,36 +14,37 @@ #define __isr_H_wuraIpBA_lTJm_HvJw_sNDo_uEd5JnucTReY__ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #include "main.h" -//============================================================================= -// Constant Definition -//============================================================================= + //============================================================================= + // Constant Definition + //============================================================================= -//============================================================================= -// Macro Definition -//============================================================================= + //============================================================================= + // Macro Definition + //============================================================================= -//============================================================================= -// Structure Definition -//============================================================================= + //============================================================================= + // Structure Definition + //============================================================================= -//============================================================================= -// Global Data Definition -//============================================================================= + //============================================================================= + // Global Data Definition + //============================================================================= -//============================================================================= -// Private Function Definition -//============================================================================= + //============================================================================= + // Private Function Definition + //============================================================================= -//============================================================================= -// Public Function Definition -//============================================================================= -//void isr_tim2_handle(void); -//void isr_adc_handle(void); -//void isr_tim0_handle(void); + //============================================================================= + // Public Function Definition + //============================================================================= + // void isr_tim2_handle(void); + // void isr_adc_handle(void); + // void isr_tim0_handle(void); #ifdef __cplusplus } diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/main.h b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/main.h index 666ae12..9391fa2 100644 --- a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/main.h +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/inc/main.h @@ -14,10 +14,10 @@ #define __main_H_wxBnwdPw_lq7D_H4I5_sHPp_uXof15pFLp4V__ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif - #include "hal_device.h" #include "syslog.h" //============================================================================= @@ -26,104 +26,103 @@ extern "C" { //------------------------------------------------------------------------------ // PFC DUTY 參數 -#define PFC_PERIOD 600 // 600 = 100khz -#define PFC_DUTY_MAX 540 //(PFC_PERIOD * 0.9) // 600 * 0.85 = 510 -#define PFC_DUTY_MIN 12 //(PFC_PERIOD * 0.02) // 600 * 0.02 = 12 +#define PFC_PERIOD 600 // 600 = 100khz +#define PFC_DUTY_MAX 540 //(PFC_PERIOD * 0.9) // 600 * 0.85 = 510 +#define PFC_DUTY_MIN 12 //(PFC_PERIOD * 0.02) // 600 * 0.02 = 12 // VBUS 參數 -#define VBUS_SET 360 // unit: volt (Transformer N = 14) -#define VBUS_SET_H (VBUS_SET+20) // burst mode in, 在過零區判斷 -#define VBUS_SET_L (VBUS_SET-20) // burst mode out, 在過零區判斷 -//#define VBUS_SET_H2 370 // for skip mode -#define VBUS_OVP 410 // 420V 電容 -#define VBUS_2ADC 149.15f // 4M + 27K -#define VCOMP_2DUTY 0 // vbus_comp control duty -#define V_COMP_MAX 16000 // (PFC_DUTY_MAX * 32) // 480 * 32 = 16360 -#define V_COMP_MIN 300 // (PFC_DUTY_MAX * 32) // 12 * 32 = 384 -#define V_INT_GAIN_BIT 9 // 7=/128, 9=/512 大約除 120 ~ 500 之間 (粗調用bit, 細調用整數) -#define V_POR_GAIN_BIT 8 // 6=/64, 8=/256 大約除 60 ~ 250 之間 -#define VBUS_INT_MAX (V_COMP_MAX << V_INT_GAIN_BIT) -#define VBUS_POR_MAX (V_COMP_MAX << (V_POR_GAIN_BIT-1)) +#define VBUS_SET 360 // unit: volt (Transformer N = 14) +#define VBUS_SET_H (VBUS_SET + 20) // burst mode in, 在過零區判斷 +#define VBUS_SET_L (VBUS_SET - 20) // burst mode out, 在過零區判斷 +// #define VBUS_SET_H2 370 // for skip mode +#define VBUS_OVP 410 // 420V 電容 +#define VBUS_2ADC 149.15f // 4M + 27K +#define VCOMP_2DUTY 0 // vbus_comp control duty +#define V_COMP_MAX 16000 // (PFC_DUTY_MAX * 32) // 480 * 32 = 16360 +#define V_COMP_MIN 300 // (PFC_DUTY_MAX * 32) // 12 * 32 = 384 +#define V_INT_GAIN_BIT 9 // 7=/128, 9=/512 大約除 120 ~ 500 之間 (粗調用bit, 細調用整數) +#define V_POR_GAIN_BIT 8 // 6=/64, 8=/256 大約除 60 ~ 250 之間 +#define VBUS_INT_MAX (V_COMP_MAX << V_INT_GAIN_BIT) +#define VBUS_POR_MAX (V_COMP_MAX << (V_POR_GAIN_BIT - 1)) //--------------------------------------------------------------- -#define DIGI_COMP_BIT 10 -//#define DIGI_COMP_MAX (VBUS_SET_H * 4096 / VBUS_2ADC / 3.3) << 4 +#define DIGI_COMP_BIT 10 +// #define DIGI_COMP_MAX (VBUS_SET_H * 4096 / VBUS_2ADC / 3.3) << 4 //------------------------------------------------------------------ -// 武士 12V 變壓器 + 47nF 諧振頻率 ~ 75KHZ -// 實測值 106uH + 47nF = 73KHZ --> PERIOD = 820 ~ 830 -// 高正 40uH + 68nF ~ 95KHZ -#define LLC_PERIOD_SS 400 // 600 = 100khz (EPWM initial use) -#define DEAD_TIME 500 // ns -#define DEAD_TIME_VALUE (DEAD_TIME * 0.06) // double +// 武士 12V 變壓器 + 47nF 諧振頻率 ~ 75KHZ +// 實測值 106uH + 47nF = 73KHZ --> PERIOD = 820 ~ 830 +// 高正 40uH + 68nF ~ 95KHZ +#define LLC_PERIOD_SS 400 // 600 = 100khz (EPWM initial use) +#define DEAD_TIME 500 // ns +#define DEAD_TIME_VALUE (DEAD_TIME * 0.06) // double // LLC free run, 改控 vbus_set -#define LLC_PERIOD_MIN 400 // MIN, 400 = 150KHZ (>760不會振) -#define LLC_PERIOD_MAX 820 // MAX, 800 = 75KHZ // 可調範圍太大會共振 -#define LLC_COMP_GAIN_BIT 10 // 要慢才不會振 -#define LLC_COMP_MAX ((LLC_PERIOD_MAX-LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT) +#define LLC_PERIOD_MIN 400 // MIN, 400 = 150KHZ (>760不會振) +#define LLC_PERIOD_MAX 820 // MAX, 800 = 75KHZ // 可調範圍太大會共振 +#define LLC_COMP_GAIN_BIT 10 // 要慢才不會振 +#define LLC_COMP_MAX ((LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT) // LLC Soft Start 掃頻 2倍 ~ 1倍 = 150KHZ ~ 73KHZ -#define LLC_SS_MIN (LLC_PERIOD_MIN << 2) // 精度不夠,放大 4 倍, 1600 -#define LLC_SS_MAX (LLC_PERIOD_MAX << 2) // 精度不夠,放大 4 倍, 3280 -#define LLC_SS_COUNT (LLC_SS_MAX - LLC_SS_MIN) // 3280 - 1600 = 1680 * 10us = 16.8ms +#define LLC_SS_MIN (LLC_PERIOD_MIN << 2) // 精度不夠,放大 4 倍, 1600 +#define LLC_SS_MAX (LLC_PERIOD_MAX << 2) // 精度不夠,放大 4 倍, 3280 +#define LLC_SS_COUNT (LLC_SS_MAX - LLC_SS_MIN) // 3280 - 1600 = 1680 * 10us = 16.8ms // TIM0 參數 = ADC 取樣頻率 -#define TIM0_PERIOD 600 // 60M / 600 = 100KHZ +#define TIM0_PERIOD 600 // 60M / 600 = 100KHZ // IAC 參數 -#define I_COMP_MAX 16000 // = V_COMP_MAX * 1.414 -#define I_INT_GAIN_BIT 2 -//#define I_POR_GAIN_BIT 6 -#define I_INT_MAX (I_COMP_MAX << 3) -#define I_POR_MAX (I_INT_MAX) // 減半,影響 50% +#define I_COMP_MAX 16000 // = V_COMP_MAX * 1.414 +#define I_INT_GAIN_BIT 2 +// #define I_POR_GAIN_BIT 6 +#define I_INT_MAX (I_COMP_MAX << 3) +#define I_POR_MAX (I_INT_MAX) // 減半,影響 50% -//#define VAC_BROWN_IN 1113 // 約 95V (你原本的邏輯) -//#define VAC_BROWN_OUT 930 // 約 80V (根據你的比例計算) -#define VAC_ZERO 400 -#define VAC_ZERO_RISE 600 -#define BROWNOUT_DELAY 500 // 延遲計數,避免瞬時雜訊觸發 -#define VOLT_BROWN_IN 900 // 78V = 912 -#define VOLT_BROWN_OUT 855 // 73V = 855 +// #define VAC_BROWN_IN 1113 // 約 95V (你原本的邏輯) +// #define VAC_BROWN_OUT 930 // 約 80V (根據你的比例計算) +#define VAC_ZERO 400 +#define VAC_ZERO_RISE 600 +#define BROWNOUT_DELAY 500 // 延遲計數,避免瞬時雜訊觸發 +#define VOLT_BROWN_IN 900 // 78V = 912 +#define VOLT_BROWN_OUT 855 // 73V = 855 // VAC 110V = 1260 // VAC 220V = 2483 // 定義控制參數 -#define STEP_FAST 16 // 遠離目標時的步長 -#define STEP_SLOW 1 // 接近目標時的步長 -#define STABLE_THRES 5 // 狀態翻轉幾次後判定為進入穩態 +#define STEP_FAST 16 // 遠離目標時的步長 +#define STEP_SLOW 1 // 接近目標時的步長 +#define STABLE_THRES 5 // 狀態翻轉幾次後判定為進入穩態 -#define CURR_OFFSET 3840 // 零點電流 = 3820 ~ 3860 +#define CURR_OFFSET 3840 // 零點電流 = 3820 ~ 3860 + //============================================================================= + // Macro Definition + //============================================================================= -//============================================================================= -// Macro Definition -//============================================================================= + //============================================================================= + // Structure Definition + //============================================================================= -//============================================================================= -// Structure Definition -//============================================================================= + //============================================================================= + // Global Data Definition + //============================================================================= -//============================================================================= -// Global Data Definition -//============================================================================= + //============================================================================= + // Private Function Definition + //============================================================================= -//============================================================================= -// Private Function Definition -//============================================================================= + //============================================================================= + // Public Function Definition + //============================================================================= + void Power_On(); + void Power_Off(); + void Key1_Scan(); + void Key_Action(); + void Vol_Loop_PFC(); + void llc_set_period(uint16_t val); + void llc_pwm_enable(); + void llc_pwm_disable(); + void pfc_set_duty(uint16_t val); + void pfc_pwm_enable(); + void pfc_pwm_disable(); + void A_Pata_Reset(); + void Vol_Loop_LLC(void); + void Cur_Loop_PFC(void); -//============================================================================= -// Public Function Definition -//============================================================================= -void Power_On(); -void Power_Off(); -void Key1_Scan(); -void Key_Action(); -void Vol_Loop_PFC(); -void llc_set_period(uint16_t val); -void llc_pwm_enable(); -void llc_pwm_disable(); -void pfc_set_duty(uint16_t val); -void pfc_pwm_enable(); -void pfc_pwm_disable(); -void A_Pata_Reset(); -void Vol_Loop_LLC(void); -void Cur_Loop_PFC(void); - -void isr_adc_handle(void); -void isr_tim0_handle(void); + void isr_adc_handle(void); + void isr_tim0_handle(void); #ifdef __cplusplus } diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/app.c b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/app.c new file mode 100644 index 0000000..b0aa8bb --- /dev/null +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/app.c @@ -0,0 +1,380 @@ +/** + * Copyright (c) 2026 Wisetop. All Rights Reserved. + */ +#include "app.h" + +#include +#include + +#define TICK_1000_MS 1000 + +struct bode_plot_param_t bode_plot_param; + +static int bode_plot_param_write_to_flash(const struct bode_plot_param_t *param, uint32_t addr); + +/* sys clock*/ +static void sysclk_systick_init(SYSCFG_ClkSrcTypeDef clk_src, uint32_t sys_tick_ms) +{ + SYSCFG_ClkInitTypeDef SysClkInit = { 0 }; + + SysClkInit.ClkSource = clk_src; + SYSCFG_SysClkConfig(&SysClkInit); + + sys_config_systick(sys_tick_ms); +} + +static void sys_disable_ice(void) +{ + /* Disable ICE I/O for free run mode to use UART */ + sys_delay(5000); + SYSCFG_SetICEPin2NormalIO(true); +} + +/* uart*/ +void uart_init(void) +{ + GPIO_InitTypeDef gpio_init = { 0 }; + UART_InitTypeDef uart_init = { 0 }; + sys_irq_attr_t irq_attr = { + .trig_mode = SYS_IRQ_TRIGGER_LEVEL, + }; + + /* UART Tx: PB3 AF1 */ + gpio_init.GPIO_Pin = GPIO_Pin_03; + gpio_init.GPIO_AF_Mode = GPIO_AF_1; + gpio_init.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOB, &gpio_init); + + /* UART Rx: PB5 AF1 */ + gpio_init.GPIO_Pin = GPIO_Pin_05; + gpio_init.GPIO_AF_Mode = GPIO_AF_1; + GPIO_Init(GPIOB, &gpio_init); + + uart_init.BaudRate = UART_SERIAL_BAUD; + uart_init.WordLength = UART_WordLength_8b; + uart_init.StopBits = UART_StopBits_1; + uart_init.Parity = UART_Parity_No; + uart_init.Mode = UART_Mode_TxRx; + UART_Init(UART0, &uart_init); + + // clear RX FIFO and state + UART_ResetRxFIFO(UART0); + g_rx_idx = 0; + g_rx_len = 0; + g_rx_ready = 0; + + UART_ITConfig(UART0, UART_IE_RXNEE_Msk, ENABLE); + sys_register_IRQ(UART0_IRQn, uart_rx_handler, &irq_attr); + sys_enable_girq(); + + UART_Start(UART0); + return; +} + +int uart_rx_getline(char *pBuf, uint32_t size) +{ + if (!pBuf || size == 0 || !g_rx_ready) + return 0; + + uint32_t len = (g_rx_len < size - 1) ? g_rx_len : (size - 1); + for (uint32_t i = 0; i < len; i++) + pBuf[i] = g_rx_buf[i]; + pBuf[len] = '\0'; + + g_rx_len = 0; + g_rx_ready = 0; + g_rx_idx = 0; + return 1; +} + +int is_rx_frame_ready(void) +{ + return g_rx_ready; +} + +uint32_t __FASTCODE fastcode_proc(void) +{ + log_color(SLOG_CYAN, "run at fast area: $pc= x%08X\n", (uint32_t)&fastcode_proc); + return 0; +} + +__INTERRUPT void uart_rx_handler(void) +{ + SAVE_IRQ_CSR_CONTEXT(); + + while (UART_GetITStatus(UART0, UART_IE_RXNEE_Msk)) + { + uint8_t ch = (uint8_t)UART_ReceiveData(UART0); + g_rx_last_tick = sys_get_tick(); // record time of last received byte + + if (g_rx_ready) continue; // not ready to receive new frame, discard incoming data + + if (ch == '\r' || ch == '\n') + { + if (g_rx_idx > 0) + { + g_rx_buf[g_rx_idx] = '\0'; + g_rx_len = g_rx_idx; + g_rx_idx = 0; + g_rx_ready = 1; + } + } + else if (g_rx_idx < (UART_RX_BUF_SIZE - 1)) + { + g_rx_buf[g_rx_idx++] = (char)ch; + } + else + { + g_rx_idx = 0; // overflow, reset buffer index and discard data + } + } + + RESTORE_IRQ_CSR_CONTEXT(); +} + +/* cmd*/ +static bool cmd_match_with_arg(const volatile char *buf, const char *prefix, const char **arg_out) +{ + size_t len = strlen(prefix); + + if (strncmp((const char *)buf, prefix, len) != 0) + return false; + + *arg_out = (const char *)&buf[len]; + return true; +} + +static void cmd_trim_eol(char *buf) +{ + size_t len = strlen(buf); + + while (len > 0) + { + char ch = buf[len - 1]; + if (ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t') + { + buf[len - 1] = '\0'; + len--; + continue; + } + break; + } +} + +static bool parse_i32_csv5(const char *arg, struct bode_plot_param_t *out) +{ + int32_t vals[5] = { 0 }; + char *end = NULL; + + if (!arg || !out) + return false; + + for (int i = 0; i < 5; i++) + { + long v = strtol(arg, &end, 10); + if (end == arg || v < -2147483648L || v > 2147483647L) + return false; + + vals[i] = (int32_t)v; + + if (i < 4) + { + if (*end != ',') + return false; + arg = end + 1; + } + else if (*end != '\0') + { + return false; + } + } + + out->b0 = vals[0]; + out->b1 = vals[1]; + out->b2 = vals[2]; + out->a1 = vals[3]; + out->a2 = vals[4]; + return true; +} + +void uart_cmd_parse(char *cmd_buf, uint32_t size) +{ + if (!cmd_buf || size == 0) + return; + + const char *arg = NULL; + cmd_trim_eol(cmd_buf); + + /* Skip empty commands (e.g., from CR+LF line endings) */ + if (strlen(cmd_buf) == 0) + return; + + if (strcmp(cmd_buf, "help") == 0) + { + msg("Available commands:\r\n"); + msg(" help - show this help\r\n"); + msg(" version - show firmware version\r\n"); + msg(" bodeplot=B0,B1,B2,A1,A2\r\n"); + msg(" bodeplot? - show current bode plot parameters\r\n"); + msg(" flash_bodeplot? - show raw flash content for bode plot parameters\r\n"); + } + else if (strcmp(cmd_buf, "version") == 0) + { + msg("version: %s\r\n", "1.0.0"); + } + else if (cmd_match_with_arg(cmd_buf, "bodeplot=", &arg)) + { + struct bode_plot_param_t *bplot_p = &bode_plot_param; + if (parse_i32_csv5(arg, bplot_p)) + { + bode_plot_param_write_to_flash(bplot_p, FLASH_PROG_ADDR_USER_CALI); + } + else + { + msg("invalid bodeplot format, use: bodeplot=111,8,5,6,77\r\n"); + } + } + else if (strcmp(cmd_buf, "bodeplot?") == 0) + { + struct bode_plot_param_t *bplot_p = &bode_plot_param; + msg("bode plot param read from flash: b0=0x%08X, b1=0x%08X, b2=0x%08X, a1=0x%08X, a2=0x%08X\r\n", + bplot_p->b0, + bplot_p->b1, + bplot_p->b2, + bplot_p->a1, + bplot_p->a2); + msg("bode plot param read from flash: b0=%d, b1=%d, b2=%d, a1=%d, a2=%d\r\n", + bplot_p->b0, + bplot_p->b1, + bplot_p->b2, + bplot_p->a1, + bplot_p->a2); + } + else if (strcmp(cmd_buf, "flash_bodeplot?") == 0) + { + struct bode_plot_param_t tmp_bplot; + bode_plot_param_read_from_flash(&tmp_bplot, FLASH_PROG_ADDR_USER_CALI); + } + else + { + msg("Unknown command: %s\r\n", cmd_buf); + } +} + +/* flash*/ +#if 0 +static void dump_flash_bytes(uint32_t addr, uint32_t size) +{ + const uint8_t *pData = (const uint8_t *)addr; + + msg("flash dump source base address: 0x%08X, size=%u bytes\n", addr, (unsigned int)size); + + for (uint32_t i = 0; i < size; i++) + { + msg("read [0x%08X] = 0x%02X\n", (unsigned int)(addr + i), pData[i]); + } +} + +static void dump_flash_bytes_8perline(uint32_t addr, uint32_t size) +{ + const uint8_t *pData = (const uint8_t *)addr; + + msg("flash dump source base address: 0x%08X, size=%u bytes\n", addr, (unsigned int)size); + + for (uint32_t i = 0; i < size; i += 8) + { + msg("read [0x%08X]", (unsigned int)(addr + i)); + + for (uint32_t j = 0; j < 8 && (i + j) < size; j++) + { + msg(" %02X", pData[i + j]); + } + + msg("\n"); + } +} +#endif + +static int bode_plot_param_write_to_flash(const struct bode_plot_param_t *param, uint32_t addr) +{ + int rval = 0; + uint32_t word_data[5] = { 0 }; + + if (!param) + return -1; + + /* FLASH_ProgData requires 4-byte aligned length, so pad the last halfword. */ + word_data[0] = param->b0; + word_data[1] = param->b1; + word_data[2] = param->b2; + word_data[3] = param->a1; + word_data[4] = param->a2; + + rval = FLASH_ErasePage(addr); + if (rval) + { + err(" ! erase plot param fail (%d)\n", rval); + return rval; + } + + rval = FLASH_ProgData(addr, word_data, sizeof(word_data)); + if (rval) + { + err(" ! prog plot param fail (%d)\n", rval); + return rval; + } + + return 0; +} + +void bode_plot_param_read_from_flash(struct bode_plot_param_t *param, uint32_t addr) +{ + const void *flash_ptr = (const void *)addr; + + if (!param) + return; + + memcpy(param, flash_ptr, sizeof(*param)); + + msg("bode plot param read from flash: b0=0x%08X, b1=0x%08X, b2=0x%08X, a1=0x%08X, a2=0x%08X\r\n", + param->b0, + param->b1, + param->b2, + param->a1, + param->a2); + msg("bode plot param read from flash: b0=%d, b1=%d, b2=%d, a1=%d, a2=%d\r\n", + param->b0, + param->b1, + param->b2, + param->a1, + param->a2); +} + +/* main code*/ +void app(void) +{ + char cmd_buf[UART_RX_BUF_SIZE]; + + sysclk_systick_init(SYSCFG_ClkSrc_HSI, SYS_TICK_1_MS); + + sys_disable_ice(); + + uart_init(); + + info("This is a app demo project\n"); + info("uart cmd demo\n"); + + // read plot param from flash + struct bode_plot_param_t *bplot_p = &bode_plot_param; + bode_plot_param_read_from_flash(bplot_p, FLASH_PROG_ADDR_USER_CALI); + + while (1) + { + if (is_rx_frame_ready()) + { + uart_rx_getline(cmd_buf, sizeof(cmd_buf)); + msg("RX: %s\r\n", cmd_buf); + uart_cmd_parse(cmd_buf, sizeof(cmd_buf)); + } + } +} diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/copy_main.c b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/copy_main.c index e77fa8c..fb047e4 100644 --- a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/copy_main.c +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/copy_main.c @@ -1,23 +1,23 @@ #if 0 -#include "main.h" -#include "isr.h" #include "init.h" +#include "isr.h" +#include "main.h" //============================================================================= // Constant Definition //============================================================================= -#define DATA_LOG 0 -#define DATA_MONITOR 1 -#define DEBOUNCE_TIME 20 -#define BUF_SIZE 100 // > 300 記憶體不夠用(4組) > 700 記憶體不夠用(2組) +#define DATA_LOG 0 +#define DATA_MONITOR 1 +#define DEBOUNCE_TIME 20 +#define BUF_SIZE 100 // > 300 記憶體不夠用(4組) > 700 記憶體不夠用(2組) -#define CR_1P1Z_B0_Q14 6313 -#define CR_1P1Z_B1_Q14 -5113 -#define CR_1P1Z_A1_Q14 -5803 +#define CR_1P1Z_B0_Q14 6313 +#define CR_1P1Z_B1_Q14 -5113 +#define CR_1P1Z_A1_Q14 -5803 // 前饋輸出限制(請根據您主環 Q14 格式的數值範圍調整) // 假設最大前饋量限制為實數值 50.0 -> 50.0 * 16384 = 819200 -#define CR_FF_MAX_Q14 819200 // 50 duty << 14 -#define CR_FF_MIN_Q14 -819200 +#define CR_FF_MAX_Q14 819200 // 50 duty << 14 +#define CR_FF_MIN_Q14 -819200 //============================================================================= // Macro Definition @@ -54,8 +54,8 @@ typedef enum { //#define ff_max 8000 //#define v_kp 10 -#define v_ki 10 -#define v_kd 0 +#define v_ki 10 +#define v_kd 0 SystemState_t sys_state = STATE_INIT; uint8_t is_zero_crossing = 0; @@ -561,7 +561,7 @@ __attribute__((always_inline)) static inline void Cur_Loop_PFC_2P2Z(void) // 優 //count1++; // ------------------------------------------- // 5. data log - #if DATA_LOG +#if DATA_LOG count_down--; if (count_down < 1000) { @@ -578,7 +578,7 @@ __attribute__((always_inline)) static inline void Cur_Loop_PFC_2P2Z(void) // 優 pfc_pwm_disable(); sys_state = STATE_PAUSE; } - #endif +#endif // ------------------------------------------- } //============================================================================ @@ -834,7 +834,7 @@ int main(void) } #endif -#if 1 // 測試 PFC 電壓環 + 電流環 (電流環無法穩壓) (電壓環 + 電流環有 BUG,會多一個小 PULSE) +#if 1 // 測試 PFC 電壓環 + 電流環 (電流環無法穩壓) (電壓環 + 電流環有 BUG,會多一個小 PULSE) TIM2->CCR1 = 12; // min duty sys_state = STATE_PFC_SOFT_START; @@ -1082,13 +1082,13 @@ int main(void) // --- 3. 非即時任務 (UI、通訊、Data Log) --- Key1_Scan(); - #if DATA_LOG +#if DATA_LOG if (is_full == 1) Handle_UART_Log(); // 利用 PEC930 UART 輸出數據 [cite: 105, 336] - #endif +#endif - #if DATA_MONITOR +#if DATA_MONITOR Handle_UART_Monitor(); - #endif +#endif } // while -------------------------------------------------------------------- diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/init.c b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/init.c index 069d340..453e9ba 100644 --- a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/init.c +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/init.c @@ -5,16 +5,15 @@ * Author: jim_liao */ -//#include "main.h" -#include "isr.h" #include "init.h" +#include "app.h" #include "hal_device.h" +#include "isr.h" //============================================================================= // Constant Definition //============================================================================= -//#define CONFIG_OPA_PGA_GAIN OPAMP_PGAGain_1 //OPAMP_PGAGain_5 - +// #define CONFIG_OPA_PGA_GAIN OPAMP_PGAGain_1 //OPAMP_PGAGain_5 //============================================================================= // Public Function Definition @@ -66,168 +65,164 @@ _Post_Proc(PWR_ModeTypeDef pwr_mode) //======================================================================== void SYS_Config() { - SYSCFG_ClkInitTypeDef SysClkInit = {0}; + SYSCFG_ClkInitTypeDef SysClkInit = { 0 }; - SysClkInit.ClkSource = SYSCFG_SYSCLKCR_CLKSW_HSI; - SYSCFG_SysClkConfig(&SysClkInit); + SysClkInit.ClkSource = SYSCFG_SYSCLKCR_CLKSW_HSI; + SYSCFG_SysClkConfig(&SysClkInit); - sys_config_systick(SYS_TICK_1_MS); + sys_config_systick(SYS_TICK_1_MS); - //PWR_EnterDeepSleepMode(_Pre_Proc, _Post_Proc); // use WDG wake up 1 sec + // PWR_EnterDeepSleepMode(_Pre_Proc, _Post_Proc); // use WDG wake up 1 sec - gpio_config(); - opa_config(); - adc_config(); - llc_pwm_config(); // 初始化但不輸出 EPWM_CH1 - pfc_pwm_config(); // 初始化但不輸出 TIM2_CH1 + gpio_config(); + opa_config(); + adc_config(); + llc_pwm_config(); // 初始化但不輸出 EPWM_CH1 + pfc_pwm_config(); // 初始化但不輸出 TIM2_CH1 - __NOP();__NOP();__NOP();__NOP();__NOP(); // timer shift between pfc and tim0 + __NOP(); + __NOP(); + __NOP(); + __NOP(); + __NOP(); // timer shift between pfc and tim0 - tim0_config(); // trigger ADC, current loop frequency - uart_config(); // UART + tim0_config(); // trigger ADC, current loop frequency + uart_init(); } //=================================================================================== void gpio_config() { - //-----------------// - // OPA - // IN+ = PA8 - // IN- = PA9 - // OUT = PA7 - //-----------------// + //-----------------// + // OPA + // IN+ = PA8 + // IN- = PA9 + // OUT = PA7 + //-----------------// - GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitTypeDef GPIO_InitStruct; - #if 1 - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_07 | GPIO_Pin_08; // Pin_09 is set as power_ok - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_ANAL; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(GPIOA , &GPIO_InitStruct); - #endif +#if 1 + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_07 | GPIO_Pin_08; // Pin_09 is set as power_ok + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_ANAL; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOA, &GPIO_InitStruct); +#endif - #if 1 - //-----------------// - // PWM - // LLC: PA0, PA1 - // PFC: PA2 - //-----------------// - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_00 | GPIO_Pin_01; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStruct.GPIO_AF_Mode = GPIO_AF_6; // AF6 = EPWM - GPIO_Init(GPIOA, &GPIO_InitStruct); +#if 1 + //-----------------// + // PWM + // LLC: PA0, PA1 + // PFC: PA2 + //-----------------// + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_00 | GPIO_Pin_01; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStruct.GPIO_AF_Mode = GPIO_AF_6; // AF6 = EPWM + GPIO_Init(GPIOA, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_02; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStruct.GPIO_AF_Mode = GPIO_AF_5; // AF5 = TIM2 - GPIO_Init(GPIOA, &GPIO_InitStruct); - //-----------------// - // UART - // PB3:TX PB5:RX - //-----------------// - GPIO_InitTypeDef GPIOA_InitUart; - GPIO_InitTypeDef GPIOB_InitUart; + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_02; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStruct.GPIO_AF_Mode = GPIO_AF_5; // AF5 = TIM2 + GPIO_Init(GPIOA, &GPIO_InitStruct); - GPIOB_InitUart.GPIO_Pin = GPIO_Pin_03 | GPIO_Pin_05; // PB3, PB5 - GPIOB_InitUart.GPIO_Mode = GPIO_Mode_AF; - GPIOB_InitUart.GPIO_AF_Mode = GPIO_AF_1; - GPIO_Init(GPIOB, &GPIOB_InitUart); - //-----------------// - // ADC - // PA7(iac), PA10(vbus), PA13(vac) // PA11(cr), PA12(vfb)-->GPIO - //-----------------// - GPIO_InitTypeDef GPIO_InitADC; - GPIO_InitADC.GPIO_Pin = GPIO_Pin_07 | GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_11; // PA11(cr) - GPIO_InitADC.GPIO_Mode = GPIO_Mode_ANAL; - GPIO_Init(GPIOA, &GPIO_InitADC); + //-----------------// + // ADC + // PA7(iac), PA10(vbus), PA13(vac) // PA11(cr), PA12(vfb)-->GPIO + //-----------------// + GPIO_InitTypeDef GPIO_InitADC; + GPIO_InitADC.GPIO_Pin = GPIO_Pin_07 | GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_11; // PA11(cr) + GPIO_InitADC.GPIO_Mode = GPIO_Mode_ANAL; + GPIO_Init(GPIOA, &GPIO_InitADC); - //-----------------// - // Button - //-----------------// - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15; // PA15 - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN ; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // pull up - GPIO_Init(GPIOA, &GPIO_InitStruct); + //-----------------// + // Button + //-----------------// + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15; // PA15 + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // pull up + GPIO_Init(GPIOA, &GPIO_InitStruct); - //-----------------// - // FB (VCOMP) - //-----------------// - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12; // PA12 - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN ; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // no pull - GPIO_Init(GPIOA, &GPIO_InitStruct); - #endif + //-----------------// + // FB (VCOMP) + //-----------------// + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12; // PA12 + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // no pull + GPIO_Init(GPIOA, &GPIO_InitStruct); +#endif - #if 0 // 取消了 +#if 0 // 取消了 //-----------------// // test pin PA5: TP1, PA6: TP2 //-----------------// GPIO_InitStruct.GPIO_Pin = GPIO_Pin_05 | GPIO_Pin_06; // PA6 = TP2 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init(GPIOA, &GPIO_InitStruct); - #endif +#endif } //=================================================================================== void opa_config(void) { - OPAMP_InitTypeDef opa_init = {0}; + OPAMP_InitTypeDef opa_init = { 0 }; - opa_init.OPAMP_VinP = OPAMP_VinP_IO; - opa_init.OPAMP_VinM = OPAMP_VinM_GND; // 設定內部 GND ,PIN 留給 POWER_OK - opa_init.OPAMP_Vout = OPAMP_Vout_IO; // 拉到 IO,需要外部 500 ~ 1000pF 電容 - opa_init.OPAMP_Gain = OPAMP_PGAGain_15; // 使用最大 15 倍,減少 RS 功耗 + opa_init.OPAMP_VinP = OPAMP_VinP_IO; + opa_init.OPAMP_VinM = OPAMP_VinM_GND; // 設定內部 GND ,PIN 留給 POWER_OK + opa_init.OPAMP_Vout = OPAMP_Vout_IO; // 拉到 IO,需要外部 500 ~ 1000pF 電容 + opa_init.OPAMP_Gain = OPAMP_PGAGain_15; // 使用最大 15 倍,減少 RS 功耗 - // 正向放大器 OK - // 電壓隨耦器 OK - // 反向放大器 NG - // V+ 接 1/2 VCC,差動放大器 OK + // 正向放大器 OK + // 電壓隨耦器 OK + // 反向放大器 NG + // V+ 接 1/2 VCC,差動放大器 OK - OPAMP_Init(OPAMP0, &opa_init); + OPAMP_Init(OPAMP0, &opa_init); - OPAMP_Enable(OPAMP0); + OPAMP_Enable(OPAMP0); } //=================================================================================== void adc_config(void) { - ADC_InitTypeDef init = {0}; - ADC_StructInit(&init); + ADC_InitTypeDef init = { 0 }; + ADC_StructInit(&init); - ADC_InitTypeDef init1 = {0}; - ADC_StructInit(&init1); - // iac = PA7 = ADC_Channel_09 - // vac = PA13 = ADC_Channel_07 - // vbus = PA10 = ADC_Channel_04 - // ---------------------------------------------- - // vcr = PA11 = ADC_Channel_05 (未使用) - // vfb = PA12 = ADC_Channel_06 (使用 GPIO) - init1.SelChannels = ADC_Channel_04 | ADC_Channel_07 | ADC_Channel_09; - //init1.SelChannels = ADC_Channel_09 ;// OP_O 指定到 PA7 時,ADC 需要用 CH_09 讀取 - init1.ClkPrescaler = ADC_ClkDiv_4; // 60M/4 = 15M,接近 1MSPS (1us 轉換時間), 最快速度 - init1.DataAlign = ADC_DataAlign_Right; - init1.Mode = ADC_Mode_Scan; // Scan mode - ADC_Init(ADC0, &init1); + ADC_InitTypeDef init1 = { 0 }; + ADC_StructInit(&init1); + // iac = PA7 = ADC_Channel_09 + // vac = PA13 = ADC_Channel_07 + // vbus = PA10 = ADC_Channel_04 + // ---------------------------------------------- + // vcr = PA11 = ADC_Channel_05 (未使用) + // vfb = PA12 = ADC_Channel_06 (使用 GPIO) + init1.SelChannels = ADC_Channel_04 | ADC_Channel_07 | ADC_Channel_09; + // init1.SelChannels = ADC_Channel_09 ;// OP_O 指定到 PA7 時,ADC 需要用 CH_09 讀取 + init1.ClkPrescaler = ADC_ClkDiv_4; // 60M/4 = 15M,接近 1MSPS (1us 轉換時間), 最快速度 + init1.DataAlign = ADC_DataAlign_Right; + init1.Mode = ADC_Mode_Scan; // Scan mode + ADC_Init(ADC0, &init1); - //ADC_ExtTrigConfig(ADC0, ADC_ExtTrigSource_EPWM_CH2R, ADC_ExtTrigMode_Enable); - ADC_ExtTrigConfig(ADC0, ADC_ExtTrigSource_16, ADC_ExtTrigMode_Enable); // use tim0 trigger + // ADC_ExtTrigConfig(ADC0, ADC_ExtTrigSource_EPWM_CH2R, ADC_ExtTrigMode_Enable); + ADC_ExtTrigConfig(ADC0, ADC_ExtTrigSource_16, ADC_ExtTrigMode_Enable); // use tim0 trigger - #if 1 - { // Configure TIM interrupts - sys_irq_attr_t irq_attr = { .disable_vector = false, }; +#if 1 + { // Configure TIM interrupts + sys_irq_attr_t irq_attr = { + .disable_vector = false, + }; - irq_attr.trig_mode = SYS_IRQ_TRIGGER_LEVEL; - irq_attr.level = SYS_IRQ_LEVEL_H; - irq_attr.priority = SYS_IRQ_PRIORITY_MIDDEN; - sys_register_IRQ(ADC0_IRQn, isr_adc_handle, &irq_attr); - ADC0->CON0_b.INT_EN = 1; - } - #endif + irq_attr.trig_mode = SYS_IRQ_TRIGGER_LEVEL; + irq_attr.level = SYS_IRQ_LEVEL_H; + irq_attr.priority = SYS_IRQ_PRIORITY_MIDDEN; + sys_register_IRQ(ADC0_IRQn, isr_adc_handle, &irq_attr); + ADC0->CON0_b.INT_EN = 1; + } +#endif } //=================================================================================== void llc_pwm_config() // complimentary PWM for LLC { - TIM_OCInitTypeDef TIM_OCInitStruct; - TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; + TIM_OCInitTypeDef TIM_OCInitStruct; + TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; - /* + /* { // Configure TIM interrupts sys_irq_attr_t irq_attr = { .disable_vector = false, }; @@ -236,57 +231,57 @@ void llc_pwm_config() // complimentary PWM for LLC irq_attr.priority = SYS_IRQ_PRIORITY_MIDDEN; sys_register_IRQ(EPWM_IRQn, isr_epwm_handle, &irq_attr); } - */ - TIM_DeInit(EPWM); + */ + TIM_DeInit(EPWM); - TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct); - TIM_TimeBaseInitStruct.TIM_Prescaler = 0; - TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInitStruct.TIM_Period = LLC_PERIOD_SS; - TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_Div1; - TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; - TIM_TimeBaseInit(EPWM, &TIM_TimeBaseInitStruct); + TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct); + TIM_TimeBaseInitStruct.TIM_Prescaler = 0; + TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInitStruct.TIM_Period = LLC_PERIOD_SS; + TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_Div1; + TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; + TIM_TimeBaseInit(EPWM, &TIM_TimeBaseInitStruct); - TIM_ARRPreloadConfig(EPWM,ENABLE); + TIM_ARRPreloadConfig(EPWM, ENABLE); - TIM_OCStructInit(&TIM_OCInitStruct); - TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; - TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Disable; - TIM_OCInitStruct.TIM_Pulse = 0; - TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; - TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset; - TIM_OCInitStruct.TIM_Pulse = 1; + TIM_OCStructInit(&TIM_OCInitStruct); + TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; + TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Disable; + TIM_OCInitStruct.TIM_Pulse = 0; + TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset; + TIM_OCInitStruct.TIM_Pulse = 1; - TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable; - TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCPolarity_High; - TIM_OC1Init(EPWM, &TIM_OCInitStruct); + TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable; + TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCPolarity_High; + TIM_OC1Init(EPWM, &TIM_OCInitStruct); - TIM_OCInitStruct.TIM_Pulse = 1; - TIM_OC2Init(EPWM, &TIM_OCInitStruct); + TIM_OCInitStruct.TIM_Pulse = 1; + TIM_OC2Init(EPWM, &TIM_OCInitStruct); - { /* Automatic Output enable, Break, dead time and lock configuration */ - TIM_BDTRInitTypeDef bdtr_init = {0}; - bdtr_init.TIM_LOCKLevel = TIM_LockLevel_OFF; - bdtr_init.TIM_DeadTime = DEAD_TIME_VALUE; + { /* Automatic Output enable, Break, dead time and lock configuration */ + TIM_BDTRInitTypeDef bdtr_init = { 0 }; + bdtr_init.TIM_LOCKLevel = TIM_LockLevel_OFF; + bdtr_init.TIM_DeadTime = DEAD_TIME_VALUE; - TIM_BDTRConfig(EPWM, &bdtr_init); - } + TIM_BDTRConfig(EPWM, &bdtr_init); + } - //EPWM->DIER |= 0x1000; // Underflow interrupt enable - //__enable_irq(); - TIM_Cmd(EPWM, ENABLE); - TIM_CtrlPWMOutputs(EPWM, ENABLE); - EPWM->CCMR1_OUTPUT_b.OC1PE = 1; // Output Compare 1 preload enable + // EPWM->DIER |= 0x1000; // Underflow interrupt enable + //__enable_irq(); + TIM_Cmd(EPWM, ENABLE); + TIM_CtrlPWMOutputs(EPWM, ENABLE); + EPWM->CCMR1_OUTPUT_b.OC1PE = 1; // Output Compare 1 preload enable - //EPWM->CCR1 = 300; // for test - //REG_SET_BITS(EPWM->CCER, TIM_CCER_CC1E_Msk | TIM_CCER_CC1NE_Msk); // 需要 SET 才會輸出 + // EPWM->CCR1 = 300; // for test + // REG_SET_BITS(EPWM->CCER, TIM_CCER_CC1E_Msk | TIM_CCER_CC1NE_Msk); // 需要 SET 才會輸出 } //=================================================================================== void pfc_pwm_config() // single PWM for PFC { - TIM_OCInitTypeDef TIM_OCInitStruct; - TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; - /* + TIM_OCInitTypeDef TIM_OCInitStruct; + TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; + /* { // Configure TIM interrupts sys_irq_attr_t irq_attr = { .disable_vector = false, }; @@ -295,74 +290,56 @@ void pfc_pwm_config() // single PWM for PFC irq_attr.priority = SYS_IRQ_PRIORITY_MIDDEN; sys_register_IRQ(TIM2_IRQn, isr_tim2_handle, &irq_attr); } - */ + */ - TIM_DeInit(TIM2); + TIM_DeInit(TIM2); - TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct); - TIM_TimeBaseInitStruct.TIM_Prescaler = 0; - TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInitStruct.TIM_Period = PFC_PERIOD; - TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_Div1; - TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); - TIM_ARRPreloadConfig(TIM2, ENABLE); + TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct); + TIM_TimeBaseInitStruct.TIM_Prescaler = 0; + TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInitStruct.TIM_Period = PFC_PERIOD; + TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_Div1; + TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; + TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); + TIM_ARRPreloadConfig(TIM2, ENABLE); - TIM_OCStructInit(&TIM_OCInitStruct); - TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; - TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Disable; - TIM_OCInitStruct.TIM_Pulse = 0; - TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; - TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset; - TIM_OCInitStruct.TIM_Pulse = 1; - //TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable; // no negative output - //TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCPolarity_High; - TIM_OC1Init(TIM2, &TIM_OCInitStruct); + TIM_OCStructInit(&TIM_OCInitStruct); + TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; + TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Disable; + TIM_OCInitStruct.TIM_Pulse = 0; + TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset; + TIM_OCInitStruct.TIM_Pulse = 1; + // TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable; // no negative output + // TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCPolarity_High; + TIM_OC1Init(TIM2, &TIM_OCInitStruct); - //TIM2->DIER |= 0x1000; // Underflow interrupt enable - //__enable_irq(); - TIM_Cmd(TIM2, ENABLE); // enable PWM - TIM_CtrlPWMOutputs(TIM2, ENABLE); // enable PWM output - TIM2->CCMR1_OUTPUT_b.OC1PE = 1; // Output Compare 1 preload enable - //TIM2->CCR1 = 200; // for test - //REG_SET_BITS(TIM2->CCER, TIM_CCER_CC1E_Msk); // set bit enable output + // TIM2->DIER |= 0x1000; // Underflow interrupt enable + //__enable_irq(); + TIM_Cmd(TIM2, ENABLE); // enable PWM + TIM_CtrlPWMOutputs(TIM2, ENABLE); // enable PWM output + TIM2->CCMR1_OUTPUT_b.OC1PE = 1; // Output Compare 1 preload enable + // TIM2->CCR1 = 200; // for test + // REG_SET_BITS(TIM2->CCER, TIM_CCER_CC1E_Msk); // set bit enable output } -//=================================================================================== -void uart_config() -{ - UART_InitTypeDef uart_init = {0}; - uart_init.BaudRate = 9600; //115200; - uart_init.WordLength = UART_WordLength_8b; - uart_init.StopBits = UART_StopBits_1; - uart_init.Parity = UART_Parity_No; - uart_init.Mode = UART_Mode_TxRx; - UART_Init(UART0, &uart_init); - UART_Start(UART0); -} -//=================================================================================== -void UART_Send_Wait(UART_Type *pHUart, uint16_t value) -{ - UART_SendData(pHUart,value); - UART_WaitTxFifoEmpty(pHUart); -} //=================================================================================== void tim0_config() { - LPTIM_InitTypeDef Init = {0}; + LPTIM_InitTypeDef Init = { 0 }; - Init.LPTIM_Prescaler = 0; - Init.LPTIM_ClockSource = LPTIM_CLK_Src_SysClk; - Init.LPTIM_MatchMode = LPTIM_MatchMode_IRQ | LPTIM_MatchMode_Reset; // | LPTIM_MatchMode_Stop; - Init.LPTIM_MatchValue = TIM0_PERIOD; - LPTIM_Init(TIM0, &Init); + Init.LPTIM_Prescaler = 0; + Init.LPTIM_ClockSource = LPTIM_CLK_Src_SysClk; + Init.LPTIM_MatchMode = LPTIM_MatchMode_IRQ | LPTIM_MatchMode_Reset; // | LPTIM_MatchMode_Stop; + Init.LPTIM_MatchValue = TIM0_PERIOD; + LPTIM_Init(TIM0, &Init); - #if 0 +#if 0 sys_irq_attr_t irq_attr = { .trig_mode = SYS_IRQ_TRIGGER_LEVEL, }; sys_register_IRQ(TIM0_IRQn, isr_tim0_handle, &irq_attr); sys_enable_girq(); LPTIM_ITConfig(TIM0, true); - #endif +#endif - LPTIM_Enable(TIM0); + LPTIM_Enable(TIM0); } diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/isr.c b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/isr.c index 8aa4738..41774b9 100644 --- a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/isr.c +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/isr.c @@ -10,7 +10,6 @@ * @description */ -#include "main.h" #include "isr.h" #include "init.h" @@ -25,13 +24,13 @@ //============================================================================= // Global Data Definition //============================================================================= -//uint8_t volatile tim0_trigger = 0; -//extern uint16_t iac; -//extern uint16_t vac; -//extern uint16_t vbus; -//extern uint16_t vac_avg1, vac_avg2; -//extern uint16_t vbus_avg; -//extern uint8_t hi_line; +// uint8_t volatile tim0_trigger = 0; +// extern uint16_t iac; +// extern uint16_t vac; +// extern uint16_t vbus; +// extern uint16_t vac_avg1, vac_avg2; +// extern uint16_t vbus_avg; +// extern uint8_t hi_line; //============================================================================= // Private Function Definition //============================================================================= @@ -42,9 +41,9 @@ /* __INTERRUPT void isr_tim2_handle(void) { - if((TIM2->SR & 0x20000) == 0x20000) // UDIF: Underflow interrupt flag + if((TIM2->SR & 0x20000) == 0x20000) // UDIF: Underflow interrupt flag { - TIM_ClearITPendingBit(TIM2, 0x20000); + TIM_ClearITPendingBit(TIM2, 0x20000); } } */ @@ -68,5 +67,3 @@ __INTERRUPT void isr_tim0_handle(void) return; } #endif - - diff --git a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/main.c b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/main.c index ac865c0..1c5e448 100644 --- a/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/main.c +++ b/pec930_sdk-v1.0.1/Examples/template/PFC_LLC_2026-05-20_2P2Z_ok/src/main.c @@ -1,23 +1,24 @@ #include "main.h" -#include "isr.h" +#include "app.h" #include "init.h" +#include "isr.h" //============================================================================= // Constant Definition //============================================================================= -#define DATA_LOG 0 -#define DATA_MONITOR 1 -#define DEBOUNCE_TIME 20 -#define BUF_SIZE 100 // > 300 記憶體不夠用(4組) > 700 記憶體不夠用(2組) +#define DATA_LOG 0 +#define DATA_MONITOR 0 +#define DEBOUNCE_TIME 20 +#define BUF_SIZE 100 // > 300 記憶體不夠用(4組) > 700 記憶體不夠用(2組) -#define CR_1P1Z_B0_Q14 6313 -#define CR_1P1Z_B1_Q14 -5113 -#define CR_1P1Z_A1_Q14 -5803 +#define CR_1P1Z_B0_Q14 6313 +#define CR_1P1Z_B1_Q14 -5113 +#define CR_1P1Z_A1_Q14 -5803 // 前饋輸出限制(請根據您主環 Q14 格式的數值範圍調整) // 假設最大前饋量限制為實數值 50.0 -> 50.0 * 16384 = 819200 -#define CR_FF_MAX_Q14 819200 // 50 duty << 14 -#define CR_FF_MIN_Q14 -819200 +#define CR_FF_MAX_Q14 819200 // 50 duty << 14 +#define CR_FF_MIN_Q14 -819200 //============================================================================= // Macro Definition @@ -26,36 +27,38 @@ //============================================================================= // Structure Definition //============================================================================= -typedef enum { - KEY_IDLE = 0, - KEY_DOWN, - KEY_WAIT_RELEASE +typedef enum +{ + KEY_IDLE = 0, + KEY_DOWN, + KEY_WAIT_RELEASE } KeyState_t; -typedef enum { - STATE_INIT, - STATE_STANDBY, // 等 AC brown-in - STATE_PFC_SOFT_START, // 第一階段:PFC 透過最小 duty 提升 vbus,若 vbus 足夠,直接進入下一階段 - STATE_LLC_SOFT_START, // 第二階段:LLC 掃頻 - STATE_RUN_NORMAL, // 第三階段:二級都進入穩態閉環 - STATE_RUN_SKIP, // 第四階段:負載太小,暫時關閉 PFC - STATE_FAULT, // 故障保護 - STATE_PAUSE // 暫停,測試用 +typedef enum +{ + STATE_INIT, + STATE_STANDBY, // 等 AC brown-in + STATE_PFC_SOFT_START, // 第一階段:PFC 透過最小 duty 提升 vbus,若 vbus 足夠,直接進入下一階段 + STATE_LLC_SOFT_START, // 第二階段:LLC 掃頻 + STATE_RUN_NORMAL, // 第三階段:二級都進入穩態閉環 + STATE_RUN_SKIP, // 第四階段:負載太小,暫時關閉 PFC + STATE_FAULT, // 故障保護 + STATE_PAUSE // 暫停,測試用 } SystemState_t; //============================================================================= // Global Data Definition //============================================================================= -//#define kp 250 -//#define ki 2 -//#define kd 0 +// #define kp 250 +// #define ki 2 +// #define kd 0 -//#define ff_max 8000 +// #define ff_max 8000 -//#define v_kp 10 -#define v_ki 10 -#define v_kd 0 +// #define v_kp 10 +#define v_ki 10 +#define v_kd 0 SystemState_t sys_state = STATE_INIT; uint8_t is_zero_crossing = 0; @@ -73,9 +76,9 @@ static uint16_t vac = 0; static uint16_t vbus = 0; static uint16_t vcr = 0; -static int32_t vcr_x1_q14 = 0; // x[n-1] -static int32_t vcr_y1_q14 = 0; // y[n-1] -static int32_t cr_feed_forward_output_q14 = 0; // 最終輸出的 Q14 補償量 +static int32_t vcr_x1_q14 = 0; // x[n-1] +static int32_t vcr_y1_q14 = 0; // y[n-1] +static int32_t cr_feed_forward_output_q14 = 0; // 最終輸出的 Q14 補償量 uint32_t count1; @@ -83,8 +86,8 @@ uint32_t vbus_ovp = (VBUS_OVP * 4096 / VBUS_2ADC / 3.3); uint32_t vbus_set = (VBUS_SET * 4096 / VBUS_2ADC / 3.3); uint32_t vbus_set_h = (VBUS_SET_H * 4096 / VBUS_2ADC / 3.3); // burst mode in uint32_t vbus_set_l = (VBUS_SET_L * 4096 / VBUS_2ADC / 3.3); // burst mode out -//uint32_t vbus_set_h2 = (VBUS_SET_H2 * 4096 / VBUS_2ADC / 3.3); -//uint32_t digi_vcomp_max = (uint32_t)(VBUS_SET_H * 4096 / VBUS_2ADC / 3.3) << DIGI_COMP_BIT; +// uint32_t vbus_set_h2 = (VBUS_SET_H2 * 4096 / VBUS_2ADC / 3.3); +// uint32_t digi_vcomp_max = (uint32_t)(VBUS_SET_H * 4096 / VBUS_2ADC / 3.3) << DIGI_COMP_BIT; uint32_t digi_vcomp_max = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT; int32_t vbus_err = 0; int32_t vbus_err_prev = 0; @@ -96,10 +99,10 @@ uint16_t pfc_duty = 0; uint8_t pfc_ss = 0; uint16_t pfc_ss_cnt = 0; uint16_t llc_ss_cnt = 0; -//volatile int16_t iac_err_0, iac_err_1; -//volatile uint16_t iac_set; -//volatile int32_t iac_int, iac_por, iac_der; -//volatile int16_t iac_comp = 0; +// volatile int16_t iac_err_0, iac_err_1; +// volatile uint16_t iac_set; +// volatile int32_t iac_int, iac_por, iac_der; +// volatile int16_t iac_comp = 0; //----------------------------------------------- KeyState_t key1State = KEY_IDLE; uint32_t key1Timer = 0; @@ -112,8 +115,8 @@ uint32_t msg_timer; uint16_t vbus_volt, vac_volt; int32_t tx_buf1[BUF_SIZE]; int64_t tx_buf2[BUF_SIZE]; -//uint16_t tx_buf3[BUF_SIZE]; -//uint16_t tx_buf4[BUF_SIZE]; +// uint16_t tx_buf3[BUF_SIZE]; +// uint16_t tx_buf4[BUF_SIZE]; uint16_t buf_idx = 0; uint8_t is_full = 0; uint16_t count_down = 60000; // for data log @@ -135,29 +138,29 @@ uint16_t brownout_cnt = 0; uint8_t volatile tim0_trigger = 0; // 全局或靜態變數(需在函數外或 static 保留狀態) -static int32_t iac_err_0 = 0; // e[k] -static int32_t iac_err_1 = 0; // e[k-1] -static int32_t iac_err_2 = 0; // e[k-2] -static int32_t iac_comp = 0; // u[k] -static int32_t iac_comp_1 = 0; // u[k-1] (前一次輸出) -static int32_t iac_comp_2 = 0; // u[k-2] (前兩次輸出) +static int32_t iac_err_0 = 0; // e[k] +static int32_t iac_err_1 = 0; // e[k-1] +static int32_t iac_err_2 = 0; // e[k-2] +static int32_t iac_comp = 0; // u[k] +static int32_t iac_comp_1 = 0; // u[k-1] (前一次輸出) +static int32_t iac_comp_2 = 0; // u[k-2] (前兩次輸出) static int32_t vbus_err_1 = 0; static int32_t vbus_comp_1 = 0; // 2P2Z 係數(這些需要根據你的 PID 增益與控制頻率重新計算或調試) -//int32_t b0 = kp + ki + kd; // 對應比例 + 部分積分/微分貢獻(可調整) -//int32_t b1 = -kp - kd - kd; // e[k-1] 係數(通常為正或負) -//int32_t b2 = kd; // e[k-2] 係數 -//int32_t a1 = 128; // -A1(因為通常寫成 u[k] = ... + A1*u[k-1] + A2*u[k-2],這裡 a1 = 128 代表 A1 ≈ 1) -//int32_t a2 = 0; // -A2(PID 特例時 a2 常為 0) +// int32_t b0 = kp + ki + kd; // 對應比例 + 部分積分/微分貢獻(可調整) +// int32_t b1 = -kp - kd - kd; // e[k-1] 係數(通常為正或負) +// int32_t b2 = kd; // e[k-2] 係數 +// int32_t a1 = 128; // -A1(因為通常寫成 u[k] = ... + A1*u[k-1] + A2*u[k-2],這裡 a1 = 128 代表 A1 ≈ 1) +// int32_t a2 = 0; // -A2(PID 特例時 a2 常為 0) // 電壓環 2p2z 係數 -//int32_t v_b0 = v_kp + v_ki + v_kd; -//int32_t v_b1 = -v_kp - v_kd - v_kd; -//int32_t v_b2 = v_kd; -//int32_t v_a1 = 128; -//int32_t v_a2 = 0; +// int32_t v_b0 = v_kp + v_ki + v_kd; +// int32_t v_b1 = -v_kp - v_kd - v_kd; +// int32_t v_b2 = v_kd; +// int32_t v_a1 = 128; +// int32_t v_a2 = 0; uint16_t updata_cnt = 0; @@ -170,173 +173,182 @@ int32_t vbus_err_prev1, vbus_err_prev2; //============================================================================= void A_Para_Reset() { - vbus_int = 0; vbus_comp = 1000; - //iac_int = 0; iac_comp = 1000; - digital_vcomp = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT; - vbus_set = (VBUS_SET * 4096 / VBUS_2ADC / 3.3); - pfc_ss = 0; pfc_ss_cnt = 0; - v_loop_cnt = 0; - temp_off = 0; + vbus_int = 0; + vbus_comp = 1000; + // iac_int = 0; iac_comp = 1000; + digital_vcomp = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT; + vbus_set = (VBUS_SET * 4096 / VBUS_2ADC / 3.3); + pfc_ss = 0; + pfc_ss_cnt = 0; + v_loop_cnt = 0; + temp_off = 0; - iac_err_0 = 0; - iac_err_1 = 0; - iac_err_2 = 0; - iac_comp_1 = 0; - iac_comp_2 = 0; + iac_err_0 = 0; + iac_err_1 = 0; + iac_err_2 = 0; + iac_comp_1 = 0; + iac_comp_2 = 0; - vbus_err = 0; - vbus_err_prev = 0; - vbus_err_prev1 = 0; - vbus_err_prev2 = 0; - vbus_comp_prev = 0; - vbus_comp_prev1 = 0; - vbus_comp_prev2 = 0; - //vbus_comp2 = 1000; + vbus_err = 0; + vbus_err_prev = 0; + vbus_err_prev1 = 0; + vbus_err_prev2 = 0; + vbus_comp_prev = 0; + vbus_comp_prev1 = 0; + vbus_comp_prev2 = 0; + // vbus_comp2 = 1000; - // set default value - TIM2->ARR = PFC_PERIOD; - TIM2->CCR1 = PFC_DUTY_MIN; // min for ss - TIM2->EGR |= 0x01; - EPWM->ARR = LLC_PERIOD_SS; - EPWM->CCR1 = (LLC_PERIOD_SS >> 1); - EPWM->EGR |= 0x01; - llc_period_ss = 0; + // set default value + TIM2->ARR = PFC_PERIOD; + TIM2->CCR1 = PFC_DUTY_MIN; // min for ss + TIM2->EGR |= 0x01; + EPWM->ARR = LLC_PERIOD_SS; + EPWM->CCR1 = (LLC_PERIOD_SS >> 1); + EPWM->EGR |= 0x01; + llc_period_ss = 0; - pfc_running = 0; - llc_running = 0; - brownout_cnt = 0; + pfc_running = 0; + llc_running = 0; + brownout_cnt = 0; } //------------------------------------------------------------------------------ void Key1_Scan() { - keyInput = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15); + keyInput = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15); - switch (key1State) { - case KEY_IDLE: - if (keyInput == 0) { // 剛按下 - key1Timer = sys_get_tick(); // 紀錄時間 - key1State = KEY_DOWN; - } - break; + switch (key1State) + { + case KEY_IDLE: + if (keyInput == 0) + { // 剛按下 + key1Timer = sys_get_tick(); // 紀錄時間 + key1State = KEY_DOWN; + } + break; - case KEY_DOWN: - if (keyInput == 0) { - if (sys_get_tick() - key1Timer >= DEBOUNCE_TIME) { - key1State = KEY_WAIT_RELEASE; // 完成去抖 - } - } else { - key1State = KEY_IDLE; // 回到 IDLE - } - break; + case KEY_DOWN: + if (keyInput == 0) + { + if (sys_get_tick() - key1Timer >= DEBOUNCE_TIME) + { + key1State = KEY_WAIT_RELEASE; // 完成去抖 + } + } + else + { + key1State = KEY_IDLE; // 回到 IDLE + } + break; - case KEY_WAIT_RELEASE: - if (keyInput == 1) { // 剛放開 - key1Timer = sys_get_tick(); - key1State = KEY_IDLE; - key1_action = 1; // 執行動作 - Key_Action(); - } - break; - } + case KEY_WAIT_RELEASE: + if (keyInput == 1) + { // 剛放開 + key1Timer = sys_get_tick(); + key1State = KEY_IDLE; + key1_action = 1; // 執行動作 + Key_Action(); + } + break; + } } //------------------------------------------------------------------------- void Key_Action() { - if (power_on_cmd == 0) - { - power_on_cmd = 1; - //A_Para_Reset(); - //Power_On(); - } - else - { - power_on_cmd = 0; - Power_Off(); - } + if (power_on_cmd == 0) + { + power_on_cmd = 1; + // A_Para_Reset(); + // Power_On(); + } + else + { + power_on_cmd = 0; + Power_Off(); + } } //------------------------------------------------------------------------- void Power_On() { - power_on_cmd = 1; - llc_pwm_enable(); // LLC ON first - pfc_pwm_enable(); + power_on_cmd = 1; + llc_pwm_enable(); // LLC ON first + pfc_pwm_enable(); } //------------------------------------------------------------------------- void Power_Off() { - power_on_cmd = 0; - pfc_pwm_disable(); // PFC OF first - sys_delay(2000); // discharge - llc_pwm_disable(); - sys_state = STATE_PAUSE; - A_Para_Reset(); + power_on_cmd = 0; + pfc_pwm_disable(); // PFC OF first + sys_delay(2000); // discharge + llc_pwm_disable(); + sys_state = STATE_PAUSE; + A_Para_Reset(); } //=================================================================================== void llc_set_period(uint16_t val) { - if (val > LLC_PERIOD_MAX) val = LLC_PERIOD_MAX; // 可以小,不能過大 - EPWM->ARR = val; - EPWM->CCR1 = val>>1; + if (val > LLC_PERIOD_MAX) val = LLC_PERIOD_MAX; // 可以小,不能過大 + EPWM->ARR = val; + EPWM->CCR1 = val >> 1; } //=================================================================================== void pfc_set_duty(uint16_t val) { - if (val > PFC_DUTY_MAX) val = PFC_DUTY_MAX; - if (val < PFC_DUTY_MIN) val = PFC_DUTY_MIN; - TIM2->CCR1 = val; + if (val > PFC_DUTY_MAX) val = PFC_DUTY_MAX; + if (val < PFC_DUTY_MIN) val = PFC_DUTY_MIN; + TIM2->CCR1 = val; } //=================================================================================== void llc_pwm_enable() { - REG_SET_BITS(EPWM->CCER, TIM_CCER_CC1E_Msk | TIM_CCER_CC1NE_Msk); + REG_SET_BITS(EPWM->CCER, TIM_CCER_CC1E_Msk | TIM_CCER_CC1NE_Msk); } //=================================================================================== void llc_pwm_disable() { - REG_CLR_BITS(EPWM->CCER, TIM_CCER_CC1E_Msk | TIM_CCER_CC1NE_Msk); + REG_CLR_BITS(EPWM->CCER, TIM_CCER_CC1E_Msk | TIM_CCER_CC1NE_Msk); } //=================================================================================== void pfc_pwm_enable() { - REG_SET_BITS(TIM2->CCER, TIM_CCER_CC1E_Msk); + REG_SET_BITS(TIM2->CCER, TIM_CCER_CC1E_Msk); } //=================================================================================== void pfc_pwm_disable() { - REG_CLR_BITS(TIM2->CCER, TIM_CCER_CC1E_Msk); + REG_CLR_BITS(TIM2->CCER, TIM_CCER_CC1E_Msk); } //====================================================================================== void Vol_Loop_PFC_1P1Z(void) // TEST OK { - // 1. 計算誤差 - int32_t vbus_err_n = (int32_t)vbus_set - (int32_t)vbus_avg; + // 1. 計算誤差 + int32_t vbus_err_n = (int32_t)vbus_set - (int32_t)vbus_avg; - // --- 策略 A:動態增益調整 --- - int32_t b0 = 135; - int32_t b1 = -134; + // --- 策略 A:動態增益調整 --- + int32_t b0 = 135; + int32_t b1 = -134; - if (vbus_err_n > 30 || vbus_err_n < -30) - { - // 大誤差時(通常是剛啟動或大跳載),強化參數加快反應 - //b0 = 250; - //b1 = -240; - b0 = 180; // 稍微調降強增益的力道 - b1 = -175; - } - // --- 策略 B:接近目標時微調零點 (抗過衝) --- - else if (vbus_err_n < 20 && vbus_err_n > -20) - { - // 當誤差縮小時,稍微減小 b0 與 b1 的差值,降低積分衝力 - b0 = 120; - b1 = -119; // 如果不能用浮點數,請維持 120 / -119,增加阻尼感 - } + if (vbus_err_n > 30 || vbus_err_n < -30) + { + // 大誤差時(通常是剛啟動或大跳載),強化參數加快反應 + // b0 = 250; + // b1 = -240; + b0 = 180; // 稍微調降強增益的力道 + b1 = -175; + } + // --- 策略 B:接近目標時微調零點 (抗過衝) --- + else if (vbus_err_n < 20 && vbus_err_n > -20) + { + // 當誤差縮小時,稍微減小 b0 與 b1 的差值,降低積分衝力 + b0 = 120; + b1 = -119; // 如果不能用浮點數,請維持 120 / -119,增加阻尼感 + } - // 2. 差分方程計算 - int64_t acc = (int64_t)b0 * vbus_err_n; - acc += (int64_t)b1 * vbus_err_1; - acc += ((int64_t)16384 * vbus_comp_1) >> 14; // 16384 = 1 >> 14 + // 2. 差分方程計算 + int64_t acc = (int64_t)b0 * vbus_err_n; + acc += (int64_t)b1 * vbus_err_1; + acc += ((int64_t)16384 * vbus_comp_1) >> 14; // 16384 = 1 >> 14 - int32_t y_n = (int32_t)acc; + int32_t y_n = (int32_t)acc; #if 0 // 有問題 // --- 策略 C:軟限制抗過衝 (Soft Clamping) --- @@ -359,75 +371,77 @@ void Vol_Loop_PFC_1P1Z(void) // TEST OK } #endif - // 3. 輸出限幅執行 - if (y_n > 8847360) y_n = 8847360; // 540 << 14 - else if (y_n < 196608) y_n = 196608; // 12 << 14 + // 3. 輸出限幅執行 + if (y_n > 8847360) + y_n = 8847360; // 540 << 14 + else if (y_n < 196608) + y_n = 196608; // 12 << 14 - // 4. 更新狀態變數 - vbus_err_1 = vbus_err_n; - vbus_comp_1 = y_n; + // 4. 更新狀態變數 + vbus_err_1 = vbus_err_n; + vbus_comp_1 = y_n; - // 5. 輸出 Duty >> 14 - if (sys_state == STATE_PFC_SOFT_START) // 緩啟動期間直接控制 DUTY - TIM2->CCR1 = (vbus_comp_1 >> 14); // 0~540 + // 5. 輸出 Duty >> 14 + if (sys_state == STATE_PFC_SOFT_START) // 緩啟動期間直接控制 DUTY + TIM2->CCR1 = (vbus_comp_1 >> 14); // 0~540 - // 6. 輸出 comp >> 9 (變大 32 倍) (MAX ~ 18000) (540*32=17280)差不多,>> 9 應該是對的 - if (sys_state == STATE_RUN_NORMAL) // 正常工作時間輸出 COMP 值 - vbus_comp2 = (vbus_comp_1 >> 9); + // 6. 輸出 comp >> 9 (變大 32 倍) (MAX ~ 18000) (540*32=17280)差不多,>> 9 應該是對的 + if (sys_state == STATE_RUN_NORMAL) // 正常工作時間輸出 COMP 值 + vbus_comp2 = (vbus_comp_1 >> 9); } //========================================================================== // Cr 1P1Z 回授,做負載驟變補償,執行頻率 10KHZ // 抓取 vcr 的動態變化趨勢,並在穩態時回歸平靜 void Load_Loop_1P1Z(void) { - int32_t x0; - int64_t temp_y0; // 使用 64 位元暫存,完全避免 32 位元相乘時溢位 - int32_t y0; + int32_t x0; + int64_t temp_y0; // 使用 64 位元暫存,完全避免 32 位元相乘時溢位 + int32_t y0; - // 1. 讀取當前 vcr - x0 = vcr; + // 1. 讀取當前 vcr + x0 = vcr; - // 2. 執行 1P1Z 差分方程計算: - temp_y0 = ( (int64_t)CR_1P1Z_B0_Q14 * x0 ) - + ( (int64_t)CR_1P1Z_B1_Q14 * vcr_x1_q14 ) - - ( (int64_t)CR_1P1Z_A1_Q14 * vcr_y1_q14 ); + // 2. 執行 1P1Z 差分方程計算: + temp_y0 = ((int64_t)CR_1P1Z_B0_Q14 * x0) + ((int64_t)CR_1P1Z_B1_Q14 * vcr_x1_q14) - ((int64_t)CR_1P1Z_A1_Q14 * vcr_y1_q14); - // 將 Q28 格式還原回 Q14 格式(右移 14 位元 - y0 = (int32_t)(temp_y0 >> 14); + // 將 Q28 格式還原回 Q14 格式(右移 14 位元 + y0 = (int32_t)(temp_y0 >> 14); - // 更新歷史狀態變數 (Q14 格式) - vcr_x1_q14 = x0; - vcr_y1_q14 = y0; + // 更新歷史狀態變數 (Q14 格式) + vcr_x1_q14 = x0; + vcr_y1_q14 = y0; - // 定點數安全限幅 (Saturation) - if (y0 > CR_FF_MAX_Q14) y0 = CR_FF_MAX_Q14; // 868352 = 53 duty - else if (y0 > -CR_FF_MIN_Q14) y0 = -CR_FF_MIN_Q14; + // 定點數安全限幅 (Saturation) + if (y0 > CR_FF_MAX_Q14) + y0 = CR_FF_MAX_Q14; // 868352 = 53 duty + else if (y0 > -CR_FF_MIN_Q14) + y0 = -CR_FF_MIN_Q14; - cr_feed_forward_output_q14 = y0; + cr_feed_forward_output_q14 = y0; } //======================================================================== __attribute__((always_inline)) static inline void Cur_Loop_PFC_2P2Z(void) // 優化後 3.65us { - if (sys_state != STATE_RUN_NORMAL) return; + if (sys_state != STATE_RUN_NORMAL) return; - // 1. 取得回授與計算誤差 - int32_t local_vbus_comp2 = vbus_comp2; - int32_t local_vac_avg1 = vac_avg1; + // 1. 取得回授與計算誤差 + int32_t local_vbus_comp2 = vbus_comp2; + int32_t local_vac_avg1 = vac_avg1; - // 電流採樣處理 - int32_t local_iac = 3840 - iac; // OPA 電路的關係,實際值為 CURR_OFFSET - ADC - if (local_iac < 0) local_iac = 0; // 避免負值 + // 電流採樣處理 + int32_t local_iac = 3840 - iac; // OPA 電路的關係,實際值為 CURR_OFFSET - ADC + if (local_iac < 0) local_iac = 0; // 避免負值 - // 計算電流給定值 - int32_t local_iac_set = (local_vac_avg1 * local_vbus_comp2) / 5700; + // 計算電流給定值 + int32_t local_iac_set = (local_vac_avg1 * local_vbus_comp2) / 5700; - int32_t local_iac_err_0 = local_iac_set - local_iac; // err = set - meas - //local_iac_err_0 <<= 14; + int32_t local_iac_err_0 = local_iac_set - local_iac; // err = set - meas + // local_iac_err_0 <<= 14; - //print1 = local_iac_err_0; - //print2 = local_iac_set; + // print1 = local_iac_err_0; + // print2 = local_iac_set; - // 2. 2P2Z 運算 (Fixed-point Q14) + // 2. 2P2Z 運算 (Fixed-point Q14) #if 0 // (會振,改參數) int64_t acc1 = ((int64_t)598 * local_iac_err_0) // < 12 bit + ((int64_t)-64 * iac_err_1) @@ -440,267 +454,327 @@ __attribute__((always_inline)) static inline void Cur_Loop_PFC_2P2Z(void) // 優 //print3 = acc2; #endif -#if 1 // - int64_t acc1 = ((int64_t)377 * local_iac_err_0) // < 12 bit - + ((int64_t)-585 * iac_err_1) - + ((int64_t)215 * iac_err_2); - //print2 = (int32_t)acc1; - acc1 <<= 15; // +#if 0 + int64_t acc1 = ((int64_t)377 * local_iac_err_0) // < 12 bit + + ((int64_t)-585 * iac_err_1) + ((int64_t)215 * iac_err_2); + // print2 = (int32_t)acc1; + acc1 <<= 15; // - int64_t acc2 = -((int64_t)-20921 * iac_comp_1); // y[n-1] - acc2 -= ((int64_t)4545 * iac_comp_2); // y[n-2] - //print3 = acc2; + int64_t acc2 = -((int64_t)-20921 * iac_comp_1); // y[n-1] + acc2 -= ((int64_t)4545 * iac_comp_2); // y[n-2] + // print3 = acc2; #endif - acc1 += acc2; +#if 1 + struct bode_plot_param_t *bplot_p = &bode_plot_param; + int64_t acc1 = ((int64_t)bplot_p->b0 * local_iac_err_0) + ((int64_t)bplot_p->b1 * iac_err_1) + ((int64_t)bplot_p->b2 * iac_err_2); - int32_t y_n = acc1 >> 14; + int64_t acc2 = -((int64_t)bplot_p->a1 * iac_comp_1); // y[n-1] + acc2 -= ((int64_t)bplot_p->a2 * iac_comp_2); // y[n-2] +#endif - // 限制極限值 - if (y_n > 8847360) y_n = 8847360; // 540 << 14 (回存原值,不是縮小後的) - //if (y_n > 3276800) y_n = 3276800; // 200 << 14 - else if (y_n < 196608) y_n = 196608; // 12 << 14 (最小輸出會變成 0 ??) + acc1 += acc2; - //if (y_n > 141557760) y_n = 141557760; // 8640 << 14 - //else if (y_n < 0) y_n = 0; + int32_t y_n = acc1 >> 14; - //print2 = y_n; - // 更新狀態變數 (儲存原始計算值以保留積分能量) - iac_err_2 = iac_err_1; - iac_err_1 = local_iac_err_0; + // 限制極限值 + if (y_n > 8847360) y_n = 8847360; // 540 << 14 (回存原值,不是縮小後的) + // if (y_n > 3276800) y_n = 3276800; // 200 << 14 + else if (y_n < 196608) + y_n = 196608; // 12 << 14 (最小輸出會變成 0 ??) - // 重要:iac_comp_1 儲存 local_temp,確保下一個週期的 a1, a2 運算正確 - iac_comp_2 = iac_comp_1; - iac_comp_1 = y_n; + // if (y_n > 141557760) y_n = 141557760; // 8640 << 14 + // else if (y_n < 0) y_n = 0; - // 4. 硬體 Duty 限幅與輸出 + // print2 = y_n; + // 更新狀態變數 (儲存原始計算值以保留積分能量) + iac_err_2 = iac_err_1; + iac_err_1 = local_iac_err_0; - uint16_t local_duty = (uint16_t)(y_n >> 14); - //uint16_t local_duty = (uint16_t)(y_n >> 18); + // 重要:iac_comp_1 儲存 local_temp,確保下一個週期的 a1, a2 運算正確 + iac_comp_2 = iac_comp_1; + iac_comp_1 = y_n; - if (local_duty > PFC_DUTY_MAX) local_duty = PFC_DUTY_MAX; // MAX = 540 - else if (local_duty < PFC_DUTY_MIN) local_duty = PFC_DUTY_MIN; // MIN = 12 + // 4. 硬體 Duty 限幅與輸出 - TIM2->CCR1 = local_duty; // 有括號,先 >> 14 + uint16_t local_duty = (uint16_t)(y_n >> 14); + // uint16_t local_duty = (uint16_t)(y_n >> 18); - //count1++; - // ------------------------------------------- - // 5. data log - #if DATA_LOG - count_down--; - if (count_down < 1000) - { - tx_buf1[buf_idx] = local_iac_err_0; // y[n] - tx_buf2[buf_idx] = acc; // x[n] - //tx_buf3[buf_idx] = local_iac_err_0; - //tx_buf4[buf_idx] = local_duty; - buf_idx++; - } + if (local_duty > PFC_DUTY_MAX) + local_duty = PFC_DUTY_MAX; // MAX = 540 + else if (local_duty < PFC_DUTY_MIN) + local_duty = PFC_DUTY_MIN; // MIN = 12 - if (buf_idx >= (BUF_SIZE-1)) - { - is_full = 1; - pfc_pwm_disable(); - sys_state = STATE_PAUSE; - } - #endif - // ------------------------------------------- + TIM2->CCR1 = local_duty; // 有括號,先 >> 14 + +// count1++; +// ------------------------------------------- +// 5. data log +#if DATA_LOG + count_down--; + if (count_down < 1000) + { + tx_buf1[buf_idx] = local_iac_err_0; // y[n] + tx_buf2[buf_idx] = acc; // x[n] + // tx_buf3[buf_idx] = local_iac_err_0; + // tx_buf4[buf_idx] = local_duty; + buf_idx++; + } + + if (buf_idx >= (BUF_SIZE - 1)) + { + is_full = 1; + pfc_pwm_disable(); + sys_state = STATE_PAUSE; + } +#endif + // ------------------------------------------- } //============================================================================ void Vol_Loop_LLC(void) // 測試可工作 { - static uint8_t last_gpio = 0; - static uint16_t toggle_cnt = 0; - static uint16_t stable_timer = 0; + static uint8_t last_gpio = 0; + static uint16_t toggle_cnt = 0; + static uint16_t stable_timer = 0; - // 1. 讀取 GPIO 回授 - uint8_t gpio = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12); + // 1. 讀取 GPIO 回授 + uint8_t gpio = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12); - // 2. 判斷是否發生翻轉 (判斷是否在平衡點附近跳動) - if (gpio != last_gpio) { - toggle_cnt++; - last_gpio = gpio; - stable_timer = 0; // 只要有翻轉,就重置穩定計時器 - } else { - // 如果 GPIO 長時間沒翻轉,說明離目標還很遠 - if (stable_timer < 1000) stable_timer++; + // 2. 判斷是否發生翻轉 (判斷是否在平衡點附近跳動) + if (gpio != last_gpio) + { + toggle_cnt++; + last_gpio = gpio; + stable_timer = 0; // 只要有翻轉,就重置穩定計時器 + } + else + { + // 如果 GPIO 長時間沒翻轉,說明離目標還很遠 + if (stable_timer < 1000) stable_timer++; + } + + // 3. 根據翻轉頻率決定步長 + uint16_t current_step; + if (toggle_cnt > STABLE_THRES) + { + // 頻繁翻轉:進入「死區」或「極小步長」模式 + current_step = 0; // 設為 0 表示進入死區,完全停止震盪 + + // 為了防止永久卡死,當連續相同狀態一段時間後再恢復調整 + if (stable_timer > 50) toggle_cnt = 0; + } + else + { + // 距離目標尚遠:根據 stable_timer 決定快慢 + current_step = (stable_timer > 100) ? STEP_FAST : STEP_SLOW; + } + + // 4. 執行調整 + if (current_step > 0) + { + if (gpio == 1) + { + if (digital_vcomp + current_step <= digi_vcomp_max) + digital_vcomp += current_step; } - - // 3. 根據翻轉頻率決定步長 - uint16_t current_step; - if (toggle_cnt > STABLE_THRES) { - // 頻繁翻轉:進入「死區」或「極小步長」模式 - current_step = 0; // 設為 0 表示進入死區,完全停止震盪 - - // 為了防止永久卡死,當連續相同狀態一段時間後再恢復調整 - if (stable_timer > 50) toggle_cnt = 0; - } else { - // 距離目標尚遠:根據 stable_timer 決定快慢 - current_step = (stable_timer > 100) ? STEP_FAST : STEP_SLOW; + else + { + if (digital_vcomp > (1000 + current_step)) + digital_vcomp -= current_step; } + } - // 4. 執行調整 - if (current_step > 0) { - if (gpio == 1) { - if (digital_vcomp + current_step <= digi_vcomp_max) - digital_vcomp += current_step; - } else { - if (digital_vcomp > (1000 + current_step)) - digital_vcomp -= current_step; - } - } + // 5. 計算並更新 ARR (原本的邏輯) + uint32_t new_arr = LLC_PERIOD_MIN + (digital_vcomp >> LLC_COMP_GAIN_BIT); - // 5. 計算並更新 ARR (原本的邏輯) - uint32_t new_arr = LLC_PERIOD_MIN + (digital_vcomp >> LLC_COMP_GAIN_BIT); + if (new_arr > LLC_PERIOD_MAX) new_arr = LLC_PERIOD_MAX; + if (new_arr < LLC_PERIOD_MIN) new_arr = LLC_PERIOD_MIN; - if (new_arr > LLC_PERIOD_MAX) new_arr = LLC_PERIOD_MAX; - if (new_arr < LLC_PERIOD_MIN) new_arr = LLC_PERIOD_MIN; - - if (EPWM->ARR != new_arr) { - EPWM->ARR = new_arr; - EPWM->CCR1 = (new_arr >> 1); - } + if (EPWM->ARR != new_arr) + { + EPWM->ARR = new_arr; + EPWM->CCR1 = (new_arr >> 1); + } } //================================================================================= __INTERRUPT void isr_adc_handle(void) { - SAVE_IRQ_CSR_CONTEXT(); - ADC_ClearITFlag(ADC0); + SAVE_IRQ_CSR_CONTEXT(); + ADC_ClearITFlag(ADC0); - //GPIO_SetBits(GPIOA, GPIO_Pin_06); + // GPIO_SetBits(GPIOA, GPIO_Pin_06); - tim0_trigger = 1; + tim0_trigger = 1; - // get ADC value - iac = ADC0->DAT9_b.DATA; // PA7, AIN9 - vac = ADC0->DAT7_b.DATA; // PA13, AIN7 - vbus = ADC0->DAT4_b.DATA; // PA10, AIN4 - vcr = ADC0->DAT5_b.DATA; // PA11, AIN5 + // get ADC value + iac = ADC0->DAT9_b.DATA; // PA7, AIN9 + vac = ADC0->DAT7_b.DATA; // PA13, AIN7 + vbus = ADC0->DAT4_b.DATA; // PA10, AIN4 + vcr = ADC0->DAT5_b.DATA; // PA11, AIN5 - Cur_Loop_PFC_2P2Z(); // current loop + Cur_Loop_PFC_2P2Z(); // current loop - //GPIO_ResetBits(GPIOA, GPIO_Pin_06); + // GPIO_ResetBits(GPIOA, GPIO_Pin_06); - RESTORE_IRQ_CSR_CONTEXT(); - return; + RESTORE_IRQ_CSR_CONTEXT(); + return; } //============================================================================ void reset_pid_parameters(void) { - vbus_int = 0; vbus_comp = 1000; + vbus_int = 0; + vbus_comp = 1000; - iac_err_0 = 0; - iac_err_1 = 0; - iac_err_2 = 0; - iac_comp = 0; - iac_comp_1 = 0; - iac_comp_2 = 0; + iac_err_0 = 0; + iac_err_1 = 0; + iac_err_2 = 0; + iac_comp = 0; + iac_comp_1 = 0; + iac_comp_2 = 0; - digital_vcomp = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT; + digital_vcomp = (LLC_PERIOD_MAX - LLC_PERIOD_MIN) << LLC_COMP_GAIN_BIT; } //============================================================================== void Handle_UART_Monitor(void) { - if (sys_get_tick() - msg_timer >= 1000) // msg_out = 1, print - { - //printf("%d %d %d\r\n", vac_pk1, vac_pk2, is_brown_in); - //printf("%d %d %d %d %d %d", power_on_cmd, sys_state, vbus_comp2, print1, print2, print3); - printf("%d %d %d", power_on_cmd, sys_state, vbus_comp2); - // 電壓環輸出最大 COMP,但是電流環輸出最小 DUTY - msg_timer = sys_get_tick(); - } - // iac 零點大約 3640 ~ 3680 + if (sys_get_tick() - msg_timer >= 1000) // msg_out = 1, print + { + // printf("%d %d %d\r\n", vac_pk1, vac_pk2, is_brown_in); + // printf("%d %d %d %d %d %d", power_on_cmd, sys_state, vbus_comp2, print1, print2, print3); + printf("%d %d %d", power_on_cmd, sys_state, vbus_comp2); + // 電壓環輸出最大 COMP,但是電流環輸出最小 DUTY + msg_timer = sys_get_tick(); + } + // iac 零點大約 3640 ~ 3680 } //================================================================================ void Handle_UART_Log(void) { - for (int i = 0; i < BUF_SIZE; i++) - { - //printf("%d:%d:%d:%d\r\n", tx_buf1[i], tx_buf2[i], tx_buf3[i], tx_buf4[i]); - printf("%d:%d\r\n", tx_buf1[i], tx_buf2[i]); - //printf("%d\r\n", tx_buf1[i]); - sys_delay(5); - } - is_full = 0; // [重要] 列印完務必清除旗標,否則會死循環 - buf_idx = 0; // 重置索引 + for (int i = 0; i < BUF_SIZE; i++) + { + // printf("%d:%d:%d:%d\r\n", tx_buf1[i], tx_buf2[i], tx_buf3[i], tx_buf4[i]); + printf("%d:%d\r\n", tx_buf1[i], tx_buf2[i]); + // printf("%d\r\n", tx_buf1[i]); + sys_delay(5); + } + is_full = 0; // [重要] 列印完務必清除旗標,否則會死循環 + buf_idx = 0; // 重置索引 } //================================================================================ void Vac_Peak_Detector(void) { - // 1. 峰值追蹤 (Peak Detector):只要不在過零區,就持續抓最大值 - if (vac >= VAC_ZERO) - { - is_zero_crossing = 0; - last_is_zero_crossing = 0; - if (vac > vac_pk1) vac_pk1 = vac; // 只有比目前紀錄大才更新,確保 vac_pk1 停在波峰 - } - else - { - // 2. 進入過零區 (vac < 400) - is_zero_crossing = 1; - // 3. 邊緣觸發:只在從「非過零」進入「過零」的瞬間交接數據 - if (last_is_zero_crossing == 0 && vac_pk1 > VAC_ZERO_RISE) - { - vac_pk2 = vac_pk1; // 這裡的 vac_pk1 必定是剛才半周抓到的最高點 + // 1. 峰值追蹤 (Peak Detector):只要不在過零區,就持續抓最大值 + if (vac >= VAC_ZERO) + { + is_zero_crossing = 0; + last_is_zero_crossing = 0; + if (vac > vac_pk1) vac_pk1 = vac; // 只有比目前紀錄大才更新,確保 vac_pk1 停在波峰 + } + else + { + // 2. 進入過零區 (vac < 400) + is_zero_crossing = 1; + // 3. 邊緣觸發:只在從「非過零」進入「過零」的瞬間交接數據 + if (last_is_zero_crossing == 0 && vac_pk1 > VAC_ZERO_RISE) + { + vac_pk2 = vac_pk1; // 這裡的 vac_pk1 必定是剛才半周抓到的最高點 - // --- 新增 Brown-in / Brown-out 判斷邏輯 --- - if (is_brown_in == 0) - { - // 目前處於關閉狀態,檢查是否達到啟動門檻 - if (vac_pk2 >= VOLT_BROWN_IN) is_brown_in = 1; // 執行 Brown-in - } - else - { - // 目前處於啟動狀態,檢查是否低於欠壓門檻 - if (vac_pk2 < VOLT_BROWN_OUT) is_brown_in = 0; // 執行 Brown-out - } + // --- 新增 Brown-in / Brown-out 判斷邏輯 --- + if (is_brown_in == 0) + { + // 目前處於關閉狀態,檢查是否達到啟動門檻 + if (vac_pk2 >= VOLT_BROWN_IN) is_brown_in = 1; // 執行 Brown-in + } + else + { + // 目前處於啟動狀態,檢查是否低於欠壓門檻 + if (vac_pk2 < VOLT_BROWN_OUT) is_brown_in = 0; // 執行 Brown-out + } - vac_pk1 = 0; // 交接完後立即清零,為下半周做準備 - last_is_zero_crossing = 1; // 剛過上升緣 - } - } + vac_pk1 = 0; // 交接完後立即清零,為下半周做準備 + last_is_zero_crossing = 1; // 剛過上升緣 + } + } +} + +static void uart_rx_task(void) +{ + // RX timeout + if (g_rx_idx > 0 && !g_rx_ready) + { + if (sys_get_tick() - g_rx_last_tick >= UART_RX_TIMEOUT_MS) + { + UART_ResetRxFIFO(UART0); + g_rx_idx = 0; + g_rx_len = 0; + g_rx_ready = 0; + } + } + + if (!is_rx_frame_ready()) + return; + + char cmd_buf[UART_RX_BUF_SIZE]; + + uart_rx_getline(cmd_buf, sizeof(cmd_buf)); + msg("RX: %s\r\n", cmd_buf); + uart_cmd_parse(cmd_buf, sizeof(cmd_buf)); } //============================================================================= // Public Function Definition //============================================================================= int main(void) { - // 基礎硬體底層設定 (HIRC 60MHz, GPIO, ADC 採樣率 1Msps) [cite: 55, 127, 184] - SYS_Config(); + struct bode_plot_param_t *bplot_p = &bode_plot_param; - vbus_comp2 = 4000; - sys_state = STATE_RUN_NORMAL; - pfc_pwm_enable(); - pfc_running = 1; + // 基礎硬體底層設定 (HIRC 60MHz, GPIO, ADC 採樣率 1Msps) [cite: 55, 127, 184] + SYS_Config(); - // main loop - while(1) + bode_plot_param_read_from_flash(bplot_p, FLASH_PROG_ADDR_USER_CALI); + + vbus_comp2 = 4000; + sys_state = STATE_RUN_NORMAL; + pfc_pwm_enable(); + pfc_running = 1; + + // main loop + while (1) + { + uart_rx_task(); + + // 核心定時觸發:100kHz (由 TIMER0 旗標觸發) [cite: 318] + if (tim0_trigger == 1) { - // 核心定時觸發:100kHz (由 TIMER0 旗標觸發) [cite: 318] - if (tim0_trigger == 1) - { - tim0_trigger = 0; + tim0_trigger = 0; - // 高速信號濾波 (簡易位移算法減少算力消耗) --- - vac_avg1 = (vac_avg1 - (vac_avg1 >> 3)) + (vac >> 3); // for current loop - vbus_avg = (vbus_avg - (vbus_avg >> 4)) + (vbus >> 4); // for voltage loop - // 系統安全監控 (軟體第二道防護) - if (vbus > vbus_ovp) { sys_state = STATE_FAULT; Power_Off(); } // vbus ovp - if (vac_pk2 > 2600) { sys_state = STATE_FAULT; Power_Off(); } // vac over voltage - if (power_on_cmd == 0 && pfc_running == 1) Power_Off(); + // 高速信號濾波 (簡易位移算法減少算力消耗) --- + vac_avg1 = (vac_avg1 - (vac_avg1 >> 3)) + (vac >> 3); // for current loop + vbus_avg = (vbus_avg - (vbus_avg >> 4)) + (vbus >> 4); // for voltage loop + // 系統安全監控 (軟體第二道防護) + if (vbus > vbus_ovp) + { + sys_state = STATE_FAULT; + Power_Off(); + } // vbus ovp + if (vac_pk2 > 2600) + { + sys_state = STATE_FAULT; + Power_Off(); + } // vac over voltage + if (power_on_cmd == 0 && pfc_running == 1) Power_Off(); - Vac_Peak_Detector(); // VAC 峰值偵測 + Vac_Peak_Detector(); // VAC 峰值偵測 - if (sys_get_tick() > 100 && power_on_cmd == 1 && is_zero_crossing == 1) - { - sys_state = STATE_RUN_NORMAL; - if (pfc_running == 0) - { - pfc_pwm_enable(); - pfc_running = 1; - } - } + if (sys_get_tick() > 100 && power_on_cmd == 1 && is_zero_crossing == 1) + { + sys_state = STATE_RUN_NORMAL; + if (pfc_running == 0) + { + pfc_pwm_enable(); + pfc_running = 1; + } + } #if 0 // --- 2. 核心狀態機邏輯 ----------------------------------------------------------------------- @@ -819,22 +893,31 @@ int main(void) } // switch case #endif + } // if tim0_trigger - } // if tim0_trigger + // --- 3. 非即時任務 (UI、通訊、Data Log) --- + Key1_Scan(); - // --- 3. 非即時任務 (UI、通訊、Data Log) --- - Key1_Scan(); +#if DATA_LOG + if (is_full == 1) Handle_UART_Log(); // 利用 PEC930 UART 輸出數據 [cite: 105, 336] +#endif - #if DATA_LOG - if (is_full == 1) Handle_UART_Log(); // 利用 PEC930 UART 輸出數據 [cite: 105, 336] - #endif +#if DATA_MONITOR + Handle_UART_Monitor(); +#endif - #if DATA_MONITOR - Handle_UART_Monitor(); - #endif + } // while -------------------------------------------------------------------- - } // while -------------------------------------------------------------------- - - return 0; + return 0; } +#if 0 +#include "app.h" + +int main(void) +{ + app(); + + return 0; +} +#endif \ No newline at end of file