扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

RT1050 FlexIO 采集 OV7670 摄像头数据并 TFT LCD 显示实操指南

10小时前
303
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

MIMXRT1050 凭借高性能 Cortex-M7 内核与灵活的 FlexIO 外设,可实现对 OV7670 并口摄像头数据的采集与 TFT LCD 实时显示。本文基于 MIMXRT1050-EVKB 开发板,详解 FlexIO 采集 OV7670 数据、SPI 驱动 ILI9321 TFT LCD 的完整实现方案,包含硬件接线改造、核心软件适配(针对 RT1050 FlexIO 特性的代码修改)、LCD 单独测试方法,提供可直接复用的配置与源码思路,适配 240×320 分辨率的实时图像显示需求。

资料获取:RT1050 FlexIO采集OV7670摄像头数据TFTLCD显示

1. 核心方案与软硬件环境

1.1 方案整体逻辑

采用 “FlexIO 采集 + DMA 搬运 + SPI 显示” 架构,核心流程:

  1. OV7670 摄像头输出 8 位并行图像数据、像素时钟(PCLK)、行同步(HS)、帧同步(VS)信号;
  2. RT1050 的 FlexIO 外设模拟并行接口,捕获摄像头数据,通过 DMA 直接搬运至内存缓冲区,避免 CPU 占用;
  3. 内存中的图像数据(RGB565 格式)通过 SPI 接口传输至 ILI9321 TFT LCD,实现实时显示。

1.2 关键差异说明

NXP 官方应用笔记 AN12686 基于 RT1010(8 个 FlexIO shifter)开发,而 RT1050 仅支持 4 个 FlexIO shifter,因此需针对性修改DMA 配置FlexIO 数据捕获逻辑,才能适配 4 shifter 硬件限制,这是本方案的核心适配点。

3. 软硬件清单

(1)硬件组件

设备名称 型号 / 规格 核心作用
主控板 MIMXRT1050-EVKB revA1 核心控制单元,提供 FlexIO、SPI、DMA 等外设
摄像头 OV7670 并口模组 输出 8 位并行图像数据,支持 SCCB 接口配置
TFT LCD 2.4 寸 ILI9321(SPI 接口) 240×320 分辨率,接收 SPI 传输的图像数据并显示
辅助工具 杜邦线、电烙铁 硬件接线与开发板引脚改造

(2)软件环境

  • 开发 IDE:MCUXpresso IDE(或 IAR/Keil);
  • 底层驱动:NXP MCUXpresso SDK(适配 RT1050);
  • 辅助工具:LVGL 在线图像转换工具(将图片转为 RGB565 数组)。

2. 硬件配置:接线与开发板改造

硬件部分核心是FlexIO 引脚分配(避开板载冲突)、OV7670 与 RT1050 接线TFT LCD 与 SPI 接口连接,需先完成开发板引脚改造,再按定义接线。

2.1 开发板改造(关键步骤)

为减少信号干扰,需移除 MIMXRT1050-EVKB 板上的 3 个电阻与 1 个二极管,具体为:R323、R316、R309、D6,直接物理拔除即可,无需额外焊接。

2.2 OV7670 与 RT1050 接线定义

OV7670 的 8 位数据引脚、控制引脚均连接至 RT1050 的 FlexIO2 外设引脚,SCCB 配置接口(I2C)连接至 I2C1,具体接线如下:

OV7670 引脚 信号名称 RT1050-EVKB 引脚 对应外设功能
P1 PWDN GPIO_AD_B1_02(GPIO1_IO18) 功耗控制(拉低正常工作)
P2 RESET GPIO_AD_B1_03(GPIO1_IO19) 复位控制(拉高正常工作)
P3-P10 D0-D7 GPIO_B0_05~GPIO_B0_12(FlexIO2_D05~D12) 8 位并行数据输入
P11 XCLK GPIO_B0_13(FlexIO2_D13) 摄像头时钟输入
P12 PCLK GPIO_B0_14(FlexIO2_D14) 像素时钟(FlexIO 捕获触发信号)
P13 HS(HREF) GPIO_B0_15(FlexIO2_D15) 行同步信号
P14 VS GPIO_AD_B0_03(GPIO1_IO03) 帧同步信号
P15 SDA GPIO_AD_B1_01(I2C1_SDA) SCCB 数据接口
P16 SCL GPIO_AD_B1_00(I2C1_SCLK) SCCB 时钟接口
P17 GND GND 接地
P18 3.3V 3.3V 电源供电

