STM32F407VET6 Black Board

元器件
开发板
库存 300

介绍

STM32F407VET6 核心板(Black Board),基于 ARM Cortex-M4 内核,带 FPU 和 DSP 指令集,主频 168MHz,512KB Flash、192KB SRAM。板载 8MHz/32.768KHz 晶振,引出全部 GPIO(82个IO口),支持 USB OTG、2×CAN、3×I2C、3×SPI、4×USART、3×ADC、2×DAC、DCMI 摄像头接口、FSMC 并行总线。3.3V 供电,适合图像处理、音频处理、高速通信等高性能应用。

规格参数

参数
ADC3×12位(24通道)
DAC2×12位
SRAM192KB(含64KB CCM)
Flash512KB
主频168MHz
内核ARM Cortex-M4 + FPU + DSP
MCU型号STM32F407VET6
PCB尺寸70mm×55mm
定时器12×16位+2×32位
GPIO数量82(部分5V容忍)
Flash寿命10万次擦写
工作电压1.8V-3.6V
板载晶振8MHz HSE + 32.768KHz LSE
调试接口SWD/JTAG
通信接口USB 2.0 OTG FS/HS、2×CAN 2.0B、3×SPI、3×I2C、4×USART+2×UART、SDIO、DCMI
高级特性FSMC、硬件CRC、RNG

代码例程

STM32F407VET6 Black Board 代码例程.md
# STM32F407VET6 Black Board 代码例程

本文档覆盖 HAL 库、标准库,并特别包含 F407 特色功能:FPU 浮点运算、DSP 库、SDIO、DCMI 摄像头。

---

## 一、STM32CubeIDE / HAL 库例程

### 1.1 系统时钟 168MHz + FPU 使能

```c
/* main.c - F407 168MHz 初始化 + FPU */
#include "main.h"

void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /* 使能 FPU */
    SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2));  // CP10/CP11 完全访问

    /* HSE 8MHz → PLL → 168MHz */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;       // HSE ÷ 8 = 1MHz
    RCC_OscInitStruct.PLL.PLLN = 336;     // × 336 = 336MHz
    RCC_OscInitStruct.PLL.PLLP = 2;       // ÷ 2 = 168MHz (SYSCLK)
    RCC_OscInitStruct.PLL.PLLQ = 7;       // ÷ 7 = 48MHz (USB/SDIO)
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;   // 168MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;    // 42MHz
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;    // 84MHz
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5WS);  // 5等待周期!
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    // ... 外设初始化 ...
    while (1);
}
```

### 1.2 FPU 浮点运算性能对比

```c
/* 对比 FPU 硬浮点与软浮点性能 */
#include "main.h"
#include <math.h>

/* 务必在 Project Settings 中开启 FPU:
   菜单 Project → Properties → C/C++ Build → Settings →
   MCU Settings → Floating-point unit: FPv4-SP-D16
   Floating-point ABI: Hardware implementation (-mfloat-abi=hard)
*/

void FPU_Demo(void)
{
    volatile float a = 3.14159265f;
    volatile float b = 2.71828183f;
    volatile float result;
    volatile uint32_t start, elapsed;

    /* 硬件 FPU 测试:100万次浮点运算 */
    start = DWT->CYCCNT;
    for (uint32_t i = 0; i < 1000000; i++)
    {
        result = sinf(a) * cosf(b) + sqrtf(a * b);
    }
    elapsed = DWT->CYCCNT - start;
    // 在 168MHz 下,通常约 200-300ms 完成

    printf("FPU test: %lu cycles, result=%.6f\r\n", elapsed, (double)result);
}
```

### 1.3 SDIO + FATFS 读写 SD 卡

