From a4ebbbbabc06e67c0413647455775fb39f82fee2 Mon Sep 17 00:00:00 2001 From: Roy_01 Date: Wed, 1 Apr 2026 13:20:13 +0800 Subject: [PATCH] ui --- .../Examples/template/dds/inc/init.h | 2 + .../Examples/template/dds/inc/isr.h | 2 + .../Examples/template/dds/inc/main.h | 27 + .../Examples/template/dds/src/init.c | 75 +- .../Examples/template/dds/src/isr.c | 11 + .../Examples/template/dds/src/main.c | 53 + .../Profiles/Project_Debug_OpenOCD.launch | 4 +- pec930_sdk-v1.0.1/UI/serial_monitor.html | 1046 +++++++++++++++++ pec930_sdk-v1.0.1/file_implementation_plan.md | 47 + 9 files changed, 1263 insertions(+), 4 deletions(-) create mode 100644 pec930_sdk-v1.0.1/UI/serial_monitor.html create mode 100644 pec930_sdk-v1.0.1/file_implementation_plan.md diff --git a/pec930_sdk-v1.0.1/Examples/template/dds/inc/init.h b/pec930_sdk-v1.0.1/Examples/template/dds/inc/init.h index 5072036..8237157 100644 --- a/pec930_sdk-v1.0.1/Examples/template/dds/inc/init.h +++ b/pec930_sdk-v1.0.1/Examples/template/dds/inc/init.h @@ -21,4 +21,6 @@ void pwm_disable(); void pwm_brake(); void uart_config(); void UART_Send_Wait(UART_Type *pHUart, uint16_t value); +void spi_config(void); +void spi_send_daq_packet(DAQ_Packet_t *pkt); #endif /* INC_INIT_H_ */ diff --git a/pec930_sdk-v1.0.1/Examples/template/dds/inc/isr.h b/pec930_sdk-v1.0.1/Examples/template/dds/inc/isr.h index 8effcac..9fc7b3e 100644 --- a/pec930_sdk-v1.0.1/Examples/template/dds/inc/isr.h +++ b/pec930_sdk-v1.0.1/Examples/template/dds/inc/isr.h @@ -37,6 +37,7 @@ extern "C" extern volatile bool flag_24Khz_timer; extern volatile bool stringComplete; extern volatile char rxBuffer[128]; + extern long ADC_DATA[10]; // ADC 量測資料 (isr.c 填充) //============================================================================= // Private Function Definition //============================================================================= @@ -47,6 +48,7 @@ extern "C" void isr_epwm_handle(void); void isr_adc_handle(void); void isr_uart0_handle(void); + void SPIx_Handler(void); #ifdef __cplusplus } #endif diff --git a/pec930_sdk-v1.0.1/Examples/template/dds/inc/main.h b/pec930_sdk-v1.0.1/Examples/template/dds/inc/main.h index 8e03787..371a4ff 100644 --- a/pec930_sdk-v1.0.1/Examples/template/dds/inc/main.h +++ b/pec930_sdk-v1.0.1/Examples/template/dds/inc/main.h @@ -20,6 +20,8 @@ extern "C" #include "hal_device.h" #include "syslog.h" +#include "hal_spi.h" +#include "hal_crc.h" //============================================================================= // Constant Definition //============================================================================= @@ -54,6 +56,31 @@ extern "C" extern struct dds_param_t dds; + //========================================================================= + // DAQ Packet: 24kHz SPI 資料封包 + // 注意: pack(1) 確保結構無 padding,大小固定 = 34 bytes + //========================================================================= +#pragma pack(push, 1) + typedef struct { + uint16_t header; // 0x55AA 封包頭 + uint32_t timestamp; // 系統微秒時間戳 + int16_t i_u; // U相電流 + int16_t i_v; // V相電流 + int16_t i_w; // W相電流 + uint16_t v_u; // U相電壓 + uint16_t v_v; // V相電壓 + uint16_t v_w; // W相電壓 + uint16_t v_bus; // 母線電壓 + int32_t dds_ftw; // 頻率常數 + uint32_t dds_amp; // 電壓倍率常數 + int16_t error_val; // 狀態碼/誤差值 + uint16_t crc16; // 硬體 CRC 校驗碼 + } DAQ_Packet_t; +#pragma pack(pop) + + // send_daq_enabled: test_data:1 啟動, test_data:0 停止 + extern volatile bool send_daq_enabled; + #ifdef __cplusplus } #endif diff --git a/pec930_sdk-v1.0.1/Examples/template/dds/src/init.c b/pec930_sdk-v1.0.1/Examples/template/dds/src/init.c index 31343b8..70fbda3 100644 --- a/pec930_sdk-v1.0.1/Examples/template/dds/src/init.c +++ b/pec930_sdk-v1.0.1/Examples/template/dds/src/init.c @@ -35,13 +35,14 @@ void SYS_Config() sys_delay(3000); /* Disable ICE I/O */ - SYSCFG_SetICEPin2NormalIO(true); + //SYSCFG_SetICEPin2NormalIO(true); gpio_config(); opa_config(); adc_config(); pwm_config(); uart_config(); + spi_config(); /* SPI Master 初始化,必須在 gpio_config 之後呼叫 */ __enable_irq(); } @@ -81,7 +82,23 @@ void gpio_config() GPIO_InitADC.GPIO_Pin = GPIO_Pin_06 | GPIO_Pin_12; GPIO_InitADC.GPIO_Mode = GPIO_Mode_ANAL; GPIO_Init(GPIOA, &GPIO_InitADC); -#if 1 + + //-----------------// + // SPI + // PB0:MISO PA15:MOSI PA14:CLK + //-----------------// + GPIO_InitTypeDef GPIO_InitSPI; + GPIO_InitSPI.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15; + GPIO_InitSPI.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitSPI.GPIO_AF_Mode = GPIO_AF_3; + GPIO_Init(GPIOA, &GPIO_InitSPI); + + GPIO_InitSPI.GPIO_Pin = GPIO_Pin_00; + GPIO_InitSPI.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitSPI.GPIO_AF_Mode = GPIO_AF_3; + GPIO_Init(GPIOB, &GPIO_InitSPI); + +#if 0 //-----------------// // test //-----------------// @@ -263,3 +280,57 @@ void UART_Send_Wait(UART_Type *pHUart, uint16_t value) UART_SendData(pHUart, value); UART_WaitTxFifoEmpty(pHUart); } + +void spi_config(void) +{ + + + SPI_InitTypeDef SPI_InitStruct = { 0 }; + SPI_DeInit(SPI0); + SPI_InitStruct.SPI_Mode = SPI_Mode_Master; + SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; /* 閒置時鐘脅為 Low */ + SPI_InitStruct.SPI_CPHA = SPI_CPHA_Effective; /* 第二個時脈檡取樣 */ + SPI_InitStruct.SPI_TxDataSize = SPI_TxDataSize_8b; /* 8-bit 传輸 */ + SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudratePrescaler_4; /* 60MHz/4 = 15MHz SCK */ + SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; + SPI_Init(SPI0, &SPI_InitStruct); + + /* --- 啟動 CRC16 硬體模組 --- */ + CRC_Init(); + + /* Enable SPI */ + SPI_Enable(SPI0); + + sys_irq_attr_t irq_attr = { .trig_mode = SYS_IRQ_TRIGGER_LEVEL, }; + sys_register_IRQ(SPI0_IRQn, SPIx_Handler, &irq_attr); + sys_enable_girq(); + +} + +/* =========================================================================== + * spi_send_daq_packet() + * + * 將 DAQ_Packet_t 封包經 SPI0 逐位元組位元傳輸出去 + * + * 每個 byte 備給 SPI TX FIFO,用 polling 方式等待 TXNFUL + * 封包大小 = sizeof(DAQ_Packet_t) = 34 bytes + * =========================================================================== + */ +void spi_send_daq_packet(DAQ_Packet_t *pkt) +{ + /* 計算 CRC16:涵蓋 header 到 error_val,不含 crc16 欄位 itself */ + uint8_t *raw = (uint8_t *)pkt; + uint32_t payload_len = sizeof(DAQ_Packet_t) - sizeof(uint16_t); /* 排除最後 2 bytes crc */ + pkt->crc16 = (uint16_t)CRC_CalcBlockCRC(raw, (int)payload_len, CRC_Width_CRC16); + + /* 逐 byte polling 發送 */ + uint32_t len = sizeof(DAQ_Packet_t); + for (uint32_t i = 0; i < len; i++) + { + /* 等 TX FIFO 非滿 */ + while (SPI_GetFlagStatus(SPI0, SPI_TXFUL_Flag) != 0); + SPI_SendData(SPI0, raw[i]); + } + /* 等待傳輸完成 */ + while (SPI_GetFlagStatus(SPI0, SPI_BUSY_Flag) != 0); +} diff --git a/pec930_sdk-v1.0.1/Examples/template/dds/src/isr.c b/pec930_sdk-v1.0.1/Examples/template/dds/src/isr.c index 725bfd0..220f7ce 100644 --- a/pec930_sdk-v1.0.1/Examples/template/dds/src/isr.c +++ b/pec930_sdk-v1.0.1/Examples/template/dds/src/isr.c @@ -75,3 +75,14 @@ __INTERRUPT void isr_uart0_handle(void) } } } + +/* SPI IRQ Handler + * DAQ \u5c01\u5305\u7d93 spi_send_daq_packet() \u4ee5 polling \u65b9\u5f0f\u767c\u9001\uff0c\u4e0d\u9700\u8981\u4e2d\u65b7\u9a45\u52d5\u3002 + * SPIx_Handler \u4fdd\u7559\u7a7a\u6a21\uff0c\u4ee5\u5c0d\u61c9 spi_config() \u4e2d\u7684 sys_register_IRQ \u3002 */ +__INTERRUPT void SPIx_Handler(void) +{ + SAVE_IRQ_CSR_CONTEXT(); + /* \u76ee\u524d\u7a7a\u767d\uff1aDAQ SPI \u4f7f\u7528 polling \u6a21\u5f0f\uff0c\u4e0d\u9700\u9032\u884c\u4e2d\u65b7\u64cd\u4f5c */ + RESTORE_IRQ_CSR_CONTEXT(); + return; +} diff --git a/pec930_sdk-v1.0.1/Examples/template/dds/src/main.c b/pec930_sdk-v1.0.1/Examples/template/dds/src/main.c index eb711b2..6aab4ed 100644 --- a/pec930_sdk-v1.0.1/Examples/template/dds/src/main.c +++ b/pec930_sdk-v1.0.1/Examples/template/dds/src/main.c @@ -87,6 +87,9 @@ struct dds_param_t dds = { 0 }; const uint32_t phase_offset[PHASE_COUNT] = { 0, 1398101, 2796203 }; static struct dds_cal_param phase[PHASE_COUNT] = { 0 }; +// DAQ 傳輸啟用旗標: test_data:1 啟動, test_data:0 停止 +volatile bool send_daq_enabled = false; + void dds_pwm_duty_cycle_update(void) { for (int i = 0; i < PHASE_COUNT; i++) @@ -202,6 +205,16 @@ static void cmd_parser(char *data, uint32_t len) printf("Notification disabled.\r\n"); } } + else if (strncmp(data, "test_data:1", 11) == 0) + { + send_daq_enabled = true; + printf("DAQ SPI TX: STARTED (24kHz)\r\n"); + } + else if (strncmp(data, "test_data:0", 11) == 0) + { + send_daq_enabled = false; + printf("DAQ SPI TX: STOPPED\r\n"); + } else { @@ -247,6 +260,46 @@ int main(void) printf("%d tick: %d, %d, %d\n", sys_get_tick(), phase[0].duty, phase[1].duty, phase[2].duty); } + + /* --- DAQ SPI 封包傳輸 (test_data:1 能) --- */ + if (send_daq_enabled) + { + DAQ_Packet_t pkt; + + /* 封包頭 */ + pkt.header = 0x55AA; + + /* 時間戳 (單位: us) + * sys_get_tick() 回傳 ms,乘以 1000 轉換成 us */ + pkt.timestamp = (uint32_t)(sys_get_tick() * 1000u); + + /* 電流: ADC DATA 映射到 i_u, i_v, i_w + * ADC_DATA[0] = U相 (ADC ch6), ADC_DATA[1] = V相 (ADC ch8) + * W 相香用三相平衡對稱推穎: i_w = -(i_u + i_v) */ + pkt.i_u = (int16_t)ADC_DATA[0]; + pkt.i_v = (int16_t)ADC_DATA[1]; + pkt.i_w = (int16_t)(-(ADC_DATA[0] + ADC_DATA[1])); + + /* 電壓: 以 duty cycle 對應當前的輸出電壓似真値 */ + pkt.v_u = phase[0].duty; + pkt.v_v = phase[1].duty; + pkt.v_w = phase[2].duty; + + /* 母線電壓: ADC channel 6 屈 + * (若屬於非其他通道,請改為正確的 ADC_DATA 索引) */ + pkt.v_bus = (uint16_t)ADC_DATA[0]; + + /* DDS 參數 */ + pkt.dds_ftw = (int32_t)dds.set_dds_ftw; + pkt.dds_amp = (uint32_t)dds.set_dds_amp; + + /* 狀態碼: 0 = 正常 */ + pkt.error_val = 0; + + /* 發送 (CRC16 在函式內自動填充) */ + spi_send_daq_packet(&pkt); + } + flag_24Khz_timer = false; } #else diff --git a/pec930_sdk-v1.0.1/Tools/scripts/Profiles/Project_Debug_OpenOCD.launch b/pec930_sdk-v1.0.1/Tools/scripts/Profiles/Project_Debug_OpenOCD.launch index f2a66c4..830c7cb 100644 --- a/pec930_sdk-v1.0.1/Tools/scripts/Profiles/Project_Debug_OpenOCD.launch +++ b/pec930_sdk-v1.0.1/Tools/scripts/Profiles/Project_Debug_OpenOCD.launch @@ -57,7 +57,7 @@ - - + + diff --git a/pec930_sdk-v1.0.1/UI/serial_monitor.html b/pec930_sdk-v1.0.1/UI/serial_monitor.html new file mode 100644 index 0000000..37444a5 --- /dev/null +++ b/pec930_sdk-v1.0.1/UI/serial_monitor.html @@ -0,0 +1,1046 @@ + + + + + +Serial Monitor — PEC930 + + + + + + +
+ + + + +
+
+ 已斷線 +
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ +
+ + + + + +
+ + + +
+ + + + +
+ +
+ + +
+
↵ 自動換行
+
⏱ 時間戳
+
⬇ 自動捲動
+
⌤ 顯示\\n\\r
+
+ +
+ + + + +
+ + +
+ + +
+
+
+ + + + + Monitor Output +
+
+ RX: 0 bytes + TX: 0 bytes + 0 行 +
+
+ +
+
▶ 請點擊「連線」選擇 COM Port(需使用 Chrome / Edge)
+
+ + +
+
+ + +
+
TX>
+ + Line Ending: + + +
+ +
+ + + + + + + diff --git a/pec930_sdk-v1.0.1/file_implementation_plan.md b/pec930_sdk-v1.0.1/file_implementation_plan.md new file mode 100644 index 0000000..bd4dab9 --- /dev/null +++ b/pec930_sdk-v1.0.1/file_implementation_plan.md @@ -0,0 +1,47 @@ +# SPI DAQ Transmission Feature + +This plan outlines the changes needed to support continuous 24kHz transmission of `DAQ_Packet_t` variables via SPI based on the "test_data:" UART command. + +## User Review Required + +> [!WARNING] +> **SPI Pin Conflict with PWM**: The standard SPI pin mapping configures `PA2`, `PA3`, `PA4`, and `PA5`. However, in your application `init.c`, `PA0` to `PA5` are mapped to Alternative Function 6 (`GPIO_AF_6`) as EPWM output for motor control. Please review and clarify which pins you want to use for the SPI bus. If there are alternate routing mappings or a second SPI interface (`SPI1`), please specify them. + +> [!CAUTION] +> **Performance Constraint at 24kHz**: `DAQ_Packet_t` is 34-36 bytes long (depending on packing). Transmitting this much data at 24,000 times per second means pushing an SPI bandwidth of almost 7 Megabits per second (if back-to-back), plus software overhead. If standard polling is used, this could take a significant chunk of time out of the 41.6µs period. Please advise if a high SPI Baudrate or DMA is available/desired. + +## Proposed Changes + +### [MODIFY] main.c +1. Add global runtime flag: `bool send_daq_enabled = false;`. +2. Extend `cmd_parser` to check `strncmp(data, "test_data:1", 11) == 0` (enable) and `test_data:0` (disable). +3. Inside the `flag_24Khz_timer` loop, populate `DAQ_Packet_t` structure (using actual `timestamp`, `phase` duty values mapped to current/voltage, `dds_amp`, `dds_ftw`, etc.). +4. Send the structure bytes over SPI0 if `send_daq_enabled == true`. + +### [MODIFY] main.h +1. Provide the definition of `DAQ_Packet_t`. Ensure it has `#pragma pack(push, 1)` behavior to preserve proper byte alignment for parsing. + +### [MODIFY] init.c +1. Create `spi_config(void)` function taking into account the relevant `GPIO_AF_x` mappings and highest reasonably possible `.SPI_BaudRatePrescaler`. +2. Initialize `SPI0` in Master mode. +3. Call `spi_config()` in `SYS_Config()`. + +### [MODIFY] init.h +1. Add function prototype for `spi_config()`. + +## Open Questions + +1. **Which specific GPIO pins** should be configured for the SPI bus mapping to avoid conflict with `EPWM`? +2. **What data** exactly should be mapping into variables like `i_u`, `v_u`, `v_bus`, `error_val` etc? Currently there are `phase[0].duty` and predefined values. Should we mock these fields, leave them as `0`, or link them to specific placeholders? +3. Can we assume **SPI0** in Master mode is perfectly fine for this application? +4. **CRC16 Implementation**: Is the `crc16` field generated by software or a hardware peripheral? + +## Verification Plan + +### Automated/Code Verification +- Compile code to ensure `DAQ_Packet_t` structures are safely populated and no definitions are missing. + +### Manual Verification +- Send `test_data:1` over UART. +- Measure the SPI clock and `MOSI` pin using a logic analyzer to verify data is successfully bursted exactly at the 24kHz rate. +- Parse the resulting values logic analyzer to ensure `DAQ_Packet_t` `crc16` and fields align correctly.