超声波信号采集与发射设计
auto-layout-249bbf96-74ec-46e3-abf4-b9b06aade4ab。Table
| Function | MCU pin | Net | Direction | Notes |
|---|---|---|---|---|
| AD9833 SCLK | PA5 | DDS_SPI_SCLK | Output | SPI clock to U2 SCLK |
| AD9833 SDATA | PA7 | DDS_SPI_MOSI | Output | SPI MOSI to U2 SDATA |
| AD9833 FSYNC | PA4 | DDS_SPI_CS | Output | Active-low frame sync |
| AD9833 MCLK | PA8 | DDS_MCLK | Output | Use MCO or timer clock; AD9833 output frequency depends on this clock |
| AD7606 SCLK | PB13 | ADC_SPI_SCLK | Output | SPI clock to U3 RD/SCLK |
| AD7606 CS | PB12 | ADC_SPI_CS | Output | Active-low ADC chip select |
| AD7606 DOUTA | PB14 | ADC_DOUTA | Input | SPI data input |
| AD7606 DOUTB | PB15 | ADC_DOUTB | Input | Optional second serial data lane |
| AD7606 CONVST | PD0 | ADC_CONVST | Output | Drives CONVST_A and CONVST_B together for simultaneous sampling |
| AD7606 BUSY | PD1 | ADC_BUSY | Input | Conversion busy flag |
| AD7606 RESET | PD2 | ADC_RESET | Output | Reset pulse after power-up |
| TX trigger | PD3 | TX_TRIGGER | Output | Isolated through U4 |
| TX blanking | PD4 | TX_BLANKING | Output | Isolated through U5 |
| HV status | PD5 | HV_STATUS | Input | Isolated feedback through U6 |
| SWDIO | PA13 | SWDIO | Debug | J6 |
| SWCLK | PA14 | SWCLK | Debug | J6 |
| UART TX | PA9 | UART_TX | Output | J6 debug UART |
| UART RX | PA10 | UART_RX | Input | J6 debug UART |
| Reset | NRST | MCU_RST | Input | J6 reset + pull-up/filter |
| Boot mode | BOOT0 | BOOT0 | Strap | Pulled down for normal boot |
C
#include "stm32f4xx_hal.h" #include <stdint.h> #define DDS_CS_PORT GPIOA #define DDS_CS_PIN GPIO_PIN_4 #define DDS_MCLK_PORT GPIOA #define DDS_MCLK_PIN GPIO_PIN_8 #define ADC_CS_PORT GPIOB #define ADC_CS_PIN GPIO_PIN_12 #define ADC_BUSY_PORT GPIOD #define ADC_BUSY_PIN GPIO_PIN_1 #define ADC_CONVST_PORT GPIOD #define ADC_CONVST_PIN GPIO_PIN_0 #define ADC_RESET_PORT GPIOD #define ADC_RESET_PIN GPIO_PIN_2 #define TX_TRIG_PORT GPIOD #define TX_TRIG_PIN GPIO_PIN_3 #define TX_BLANK_PORT GPIOD #define TX_BLANK_PIN GPIO_PIN_4 #define HV_STATUS_PORT GPIOD #define HV_STATUS_PIN GPIO_PIN_5 SPI_HandleTypeDef hspi1; // AD9833 on PA5/PA7, software CS PA4 SPI_HandleTypeDef hspi2; // AD7606 on PB13/PB14/PB15, software CS PB12 TIM_HandleTypeDef htim_prf; static void dds_write16(uint16_t word) { uint8_t tx[2] = { (uint8_t)(word >> 8), (uint8_t)(word & 0xFF) }; HAL_GPIO_WritePin(DDS_CS_PORT, DDS_CS_PIN, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, tx, 2, HAL_MAX_DELAY); HAL_GPIO_WritePin(DDS_CS_PORT, DDS_CS_PIN, GPIO_PIN_SET); } static void ad9833_set_sine_500khz(uint32_t mclk_hz) { // AD9833 frequency word = fout * 2^28 / MCLK. uint32_t fw = (uint32_t)(((uint64_t)500000UL * 268435456ULL) / mclk_hz); dds_write16(0x2100); // reset + write frequency registers dds_write16(0x4000 | (fw & 0x3FFF)); dds_write16(0x4000 | ((fw >> 14) & 0x3FFF)); dds_write16(0xC000); // phase 0 dds_write16(0x2000); // exit reset, sine output } static void ad7606_reset(void) { HAL_GPIO_WritePin(ADC_RESET_PORT, ADC_RESET_PIN, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(ADC_RESET_PORT, ADC_RESET_PIN, GPIO_PIN_RESET); } static void ad7606_start_conversion(void) { HAL_GPIO_WritePin(ADC_CONVST_PORT, ADC_CONVST_PIN, GPIO_PIN_SET); for (volatile int i = 0; i < 20; ++i) { __NOP(); } HAL_GPIO_WritePin(ADC_CONVST_PORT, ADC_CONVST_PIN, GPIO_PIN_RESET); } static void ad7606_read_two_lanes(uint16_t *douta, uint16_t *doutb, uint8_t count) { // For two-lane serial mode, 64 SCLK cycles read all 8 channels. // This placeholder uses SPI2 RX; exact dual-lane capture may need DMA or GPIO sampling for DOUTB. uint8_t rx[16] = {0}; HAL_GPIO_WritePin(ADC_CS_PORT, ADC_CS_PIN, GPIO_PIN_RESET); HAL_SPI_Receive(&hspi2, rx, count * 2, HAL_MAX_DELAY); HAL_GPIO_WritePin(ADC_CS_PORT, ADC_CS_PIN, GPIO_PIN_SET); for (uint8_t i = 0; i < count; ++i) { douta[i] = ((uint16_t)rx[2*i] << 8) | rx[2*i + 1]; } (void)doutb; } static void fire_burst_window(void) { HAL_GPIO_WritePin(TX_BLANK_PORT, TX_BLANK_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(TX_TRIG_PORT, TX_TRIG_PIN, GPIO_PIN_SET); // 500kHz five-cycle burst is 10us. Use a hardware timer in production. for (volatile int i = 0; i < 1000; ++i) { __NOP(); } HAL_GPIO_WritePin(TX_TRIG_PORT, TX_TRIG_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(TX_BLANK_PORT, TX_BLANK_PIN, GPIO_PIN_RESET); } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI1_Init(); MX_SPI2_Init(); MX_TIM_Init(); HAL_GPIO_WritePin(DDS_CS_PORT, DDS_CS_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(ADC_CS_PORT, ADC_CS_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(TX_TRIG_PORT, TX_TRIG_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(TX_BLANK_PORT, TX_BLANK_PIN, GPIO_PIN_RESET); ad7606_reset(); ad9833_set_sine_500khz(25000000UL); // update if actual MCLK differs while (1) { if (HAL_GPIO_ReadPin(HV_STATUS_PORT, HV_STATUS_PIN) == GPIO_PIN_SET) { fire_burst_window(); } ad7606_start_conversion(); while (HAL_GPIO_ReadPin(ADC_BUSY_PORT, ADC_BUSY_PIN) == GPIO_PIN_SET) {} uint16_t samples_a[8], samples_b[8]; ad7606_read_two_lanes(samples_a, samples_b, 8); HAL_Delay(10); // 100Hz PRF placeholder; replace with hardware timer for deterministic timing } }
Platform and toolchain
Schematic pin mapping
Bring-up sequence
Minimal STM32 HAL skeleton
Notes