```c
/* SDIO 4线模式 + FATFS */
#include "main.h"
#include "fatfs.h"

FATFS fs;           // 文件系统对象
FIL fil;            // 文件对象
UINT bw, br;

void SD_Card_Test(void)
{
    FRESULT res;
    char buf[64];

    /* 挂载文件系统 */
    res = f_mount(&fs, "", 1);
    if (res != FR_OK) {
        printf("Mount failed: %d\r\n", res);
        return;
    }

    /* 创建并写入文件 */
    res = f_open(&fil, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);
    if (res == FR_OK) {
        f_puts("Hello from STM32F407 SDIO!\r\n", &fil);
        f_puts("SD card works perfectly.\r\n", &fil);
        f_close(&fil);
        printf("File written OK\r\n");
    }

    /* 读取文件 */
    res = f_open(&fil, "test.txt", FA_READ);
    if (res == FR_OK) {
        f_read(&fil, buf, sizeof(buf) - 1, &br);
        buf[br] = '\0';
        f_close(&fil);
        printf("Read: %s", buf);
    }

    f_mount(NULL, "", 1);  // 卸载
}
```

### 1.4 DCMI + OV7725 摄像头(快照)

```c
/* DCMI 接口抓取一帧到内存 */
#include "main.h"

DCMI_HandleTypeDef hdcmi;
DMA_HandleTypeDef hdma_dcmi;

/* 帧缓冲:QVGA RGB565 = 320×240×2 = 153600 字节 */
#define FRAME_SIZE (320 * 240 * 2)
__attribute__((section(".bss"))) uint8_t frameBuf[FRAME_SIZE];

void DCMI_Init(void)
{
    /* 使能时钟 */
    __HAL_RCC_DCMI_CLK_ENABLE();
    __HAL_RCC_DMA2_CLK_ENABLE();

    hdcmi.Instance = DCMI;
    hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
    hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;
    hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_HIGH;       // 根据摄像头调整
    hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_HIGH;
    hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;
    hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;   // 8位数据模式
    hdcmi.Init.JPEGMode = DCMI_JPEG_DISABLE;
    HAL_DCMI_Init(&hdcmi);

    /* DMA 配置:DCMI → 内存 */
    hdma_dcmi.Instance = DMA2_Stream1;
    hdma_dcmi.Init.Channel = DMA_CHANNEL_1;
    hdma_dcmi.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_dcmi.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_dcmi.Init.MemInc = DMA_MINC_ENABLE;
    hdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_dcmi.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_dcmi.Init.Mode = DMA_CIRCULAR;                  // 循环模式连续抓帧
    hdma_dcmi.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_dcmi);

    __HAL_LINKDMA(&hdcmi, DMA_Handle, hdma_dcmi);
}

void DCMI_StartCapture(void)
{
    HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_CONTINUOUS,
                       (uint32_t)frameBuf, FRAME_SIZE / 4);
}
```

### 1.5 USB VCP(虚拟串口)

```c
/* USB CDC 虚拟串口 - CubeMX 配置 USB_OTG_FS Device Only → CDC */
#include "main.h"
#include "usbd_cdc_if.h"

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_USB_DEVICE_Init();  // CubeMX 自动生成

    while (1)
    {
        /* CDC_Transmit_FS 发送数据到 PC */
        char msg[] = "USB VCP from STM32F407!\r\n";
        CDC_Transmit_FS((uint8_t *)msg, sizeof(msg) - 1);
        HAL_Delay(1000);
    }
}
```

---

## 二、Keil MDK / 标准外设库例程

### 2.1 168MHz 时钟 + FPU(标准库)

```c
#include "stm32f4xx.h"

void RCC_Configuration(void)
{
    /* 使能 FPU */
    SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2));

    /* HSE ON */
    RCC_HSEConfig(RCC_HSE_ON);
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);

    /* PLL: 8MHz ÷ 8 × 336 ÷ 2 = 168MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE, 8, 336, 2, 7);
    RCC_PLLCmd(ENABLE);
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

    /* Flash 5 等待周期 */
    FLASH_SetLatency(FLASH_Latency_5);
    FLASH_PrefetchBufferCmd(ENABLE);
    FLASH_InstructionCacheCmd(ENABLE);
    FLASH_DataCacheCmd(ENABLE);

    /* 系统时钟切换 */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    while (RCC_GetSYSCLKSource() != 0x08);

    /* APB 分频 */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);     // 168MHz
    RCC_PCLK1Config(RCC_HCLK_Div4);      // 42MHz
    RCC_PCLK2Config(RCC_HCLK_Div2);      // 84MHz
}
```

