RT1050 FlexIO OV7670 带 TFT LCD 显示屏
关于RT10XX flexIO采集OV7670摄像头数据并显示在TFT LCD上,其实NXP官网有一篇很好的应用笔记AN12686 ,但是测试是基于RT1010而不是EVK。实际客户直接测试可能会比较困难。笔者在给客户支持的时候,遇到客户想在RT1050 EVK上实现flexIO来采集并口OV7670的数据,并显示在TFT LCD也就是带SPI接口的LCD上,所以本文给出了具体的成品测试结果,RT1050 flexIO和RT1010 flexIO之间还是有一些区别的。RT1010 flexIO有8个移位器,但RT1050只有4个移位器,因此需要进行一些代码修改并移植到RT1050。由于是要在MIMXRT1050-EVKB上运行,所以还需要考虑可以使用的flexIO引脚,修改EVKB,并手动焊接相关引脚,配置相应的摄像头信号和LCD显示信号。
本文主要来源于客户测试时遇到的问题,因此提供了具体的硬件连接、软件代码分享、测试成品结果等。
由于AN12686已经非常详细地给出了原理,本文旨在给出在RT1050-EVKB上工作的区别和具体条件。
2.1 硬件配置
该平台基于MIMXRT1050-EVKB revA1、OV7670模块、2.4寸TFT LCD液晶SPI串行触摸TFT彩屏ILI9321,分辨率为240*320。
关于OV7670模块状态及引脚状态请查看文章:
RT1050 CSI OV7670 camera eLCD display
摄像头模块引脚如下:
图1
TFT LCD picture:
图2
|
Pin No |
信号 |
描述 |
|
1 |
接地 |
电源地 |
|
2 |
VCC |
电源3.3V |
|
3 |
CLK |
SPI时钟 |
|
4 |
MOSI |
SPI数据 |
|
5 |
RES |
LCD复位 |
|
6 |
DC |
LCD数据/命令选择引脚 |
|
7 |
黑色 |
背光控制开关,默认开启背光,低电平关闭背光 |
|
8 |
MISO |
触摸数据读取 |
|
9 |
CS1 |
显示选择引脚 |
|
10 |
CS2 |
触摸选择引脚 |
|
11 |
PEN |
触摸中断信号 |
对于LCD,本文只使用了显示部分,没有使用毛坯模具部分。
考虑到MIMXRT1050-EVKB的引脚布局,这里没有使用应用笔记中的flexIO1,而是选择了FlexIO2。实际的 RT1050-EVKB 和 OV7670 模块和 LCD 连接引脚如下所示。
LCD信号引脚与MCU MIMXRT1050-EVKB RevA1信号引脚连接如下:
|
LCD信号和引脚 |
MIMXRT1050-EVKB revA1信号和引脚 |
||
|
接地 |
P1 |
接地 |
J24_7 |
|
3.3V VCC |
P2 |
3.3v |
J24_8 |
|
CLK |
P3 |
GPIO_AD_B1_15(SPI3_CLK) |
R98 |
|
MOSI |
P4 |
GPIO_AD_B1_14(SPI3_MOSI) |
R99 |
|
RES |
P5 |
GPIO_AD_B0_02(GPIO1_IO02) |
J24_2 |
|
DC |
P6 |
GPIO_AD_B1_10(GPIO01_IO26) |
J23_1 |
|
CS1 |
P9 |
GPIO_AD_B1_12(GPIO01_IO28) |
100 卢比 |
OV7670信号引脚与MCU MIMXRT1050-EVKB RevA1信号引脚连接情况:
|
0V7670信号及引脚 |
MIMXRT1050-EVKB revA1信号和引脚 |
||
|
OV7670_D0 |
P3 |
GPIO_B0_05(FLEXIO2_D05) |
SW5_1 |
|
OV7670_D1 |
P4 |
GPIO_B0_06(FLEXIO2_D06) |
SW5.2 |
|
OV7670_D2 |
P5 |
GPIO_B0_07(FLEXIO2_D07) |
SW5_3 |
|
OV7670_D3 |
P6 |
GPIO_B0_08(FLEXIO2_D08) |
SW5_4 |
|
OV7670_D4 |
P7 |
GPIO_B0_09(FLEXIO2_D09) |
SW6_1 |
|
OV7670_D5 |
P8 |
GPIO_B0_10(FLEXIO2_D10) |
SW7_1 |
|
OV7670_D6 |
P9 |
GPIO_B0_11(FLEXIO2_D11) |
SW6_2 |
|
OV7670_D7 |
P10 |
GPIO_B0_12(FLEXIO2_D12) |
SW6_3 |
|
时钟信号 |
P11 |
GPIO_B0_13(FLEXIO2_D13) |
SW7_2 |
|
PCLK |
P12 |
GPIO_B0_14(FLEXIO2_D14) |
SW6_4 |
|
HREF(HS) |
P13 |
GPIO_B0_15(FLEXIO2_D15) |
R258/R324 |
|
VSYNC |
P14 |
GPIO_AD_B0_03(GPIO01_03) |
J24_1 |
|
I2C_SDA |
P15 |
GPIO_AD_B1_01(I2C1_SDA) |
J23_5 |
|
I2C_SCL |
P16 |
GPIO_AD_B1_00(I2C1_SCLK) |
J23_6 |
|
密码 |
P1 |
GPIO_AD_B1_02(GPIO1_IO18) |
J22_7 |
|
复位 |
P2 |
GPIO_AD_B1_03(GPIO1_IO19) |
J22_8 |
|
3.3v |
第18页 |
3.3v |
J22_7 |
|
接地 |
P17 |
接地 |
J22_8 |
为了减少信号的影响,MIMXRT1050-EVKB移除了板上的R323、R316、R309和D6。
物理连接情况如下:
图3
2.2 软件配置
由于RT1050的flexIO与RT1010的8个移位器不同,因此需要修改DMA配置。flexio_ov7670的差异代码如下:
static FLEXIO_CAMERA_Type s_FlexioCameraDevice = {
.flexioBase = BOARD_CAMERA_FLEXIO_INST,
.datPinStartIdx = BOARD_CAMERA_FLEXIO_DATA_PIN_START_INDEX,
.pclkPinIdx = BOARD_CAMERA_FLEXIO_PCLK_PIN_INDEX,
.hrefPinIdx = BOARD_CAMERA_FLEXIO_HREF_PIN_INDEX,
.shifterStartIdx = 0U,
.shifterCount = 4,
.timerIdx = 0U,
};
static void configDMA(void)
{
uint32_t soff, smod = 0u, size=0u;
while(1u << size < DMA_TRSF_SIZE) /* size = log2(DMA_TRSF_SIZE) */
{
size++;
}
if(DMA_TRSF_SIZE == DMA_MINOR_LOOP_SIZE)
{
soff = 0u;
}
else
{
soff = DMA_TRSF_SIZE;
while(1u << smod < DMA_MINOR_LOOP_SIZE) /* smod = log2(DMA_MINOR_LOOP_SIZE) */
{
smod++;
}
}
/* Configure 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;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SLAST = 0u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DADDR = (uint32_t)(*pFlexioCameraFrameBuffer);
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 = 0u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CSR |= DMA_CSR_DREQ_MASK;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].BITER_ELINKNO = DMA_MAJOR_LOOP_SIZE;
/* Configure DMA MUX Source */
DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] = DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] & (~DMAMUX_CHCFG_SOURCE_MASK) | DMAMUX_CHCFG_SOURCE(FLEXIO_CAMERA_DMA_MUX_SRC);
/* Enable DMA channel. */
DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] |= DMAMUX_CHCFG_ENBL_MASK;
}
代码结构采用:相机采用flexIO方式采集DMA传输。采集完一帧后,DMA将数据存储到缓冲区中,然后统一在LCD上显示一帧数据。
由于flexIO OV7670和LCD SPI的配置代码很多,这里就不一一讲解了。详情请检查附件的代码源代码。
代码中有一个horsepic.h的头文件。该文件是一张320*240 RGB565的马的图片。用于单独测试LCD显示屏。通常在连接LCD后,需要单独测试LCD显示屏。您可以使用固定的图片来获取显示。,这里是将图片转换成C数组的方法:先将图片调整到LCD分辨率大小,然后通过LVGL在线转换工具进行转换,选择CF_RGB565A8,但是这种格式生成的RGB565会多出1个字节各一个,可以自己删除后,通过代码调用即可:
https://lvgl.io/tools/imageconverter
显示马的图片代码:
convert8to16();
ILI9341_FillPic(0, 0, OV7670_FRAME_WIDTH-1u, OV7670_FRAME_HEIGHT-1u, (uint16_t *)(horse16));
显示结果:
图4
关于RT1050-EVKB,使用flexIO采集OV7670数据,并通过TFT LCD显示情况。具体代码情况请查看视频。检查附加的源代码。从视频结果可以看到,flexIO OV7670摄像头数据可以成功显示,代码可以成功运行该功能。