2.3 TFT LCD 与 RT1050 SPI 接线

ILI9321 LCD 采用 SPI 接口通信,仅使用显示功能(触摸功能未启用),接线如下:

LCD 引脚 信号名称 RT1050-EVKB 引脚 对应外设功能
1 GND GND(J24_7) 接地
2 VCC 3.3V(J24_8) 电源供电
3 CLK GPIO_AD_B1_15(SPI3_CLK) SPI 时钟信号
4 MOSI GPIO_AD_B1_14(SPI3_MOSI) SPI 数据输出(图像数据)
5 RES GPIO_AD_B0_02(GPIO1_IO02) LCD 复位(高电平有效)
6 DC GPIO_AD_B1_10(GPIO1_IO26) 数据 / 命令选择(高 = 数据,低 = 命令)
7 BLK 3.3V 背光控制(拉高常亮,拉低关闭)
9 CS1 GPIO_AD_B1_12(GPIO1_IO28) 显示部分片选(拉低有效)

3. 软件配置:核心代码适配与实现

软件部分按 “LCD 单独测试→OV7670 配置→FlexIO+DMA 采集→SPI 显示” 的顺序开发,核心适配 RT1050 的 4 shifter FlexIO 特性。

3.1 LCD 单独测试(验证 SPI 驱动)

先通过固定图片验证 LCD 显示功能,避免后续集成时定位问题,步骤如下:

