一,文章简介
关于RT10XX flexIO采集OV7670摄像头数据,并且在TFT LCD显示的情况,其实NXP官网已经有一篇非常好的应用笔记AN12686,只是测试是基于RT1010并且不是EVK,可能实际客户直接测试比较困难。笔者在支持客户的时候,遇到客户想在RT1050 EVK上实现flexIO采集并口OV7670数据并且显示在TFT LCD,也就是SPI接口的LCD上,所以本文给出了具体的测试已经成品结果,RT1050 flexIO和RT1010 flexIO有些区别,RT1010 flexIO是8 shifter,但是RT1050只有4 shifter,所以需要做一些代码修改,并且移植到RT1050上。由于要运行在MIMXRT1050-EVKB 上,所以还需要考虑能使用的flexIO引脚,并且修改EVKB,手工焊接相关的引脚来配置对应的摄像头信号和LCD显示信号。
本篇文章主要来自客户测试遇到问题,所以提供具体的硬件连接,软件代码分享,测试成品结果等。
二,软硬件配置情况
由于AN12686已经非常详细的给出了原理,所以本文旨在给出不同点,以及RT1050-EVKB上工作的具体情况。
2.1 硬件配置
平台基于MIMXRT1050-EVKB revA1,OV7670模组,2.4寸TFT LCD LCD SPI串口触摸TFT彩屏ILI9321,分辨率为240*320。
OV7670模组情况以及引脚情况可以查看文章:
【朝花夕拾】RT1050CSI OV7670摄像头eLCDIF显示
摄像头引脚情况如下:
图 1
TFT LCD情况如下:
图 2
对于LCD,本文只用显示部分,不用粗模部分。
考虑到MIMXRT1050-EVKB的引脚布置情况,这里不采用应用笔记flexIO1,而是选择FlexIO2 ,下面给出实际RT1050-EVKB 与OV7670模组以及LCD连接引脚情况。
LCD信号引脚与MCU MIMXRT1050-EVKB RevA1信号引脚连接情况如下:
为了减少信号的影响,MIMXRT1050-EVKB去掉板上R323,R316,R309,D6。
实物连接情况如下:
图 3
2.2 软件配置
由于RT1050的flexIO 是4个shifter和RT1010的8个shifter不同,所以在配置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存储数据到buffer,然后统一显示一帧数据到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摄像头数据,代码能够成功运行功能。
RT1050 FlexIO OV7670
代码源码查看连接:
https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/RT1050-FlexIO-OV7670-with-TFT-LCDdisplay/ta-p/1752280