### 2.2 SysTick 精确延时

```c
/* 使用 SysTick 实现微秒级延时 */
#include "stm32f4xx.h"

volatile uint32_t usTicks;

void SysTick_Init(void)
{
    /* SysTick = 168MHz / 1 = 168MHz → 每微秒 168 个 tick */
    SysTick_Config(SystemCoreClock / 1000000);  // 1μs 中断
}

void Delay_us(uint32_t us)
{
    usTicks = us;
    while (usTicks != 0);
}

void Delay_ms(uint32_t ms)
{
    for (uint32_t i = 0; i < ms; i++)
        Delay_us(1000);
}

void SysTick_Handler(void)
{
    if (usTicks > 0) usTicks--;
}
```

### 2.3 STM32F4 DSP 库 - FFT 示例

```c
/* 需要添加 arm_cortexM4lf_math.lib 到工程 */
#define ARM_MATH_CM4
#include "arm_math.h"
#include <math.h>

#define FFT_SIZE 256

float32_t fftInput[FFT_SIZE * 2];   // 实部+虚部交织
float32_t fftOutput[FFT_SIZE];
arm_cfft_radix4_instance_f32 fftInstance;

void DSP_FFT_Demo(void)
{
    float32_t maxValue;
    uint32_t maxIndex;

    /* 生成测试信号:1KHz 正弦波 */
    for (int i = 0; i < FFT_SIZE; i++)
    {
        fftInput[i * 2]     = 100.0f * sinf(2.0f * PI * 1000.0f * i / 10000.0f);
        fftInput[i * 2 + 1] = 0.0f;  // 虚部
    }

    /* 初始化并执行 FFT */
    arm_cfft_radix4_init_f32(&fftInstance, FFT_SIZE, 0, 1);
    arm_cfft_radix4_f32(&fftInstance, fftInput);

    /* 计算幅度 */
    arm_cmplx_mag_f32(fftInput, fftOutput, FFT_SIZE);

    /* 寻找最大频率分量 */
    arm_max_f32(fftOutput, FFT_SIZE / 2, &maxValue, &maxIndex);
    printf("Peak at bin %lu, magnitude = %.2f\r\n", maxIndex, maxValue);
    printf("Frequency ≈ %.1f Hz\r\n", (float)maxIndex * 10000.0f / FFT_SIZE);
}
```

---

## 三、Arduino (STM32duino) 例程

> F407 同样支持 STM32duino,在 Board 中选择 `Generic STM32F407VET6`。

```cpp
void setup()
{
    Serial.begin(115200);
    // 注意 F407 的板载 LED 位置因版本不同而异
    // 常见版本:PE0/PE1/PB0/PB1
    pinMode(PE0, OUTPUT);
    pinMode(PE1, OUTPUT);
}

void loop()
{
    digitalWrite(PE0, LOW);
    digitalWrite(PE1, HIGH);
    delay(250);
    digitalWrite(PE0, HIGH);
    digitalWrite(PE1, LOW);
    delay(250);
    Serial.println("STM32F407 running on Arduino core!");
}
```

---

## 四、PlatformIO 配置参考

```ini
; platformio.ini - F407 Black Board
[env:black_f407ve]
platform = ststm32
board = black_f407ve
framework = arduino
; 或者使用 STM32Cube/HAL 框架
; framework = stm32cube
upload_protocol = stlink
monitor_speed = 115200

; 如需自定义频率
board_build.f_cpu = 168000000L
```

---

## 五、关键配置要点

| 要点 | 说明 |
|------|------|
| FPU 使能 | 代码中 `SCB->CPACR` 设置 + 编译器选项 `-mfloat-abi=hard -mfpu=fpv4-sp-d16` |
| Flash Latency | 168MHz 必须设为 `FLASH_LATENCY_5WS`,否则 HardFault |
| ART 加速器 | 务必开启预取缓冲和指令/数据缓存 |
| PLLQ | 给 USB/SDIO 提供 48MHz,必须确保 PLLQ 输出精确 48MHz |
| 堆栈大小 | 使用 FATFS、DSP 等库时建议增大堆栈(startup 文件中修改) |

参考资料

暂无参考文献