(1)图片转 RGB565 数组

  1. 准备一张 240×320 分辨率的图片,通过 LVGL 在线转换工具(https://lvgl.io/tools/imageconverter)转换;
  2. 转换格式选择 “CF_RGB565”,生成 C 语言数组(自动去除 Alpha 通道冗余字节),保存为horsepic.h头文件。

(2)LCD 初始化与图片显示代码

#include "ILI9321.h"
#include "horsepic.h"

// RGB888转RGB565(若转换工具未处理,需手动转换)
void convert8to16(void) {
    uint32_t i;
    for (i = 0; i < OV7670_FRAME_BYTES/3; i++) {
        horse16[i] = ((horse8[i*3] & 0xF8) << 8) | ((horse8[i*3+1] & 0xFC) << 3) | ((horse8[i*3+2] & 0xF8) >> 3);
    }
}

// 显示图片
int main(void) {
    // 初始化SPI与LCD
    ILI9321_Init();
    // 转换图片格式(若已为RGB565可省略)
    convert8to16();
    // 在LCD全屏显示图片(x1,y1,x2,y2, 图像数组)
    ILI9321_FillPic(0, 0, OV7670_FRAME_WIDTH-1, OV7670_FRAME_HEIGHT-1, (uint16_t *)horse16);
    
    while(1);
    return 0;
}
  • 若 LCD 正常显示图片,说明 SPI 驱动与接线无误。

3.2 OV7670 配置(SCCB 接口)

通过 I2C1 模拟 SCCB 接口,配置 OV7670 的图像格式、分辨率、帧率等参数,核心配置为:

  • 图像格式:RGB565(16 位色,适配 LCD);
  • 分辨率:240×320(与 LCD 一致);
  • 像素时钟:由 RT1050 FlexIO 提供(XCLK 引脚)。

核心配置代码(基于 SDK I2C 驱动):

#define OV7670_ADDR 0x21 // OV7670 SCCB地址

// 向OV7670寄存器写值
void OV7670_WriteReg(uint8_t reg, uint8_t val) {
    I2C_MasterStart(I2C1, OV7670_ADDR, kI2C_Write);
    I2C_MasterWrite(I2C1, reg);
    I2C_MasterWrite(I2C1, val);
    I2C_MasterStop(I2C1);
}

// OV7670初始化(配置RGB565格式与240×320分辨率)
void OV7670_Init(void) {
    OV7670_WriteReg(0x12, 0x04); // 复位摄像头
    delay_ms(10);
    OV7670_WriteReg(0x11, 0x00); // 帧率控制
    OV7670_WriteReg(0x3A, 0x05); // 选择RGB565格式
    // 其他分辨率配置寄存器(参考OV7670 datasheet)
    OV7670_WriteReg(0x17, 0x22);
    OV7670_WriteReg(0x18, 0x04);
}

3.3 FlexIO+DMA 采集配置(核心适配)

针对 RT1050 的 4 个 FlexIO shifter,修改 FlexIO 设备结构体与 DMA 传输参数,实现 8 位数据的正确捕获。

(1)FlexIO 设备结构体配置

// FlexIO摄像头设备配置(4 shifter适配)
static FLEXIO_CAMERA_Type s_FlexioCameraDevice = {
    .flexioBase = BOARD_CAMERA_FLEXIO_INST, // FlexIO2实例
    .shifterStartIdx = 0U, // 起始shifter索引
    .shifterCount = 4U, // RT1050仅支持4个shifter
    .datPinStartIdx = BOARD_CAMERA_FLEXIO_DATA_PIN_START_INDEX, // 数据引脚起始索引
    .pclkPinIdx = BOARD_CAMERA_FLEXIO_PCLK_PIN_INDEX, // PCLK引脚索引
    .hrefPinIdx = BOARD_CAMERA_FLEXIO_HREF_PIN_INDEX, // HS引脚索引
    .timerIdx = 0U, // 定时器索引
};

(2)DMA 配置(关键修改)

通过 DMA 将 FlexIO 捕获的数据直接搬运至内存缓冲区,核心修改传输大小地址偏移,适配 4 shifter 的数据拼接逻辑:

#define DMA_TRSF_SIZE 8U // 每次传输8字节(适配4 shifter)
#define DMA_MINOR_LOOP_SIZE 8U // 次要循环大小
#define OV7670_FRAME_BYTES (240*320*2) // 一帧图像字节数(RGB565)
uint8_t g_FlexioCameraFrameBuffer[OV7670_FRAME_BYTES]; // 图像缓冲区

static void configDMA(void) {
    uint32_t soff, smod = 0u, size = 0u;
    // 计算size = log2(DMA_TRSF_SIZE),用于DMA ATTR配置
    while((1u << size) < DMA_TRSF_SIZE) size++;
    // 配置源地址偏移(根据传输大小调整)
    if(DMA_TRSF_SIZE == DMA_MINOR_LOOP_SIZE) {
        soff = 0u;
    } else {
        soff = DMA_TRSF_SIZE;
    }
    // 计算smod = log2(DMA_MINOR_LOOP_SIZE)
    while((1u << smod) < DMA_MINOR_LOOP_SIZE) smod++;
    
    // 配置DMA TCD(传输控制描述符)
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SADDR = FLEXIO_CAMERA_GetRxBufferAddress(&s_FlexioCameraDevice);
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SOFF = soff; // 源地址偏移
    // 配置数据大小与模式(源/目的数据宽度一致)
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].ATTR = DMA_ATTR_SMOD(smod) | 
                                             DMA_ATTR_SSIZE(size) | 
                                             DMA_ATTR_DMOD(0u) | 
                                             DMA_ATTR_DSIZE(size);
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].NBYTES_MLNO = 16; // 每次传输16字节
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SLAST = 0u; // 源地址最后偏移
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DADDR = (uint32_t)g_FlexioCameraFrameBuffer; // 目的地址(图像缓冲区)
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DOFF = 8; // 目的地址偏移
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CITER_ELINKNO = DMA_MAJOR_LOOP_SIZE; // 主要循环次数
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DLAST_SGA = -OV7670_FRAME_BYTES; // 传输完成后目的地址复位
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CSR = DMA_CSR_DREQ_MASK; // 启用DMA请求
    DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].BITER_ELINKNO = DMA_MAJOR_LOOP_SIZE;
    
    // 配置DMAMUX,关联FlexIO DMA请求源
    DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] = (DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] & (~DMAMUX_CHCFG_SOURCE_MASK)) |
                                           DMAMUX_CHCFG_SOURCE(FLEXIO_CAMERA_DMA_MUX_SRC);
    DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] |= DMAMUX_CHCFG_ENBL_MASK; // 启用DMAMUX通道
}

