ui
This commit is contained in:
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||
<listEntry value="4"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList context="Context string"/> "/>
|
||||
<stringAttribute key="org.eclipse.embedcdt.debug.gdbjtag.core.PERIPHERALS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <peripherals/> "/>
|
||||
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList context="Context string"> <memoryBlockExpression address="536874960" label="&amp;pkt"/> </memoryBlockExpressionList> "/>
|
||||
<stringAttribute key="org.eclipse.embedcdt.debug.gdbjtag.core.PERIPHERALS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <peripherals> <peripheral name="SPI"/> </peripherals> "/>
|
||||
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
|
||||
</launchConfiguration>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
Reference in New Issue
Block a user