stm32f407vet6生成usb.cdc
时间: 2023-05-16 18:01:59 浏览: 360
将stm32f407vet6生成usb.cdc需要以下几个步骤:
1. 配置设备的时钟:设置PLL时钟源、分频系数、倍频系数等参数。
2. 配置设备的GPIO引脚:根据需要,将需要使用的引脚设置为GPIO模式,并进行相应的初始化。
3. 配置USB外设:包括选择USB模式、USB时钟源、EP寄存器设置等。
4. 编写相关的驱动程序:按照设备的需要编写具体的驱动程序,例如UART收发程序、控制程序等。
5. 编写USB设备描述符:编写包含设备描述、配置描述、接口描述等信息的USB设备描述符,并将其存储在Flash中。
6. 编译和烧录程序:将以上所有程序编译生成目标文件,然后将其通过JTAG等方式烧录到目标芯片中。
通过以上步骤,就可以成功地实现stm32f407vet6生成usb.cdc,从而可以和计算机之类的设备进行USB通信。在实际应用中,还可以通过添加其它的功能模块、调整参数等方式进一步优化系统性能。
相关问题
stm32f407vet6 usb开发教程与配置
<think>我们正在处理一个关于STM32F407VET6 USB开发的问题。用户需要详细的教程和配置指南。根据之前的引用,我们有一些关于STM32F407VET6的串口通信和工程搭建的参考,但直接关于USB开发的信息有限。因此,我们将基于STM32F4系列USB开发的通用方法,结合STM32CubeMX和HAL库进行说明。
步骤概述:
1. 硬件准备:STM32F407VET6开发板(如探索者开发板),USB连接线。
2. 软件准备:安装STM32CubeMX、IDE(如Keil或STM32CubeIDE)。
3. 使用STM32CubeMX配置USB外设。
4. 生成代码,并在IDE中编写应用逻辑。
5. 烧录程序并测试。
详细步骤:
1. 硬件准备:
- 确保开发板的USB接口可用(如USB_OTG_FS或USB_OTG_HS)。
- 注意:STM32F407VET6有两个USB OTG控制器:OTG FS(全速)和OTG HS(高速)。OTG HS需要外部PHY芯片,而OTG FS可以直接连接到芯片引脚(内部PHY)。通常,我们首先使用OTG FS。
2. 软件准备:
- 安装STM32CubeMX(最新版本)。
- 安装IDE(如Keil MDK或STM32CubeIDE)。
3. 创建工程:
- 打开STM32CubeMX,点击“New Project”。
- 在芯片选择框中输入“STM32F407VET6”,选择该型号。
- 在“Pinout & Configuration”标签页中配置时钟、调试接口(如SYS->Serial Wire)等。
4. 配置USB:
- 在“Connectivity”下找到“USB_OTG_FS”(或“USB_OTG_HS”)。
- 将模式(Mode)设置为“Device”(设备模式)。
- 在“Middleware”中选择“USB_DEVICE”,并在右侧下拉框中选择设备类(如“Communication Device Class (CDC)”用于虚拟串口,或“Human Interface Device Class (HID)”等)。这里以CDC为例。
- 配置时钟:确保USB时钟为48MHz。通常,STM32F4的USB需要48MHz时钟。我们可以使用外部晶振(HSE)和PLL来生成。在“Clock Configuration”标签页中配置:
- 选择HSE(如8MHz)作为时钟源。
- 配置PLL,使得PLLCLK=168MHz(系统时钟),并设置PLLQ分频系数为7(168/7=24MHz?注意:实际需要48MHz)。注意:PLL48CK必须为48MHz。具体配置:
- PLL Source: HSE
- PLLM: 8(如果HSE是8MHz,则8/8=1MHz)
- PLLN: 336
- PLLP: 2(得到168MHz系统时钟)
- PLLQ: 7(336/7=48MHz)-> 这样PLL48CK=48MHz。
- 在“Peripherals”中,将USB OTG FS的时钟源设置为“PLL48CLK”。
5. 生成代码:
- 在“Project Manager”标签页中,设置工程名称、路径和IDE。
- 在“Code Generator”中,选择“Copy only the necessary library files”和“Generate peripheral initialization as a pair of .c/.h files per peripheral”。
- 点击“Generate Code”。
6. 编写应用代码:
- 打开生成的工程,在USB_DEVICE的App目录下(如USB_DEVICE/App),我们可以修改usbd_cdc_if.c文件来实现CDC的接口函数。
- 主要关注以下函数:
- `static int8_t CDC_Init_FS(void)`: 初始化。
- `static int8_t CDC_DeInit_FS(void)`: 反初始化。
- `static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)`: 处理控制请求。
- `static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)`: 当收到数据时被调用。
- 例如,在`CDC_Receive_FS`中,我们可以将接收到的数据回传:
```c
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* 将接收到的数据通过CDC发送回去 */
CDC_Transmit_FS(Buf, *Len);
return (USBD_OK);
}
```
- 注意:在main函数中,我们需要启动USB设备:
```c
MX_USB_DEVICE_Init();
```
7. 编译和烧录:
- 编译工程,无错误后连接开发板,使用USB线(注意连接到USB_OTG_FS接口)连接到电脑。
- 烧录程序。
8. 测试:
- 电脑上会识别到一个新的串口(CDC类),使用串口调试工具(如Tera Term)打开该串口。
- 发送数据,开发板会将数据回传。
注意事项:
- 如果使用USB HS,需要外部PHY,且硬件设计必须支持。
- 时钟配置是关键,必须确保USB时钟为48MHz。
- 在STM32CubeMX中配置时,注意引脚分配(如OTG_FS的DM和DP)。
以上是一个基本的USB CDC设备(虚拟串口)的配置和开发流程。对于其他设备类(如HID、MSC等),步骤类似,只需在STM32CubeMX中选择相应的类,并实现相应的回调函数。
相关问题:
1. 如何配置STM32F407VET6的USB为HID设备?
2. 在STM32F407VET6上如何实现USB大容量存储设备(MSC)?
3. 如何优化STM32F407VET6的USB传输速度?
4. 如何处理USB设备的枚举过程?
5. 如何同时使用多个USB设备类(复合设备)?</think>### STM32F407VET6 USB开发教程及配置指南
#### 1. **开发环境准备**
- **硬件要求**:
- STM32F407VET6开发板(如正点原子探索者)
- USB连接线(Micro-USB或Type-C,连接板载USB_OTG_FS接口)
- **软件工具**:
- STM32CubeMX(配置外设和生成代码)
- IDE(Keil MDK或STM32CubeIDE)
- STM32F4xx HAL库(最新版本)
> 参考环境搭建方法:[^2]
#### 2. **USB外设配置(STM32CubeMX)**
1. **创建工程**:
- 打开STM32CubeMX → 新建工程 → 选择`STM32F407VETx`
- 配置时钟树:
- HSE选择外部晶振(通常8MHz)
- PLL配置输出168MHz系统时钟
- 确保USB时钟为48MHz(PLLQ分频系数设为7)
$$ \text{PLLQ} = \frac{\text{HSE} \times \text{PLLN}}{\text{PLLM} \times \text{PLLQ分频}} = \frac{8 \times 336}{8 \times 7} = 48\,\text{MHz} $$
2. **USB模块配置**:
- 在`Connectivity`选项卡启用`USB_OTG_FS`
- 模式选择`Device_Only`
- 在`Middleware`中选择设备类:
- CDC(虚拟串口)
- HID(人机接口设备)
- MSC(大容量存储)
- 自定义类
```c
// 示例:CDC类配置
USB_DEVICE → Class For FS IP → Communication Device Class (CDC)
```
3. **引脚分配**:
- 自动分配`PA11`(D-)和`PA12`(D+)为USB数据线
- 启用VBUS检测(如使用`PA9`)
4. **生成代码**:
- 设置工程名/路径 → 选择IDE → 生成代码
#### 3. **代码实现(以CDC为例)**
1. **初始化USB**:
```c
MX_USB_DEVICE_Init(); // 在main()中调用
```
2. **数据收发实现**:
```c
// 发送数据(在usbd_cdc_if.c中)
uint8_t data[] = "Hello USB!";
CDC_Transmit_FS(data, strlen(data));
// 接收回调(处理接收数据)
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) {
// 回传接收到的数据
CDC_Transmit_FS(Buf, *Len);
return USBD_OK;
}
```
#### 4. **关键配置详解**
- **端点配置**:
- CDC类需配置3个端点:
- EP0(控制端点)
- EP1_IN(数据发送)
- EP1_OUT(数据接收)
- 在`usbd_conf.c`中调整缓冲区大小:
```c
#define CDC_DATA_HS_MAX_PACKET_SIZE 512
```
- **时钟验证**:
- 使用示波器检查PA8(MCO)输出,确保48MHz时钟稳定
- 若时钟异常,检查PLL配置:
$$ \text{PLL48CK} = \frac{\text{HSE} \times \text{PLLN}}{\text{PLLM} \times \text{PLLQ}} $$
#### 5. **调试与测试**
1. **枚举测试**:
- 连接USB到PC → 查看设备管理器:
- CDC类显示为`USB串行设备(COMx)`
- HID类显示为`人机接口设备`
- 使用`USBView`工具检查描述符
2. **通信测试**:
- CDC类:用串口助手发送/接收数据
- MSC类:在PC识别U盘并读写文件
- 使用`Wireshark`抓取USB协议包分析
#### 6. **常见问题解决**
- **枚举失败**:
- 检查VBUS供电(需5V)
- 验证D+/D-线是否反接
- 确保描述符符合USB规范
- **数据传输错误**:
- 调整端点缓冲区大小
- 检查`HAL_PCD_SetTxFifo()`配置
- **功耗优化**:
- 空闲时切换到USB挂起模式
```c
__HAL_PCD_GATE_PHYCLOCK(&hpcd_USB_OTG_FS);
HAL_PCD_Stop(&hpcd_USB_OTG_FS);
```
> 完整工程参考:[STM32CubeF4 CDC示例](https://github.com/STMicroelectronics/STM32CubeF4)
---
### 相关问题
1. **如何实现STM32F407VET6的USB HID设备开发?**
2. **USB CDC与普通UART通信有何性能差异?**
3. **如何优化STM32F4的USB传输速度至全速12Mbps?**
4. **USB设备枚举过程中描述符的作用是什么?**
5. **如何实现STM32F407VET6的USB固件升级(DFU)?**
[^1]: STM32F407VET6串口通信与回环测试实战指南
[^2]: stm32f407vet6学习记录(0):搭建开发环境和新建hal工程
怎么实现cubmax+stm32f407vet6驱动ov7670用串口显示在上位机
<think>我们正在使用STM32F407VET6驱动OV7670摄像头,并通过串口将图像数据发送到PC上位机显示。以下是步骤和关键点:
1. 硬件连接:
- OV7670的DVP接口(数据、行同步、帧同步等)连接到STM32的DCMI接口。
- OV7670的SCCB接口(I2C)用于配置摄像头,连接到STM32的I2C引脚。
- OV7670的复位和电源控制引脚(如果需要)连接到STM32的GPIO。
- 串口通信:使用USART(如USART1)通过USB转串口模块或直接连接到PC的串口。
2. 使用CubeMX配置:
- 打开CubeMX,选择STM32F407VET6芯片。
- 配置时钟:使用外部高速时钟(HSE),配置系统时钟为168MHz。
- 配置DCMI接口:
* 在Connectivity中选择DCMI,并配置引脚(数据线D0-D7,像素时钟(PIXCLK),行同步(HSYNC),帧同步(VSYNC))。
- 配置I2C接口(用于SCCB):
* 选择I2C1或I2C2,配置为标准模式(100kHz)或快速模式(400kHz)。
- 配置串口(如USART1):
* 波特率设置为较高值(如921600或更高,以支持图像传输),8位数据,无校验,1停止位。
- 配置GPIO:
* 为OV7670的复位(RESET)和电源控制(PWDN)引脚配置GPIO输出(如果需要)。
- 配置DMA(可选):
* 为DCMI配置DMA以连续接收数据,减轻CPU负担。
* 为串口配置DMA发送,提高传输效率。
- 配置中断:
* 使能DCMI中断,以便在帧捕获完成时进行处理。
- 生成代码。
3. 代码开发:
- 初始化OV7670:
* 通过I2C(SCCB)写入OV7670的寄存器配置(初始化序列),设置分辨率(如QVGA: 320x240)、输出格式(如RGB565)、帧率等。
- 配置DCMI:
* 在CubeMX生成的代码基础上,启动DCMI捕获。
- 图像数据存储:
* 由于OV7670输出一帧320x240的RGB565图像大小为320*240*2=153600字节,而STM32F407VET6的RAM只有192KB,因此需要合理分配缓冲区(可能使用外部SRAM或分块传输)。
* 如果没有外部SRAM,则可以采用分块传输:捕获一帧后,通过串口分多次发送(每次发送一部分数据)。
- 串口传输:
* 设计串口协议:例如,先发送帧头(如0xAA, 0x55),然后发送图像数据(RGB565格式),最后发送帧尾(可选)或通过长度判断。
* 使用DMA传输可以避免阻塞CPU。
4. 上位机软件:
- 使用串口接收数据,根据协议解析图像数据。
- 将RGB565数据转换为RGB888,然后显示图像。
- 可以使用Python(PySerial和OpenCV或PyQt)或C#等语言开发。
5. 注意事项:
- OV7670的时钟输入(XCLK)需要提供,可以由STM32的MCO引脚输出(如PA8)提供(在CubeMX中配置MCO为PLL输出,分频得到8MHz或10MHz)。
- OV7670的供电需要3.3V,注意电源稳定。
具体步骤:
步骤1:CubeMX配置
- 设置时钟树:HSE输入,PLLCLK作为系统时钟,最大168MHz。
- 配置DCMI:选择对应引脚(参考数据手册)。
- 配置I2C:选择I2C1或I2C2,标准模式。
- 配置USART:异步模式,高波特率(921600或更高)。
- 配置MCO(PA8)输出时钟给OV7670(如8MHz)。
- 配置GPIO:复位和电源控制引脚(如果有)。
- 生成代码。
步骤2:编写OV7670初始化代码
- 在生成的I2C代码基础上,编写SCCB读写函数(SCCB与I2C类似,但写时序有微小差别)。
- 写入OV7670的初始化寄存器序列(可以从网上获取或根据应用笔记配置)。
步骤3:DCMI中断处理
- 在帧中断中,将捕获的一帧数据存储到缓冲区。
- 由于内存限制,可以分块:捕获一行或若干行就通过串口发送一次。
步骤4:串口发送图像数据
- 设计一个函数,将缓冲区中的图像数据通过串口发送。
- 可以分块发送,每块数据前加块头(如块索引、长度等)以便上位机重组。
步骤5:上位机开发
- 接收串口数据,按照协议解析出图像数据。
- 将RGB565转换为RGB888(每个像素:R=5位,G=6位,B=5位)。
- 显示图像。
参考代码结构(STM32部分):
- main.c:
初始化外设->初始化OV7670->启动DCMI捕获->等待中断。
- 在DCMI帧中断中,启动串口传输(分块发送)。
由于OV7670输出的是连续的数据流,我们可以使用DCMI的连续捕获模式,然后使用DMA将数据传送到内存缓冲区。但受限于内存大小,我们可以设置一个较小的缓冲区(例如一次捕获几行),然后通过串口发送出去,再捕获下一部分。
另一种方法:使用DCMI的裁剪功能(CROP)捕获图像的一部分,然后发送,再捕获下一部分,最后拼接成一整帧。但OV7670不支持CROP功能(根据引用[2]中OV2640支持),所以可能需要软件处理分块。
因此,我们可以这样做:
- 设置DCMI为连续模式,并启用DMA将数据传送到一个行缓冲区(例如一行320像素*2字节=640字节)。
- 在DCMI行中断中,将这一行数据通过串口发送出去(使用DMA发送,避免阻塞)。
- 注意:帧率可能会受串口速度限制。例如,一行640字节,以921600波特率(约92KB/s)发送一行需要约7ms,那么一帧240行需要1680ms(即帧率不到1帧/秒)。因此,需要提高波特率(如使用2M波特率)或降低分辨率。
如果使用全速USB虚拟串口(引用[2]中提到12000000波特率,即12Mbps,约1.2MB/s),则传输一帧153600字节需要约128ms,帧率可达7-8帧/秒。但STM32F407的USART最高波特率只有4.5Mbps(在168MHz下),所以如果使用硬件串口,最高波特率可以设置为2250000(2.25Mbps)或更高(需要确认芯片支持)。或者使用USB虚拟串口(CDC类)实现高速传输。
因此,建议:
- 如果使用硬件串口,使用最高波特率(如2250000),并考虑使用DMA传输。
- 或者,使用USB虚拟串口(CDC)进行高速传输(需要配置USB)。
鉴于项目复杂度,这里先以硬件串口为例。
代码示例(部分):
1. OV7670初始化序列(示例,具体需根据实际调整):
```c
// 初始化寄存器数组
const uint8_t OV7670_Reg_Init[] = {
0x12, 0x80, // 复位
// ... 其他配置
0x00 // 结束标记
};
void OV7670_Init(void) {
// 复位OV7670(通过GPIO)
// 延时
for (int i=0; OV7670_Reg_Init[i]!=0; i+=2) {
SCCB_WriteReg(OV7670_Reg_Init[i], OV7670_Reg_Init[i+1]);
}
}
```
2. 配置DCMI和DMA:
在CubeMX中配置DCMI使用DMA(连续传输,循环模式),并设置内存地址为行缓冲区,数据长度为一行(320*2=640字节)。然后使能行中断。
3. 行中断处理:
在DCMI行中断中,将行缓冲区数据通过串口DMA发送(注意:发送前需要检查上一次DMA传输是否完成,如果未完成则等待或丢弃)。发送完成后,重新启动DCMI的DMA传输(循环模式会自动覆盖缓冲区)。
4. 帧同步处理:
在帧开始和帧结束中断中,可以发送帧头和帧尾,以便上位机同步。
由于串口速度限制,实际帧率可能较低。如果追求更高帧率,建议使用USB虚拟串口或降低分辨率。
上位机部分(Python示例):
```python
import serial
import numpy as np
import cv2
ser = serial.Serial('COM3', 921600) # 根据实际情况修改串口号和波特率
width = 320
height = 240
frame_size = width * height * 2 # RGB565
# 接收一帧
def receive_frame():
# 先读取帧头(例如0xAA, 0x55)
header = ser.read(2)
if header != b'\xaa\x55':
# 同步错误
return None
# 读取图像数据
data = ser.read(frame_size)
return data
# 转换RGB565为BGR888
def rgb565_to_bgr(data):
img = np.frombuffer(data, dtype=np.uint8).reshape((height, width, 2))
bgr = np.zeros((height, width, 3), dtype=np.uint8)
# 将两个字节合并为一个uint16
rgb565 = img[:,:,0] << 8 | img[:,:,1]
# 提取RGB分量
r = (rgb565 & 0xF800) >> 8
g = (rgb565 & 0x07E0) >> 3
b = (rgb565 & 0x001F) << 3
# 组合成24位RGB
bgr[:,:,2] = r
bgr[:,:,1] = g
bgr[:,:,0] = b
return bgr
while True:
frame_data = receive_frame()
if frame_data is not None:
img_bgr = rgb565_to_bgr(frame_data)
cv2.imshow('OV7670', img_bgr)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
ser.close()
```
注意:上述代码仅为示例,实际中可能需要处理数据分块和重组。
由于项目复杂度,可能需要逐步调试。
相关问题:
1. 如何提高OV7670图像传输的帧率?
2. OV7670的初始化寄存器配置有哪些关键点?
3. 如何优化STM32的DCMI和串口DMA传输?</think>### 使用STM32F407VET6驱动OV7670摄像头并通过串口传输图像的实现方案
#### 一、硬件连接
1. **OV7670接口**:
- DVP数据接口:连接STM32的DCMI接口(D0-D7, PCLK, VSYNC, HSYNC)
- SCCB控制接口:连接STM32的I²C1(SDA-PB9, SCL-PB8)
- 电源:3.3V供电,XCLK由STM32的MCO引脚提供(PA8)
2. **串口通信**:
- USART1(TX-PA9, RX-PA10)连接USB转TTL模块
- 波特率建议≥921600bps
#### 二、CubeMX配置步骤
1. **时钟配置**:
- HSE时钟源:8MHz
- 系统时钟:168MHz
- MCO输出(PA8):84MHz → 分频为8-10MHz供OV7670
2. **DCMI接口**:
```c
// 在Connectivity中启用DCMI
Mode: Continuous Mode
Synchronization: Hardware Sync
Data Width: 8-bit
```
3. **I²C配置**:
```c
// I2C1参数
Mode: I2C
Speed: Standard Mode (100kHz)
```
4. **串口配置**:
```c
// USART1参数
Mode: Asynchronous
Baud Rate: 921600
Word Length: 8 Bits
```
5. **DMA配置**:
- 为DCMI添加DMA通道(Stream1/Channel1)
- 为USART TX添加DMA通道(Stream7/Channel4)
#### 三、关键代码实现
1. **OV7670初始化**:
```c
void OV7670_Init(void) {
SCCB_Write(0x12, 0x80); // 复位寄存器
HAL_Delay(100);
// 配置QVGA RGB565输出
SCCB_Write(0x40, 0xD0); // RGB565格式
SCCB_Write(0x12, 0x14); // QVGA分辨率(320x240)
SCCB_Write(0x11, 0x80); // 分频系数
}
```
2. **图像捕获与传输**:
```c
void Capture_Send_Frame(void) {
uint8_t frame_buffer[320 * 240 * 2]; // RGB565缓冲区
// 启动DCMI捕获
HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_CONTINUOUS,
(uint32_t)frame_buffer,
320 * 240 * 2 / 4);
// 等待帧捕获完成
while(!dcmi_frame_ready);
// 通过串口发送帧头
uint8_t header[] = {0xAA, 0x55, 0x01};
HAL_UART_Transmit_DMA(&huart1, header, sizeof(header));
// 分块发送图像数据(避免串口阻塞)
for(int i=0; i<sizeof(frame_buffer); i+=512) {
HAL_UART_Transmit_DMA(&huart1, &frame_buffer[i],
MIN(512, sizeof(frame_buffer)-i));
HAL_Delay(1);
}
}
```
3. **上位机通信协议**:
| 字节位置 | 内容 | 说明 |
|----------|-------------|----------------------|
| 0-1 | 0xAA 0x55 | 帧头标识 |
| 2 | 0x01 | 摄像头类型(OV7670) |
| 3-153602 | RGB565数据 | 320x240x2字节图像数据 |
#### 四、上位机处理(Python示例)
```python
import serial
import numpy as np
import cv2
ser = serial.Serial('COM3', 921600)
W, H = 320, 240
while True:
header = ser.read(3)
if header == b'\xaa\x55\x01':
data = ser.read(W*H*2) # 读取一帧
img = np.frombuffer(data, dtype=np.uint8).reshape(H, W, 2)
# 转换RGB565为BGR
rgb565 = img[:, :, 0] << 8 | img[:, :, 1]
bgr = cv2.cvtColor(np.stack((
(rgb565 & 0xF800) >> 8,
(rgb565 & 0x07E0) >> 3,
(rgb565 & 0x001F) << 3), axis=2),
cv2.COLOR_RGB2BGR)
cv2.imshow("OV7670", bgr)
if cv2.waitKey(1) == 27: break
```
#### 五、优化建议
1. **内存管理**:
- 使用双缓冲机制:当DMA传输一帧时处理另一帧
- 启用内存加速:`__HAL_RCC_CRC_CLK_ENABLE()`
2. **传输优化**:
- 使用JPEG压缩:OV7670支持JPEG输出(寄存器0x12[6]=1)
- 增加数据校验:每帧添加CRC校验位
3. **时序控制**:
```c
// 调整帧率(寄存器0x11)
SCCB_Write(0x11, (FREQ & 0x3F)); // PCLK分频系数
```
#### 六、常见问题解决
1. **图像偏色**:
- 调整白平衡寄存器(0x13, 0x14)
- 校准色彩矩阵(0x4F-0x5F)
2. **数据传输错位**:
- 增加硬件流控(RTS/CTS)
- 降低波特率至460800
3. **DCMI同步失败**:
```c
// 调整VSYNC/HSYNC极性
hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_LOW;
hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_LOW;
```
> **注意事项**:OV7670的SCCB时序与I²C略有差异,需在`HAL_I2C_Mem_Write()`后添加5μs延时[^3]。
阅读全文
相关推荐