3.4 整体集成与显示

完成各模块配置后,集成采集与显示逻辑,实现 “采集一帧→显示一帧” 的实时流程:

int main(void) {
    // 初始化硬件
    BOARD_InitPins();
    BOARD_InitClocks();
    I2C1_Init();
    SPI3_Init();
    DMA_Init();
    
    // 初始化外设
    OV7670_Init();
    ILI9321_Init();
    FLEXIO_CAMERA_Init(&s_FlexioCameraDevice);
    configDMA();
    
    // 启用FlexIO采集与DMA传输
    FLEXIO_CAMERA_Enable(&s_FlexioCameraDevice, true);
    DMA_EnableChannel(DMA0, FLEXIO_CAMERA_DMA_CHN);
    
    while(1) {
        // 等待一帧数据采集完成(通过VS信号或DMA完成中断判断)
        if(FLEXIO_CAMERA_IsFrameDone(&s_FlexioCameraDevice)) {
            // 显示一帧图像(缓冲区数据→LCD)
            ILI9321_FillPic(0, 0, 239, 319, (uint16_t *)g_FlexioCameraFrameBuffer);
            // 清除帧完成标志
            FLEXIO_CAMERA_ClearFrameDone(&s_FlexioCameraDevice);
        }
    }
    return 0;
}

4. 常见问题排查与避坑指南

4.1 LCD 无显示,SPI 通信异常

  • 原因 1:DC 引脚(数据 / 命令选择)接线错误,导致 LCD 无法区分命令与数据;
  • 原因 2:CS1 片选引脚未拉低,LCD 未被选中;
  • 解决:重新核对 SPI 接线(CLK/MOSI/DC/CS1),确保初始化时拉低 CS1,发送命令时拉低 DC,发送数据时拉高 DC。

4.2 采集到的数据乱码,图像花屏

  • 原因 1:FlexIO shifter 数量配置错误(按 RT1010 的 8 shifter 配置,未改为 4);
  • 原因 2:DMA 传输大小(NBYTES_MLNO)与 shifter 数量不匹配;
  • 原因 3:OV7670 图像格式配置错误(非 RGB565);
  • 解决:确认shifterCount=4U,DMA 传输参数与 4 shifter 适配,重新检查 OV7670 的 0x3A 寄存器(配置为 0x05,RGB565)。

4.3 开发板发热,信号干扰严重

  • 原因:未移除板载 R323、R316、R309 电阻与 D6 二极管,导致信号冲突;
  • 解决:按要求完成开发板硬件改造,重新焊接或拔除冲突元件。

4.4 DMA 传输完成但缓冲区无数据

  • 原因 1:DMAMUX 通道未关联正确的 FlexIO DMA 请求源;
  • 原因 2:FlexIO 的 PCLK 触发边沿配置错误(未与 OV7670 的 PCLK 同步);
  • 解决:核对DMAMUX_CHCFG_SOURCE参数为 FlexIO2 的 DMA 请求源,调整 FlexIO 捕获的 PCLK 触发边沿(上升沿 / 下降沿)。

RT1050 通过 FlexIO+DMA 实现 OV7670 数据采集与 TFT LCD 显示的核心,是适配 4 shifter 的硬件限制,关键修改点为 FlexIO 设备结构体与 DMA 传输参数。整个方案的实现流程可概括为:

  1. 硬件改造→接线→LCD 单独测试(验证 SPI 驱动);
  2. OV7670 配置(SCCB 接口)→FlexIO+DMA 采集配置;
  3. 集成采集与显示逻辑,实现实时图像传输。

本方案避开了 RT1050 与 RT1010 的 FlexIO 硬件差异,提供了完整的接线定义、核心代码适配与问题排查方法,可直接移植到 MIMXRT1050-EVKB 开发板使用。测试结果表明,该方案能稳定捕获 OV7670 的 240×320 分辨率图像,并通过 SPI 接口在 ILI9321 LCD 上实时显示,无明显延迟与花屏现象。

如需进一步优化,可调整 OV7670 的帧率参数、DMA 缓存策略或 SPI 传输速率,以平衡显示流畅度与系统资源占用。

相关推荐