单片机车道线检测模型(3)——外设(摄像头、LCD)

本篇文章为车道线检测模型系列文章的第三篇,第一篇介绍了模型所使用的单片机和开发板,第二篇介绍了实时操作系统RT-Thread,想了解的朋友点击:
(一)https://blog.csdn.net/weixin_42967006/article/details/106687245
(二)https://blog.csdn.net/weixin_42967006/article/details/106688601
本篇将为大家介绍本次用到的两个外设:OV2640摄像头和3.2寸LCD触摸屏

一、OV2640摄像头模块

1.简介

OV2640有200W像素,可选广角,带补光灯,不支持自动调焦,本次买的模块使用3.3V供电。
OV2640在通讯上有两种方式,一种是写指令寄存器的时候,用SCCB协议,SCCB是一种和IIC类似但又不完全相同的通讯协议,因为只在初始化的时候对寄存器进行配置时使用,所以通常就用GPIO模拟了,浪费一点单片机资源也影响不大。另一种通讯方式就是传输图像像素的时候使用的DCMI接口,采用8bit并口,结合帧同步、行同步和像素同步等信号来完成图像的传输。STM32F4系列单片机集成了DCMI接口,但我这次用到的AT32F403和STM32F1系列都不支持DCMI接口,只能用GPIO模拟。

下面链接中是我用到的OV2640的驱动,供参考,在使用的时候只需要根据单片机不同更改初始化函数中的GPIO配置函数,以及ov2640.h和SCCB.H中的引脚配置即可:
https://download.csdn.net/download/weixin_42967006/12514367

2.图像输出设置

OV2640输出图像大小的设置涉及到驱动中这样几个函数:

  • 传感器窗口设置(OV2640_Window_Set)
  • 图像尺寸设置(OV2640_ImageSize_Set)
  • 图像窗口设置(OV2640_ImageWin_Set)
  • 图像输出大小设置(OV2640_OutSize_Set)
    关系如下图所示,通常来说我们只需要调整OV2640_ImageWin_Set和OV2640_OutSize_Set,前者决定在图像的什么位置取多大的窗口,后者决定将窗口缩放为多大的图像,再做输出。
    在这里插入图片描述
    网上有很多原子哥的驱动代码,大部分都可以用,但有一个问题值得注意,就是有一个寄存器0x50的值原子哥的代码中设置为了0,这样的结果是当使用OV2640_OutSize_Set调整图像输出大小后,如果输出大小和窗口大小不一致,输出图像不会进行缩放,而是从输出窗口的左上角开始截取想要的大小,导致输出的图像不在摄像头采集图像的正中,发生偏移。解决办法是将寄存器0x50的值设置为0x89,如下,之后就可以对采集到的图像缩放后再输出了。
	SCCB_WR_Reg(0XFF,0X00);
	SCCB_WR_Reg(0X50,0X89);

有关这个问题更详细的可以参考下面这个帖子:
http://www.openedv.com/posts/list/0/63099.htm

3.图像接收

在初始化完成后,开始接受图像数据时,可以参考下面的时序:

while(1)
{
	while(OV2640_VSYNC == 1) //帧同步信号,高代表正在传输帧数据
  	{
  		while(OV2640_HREF == 0 && OV2640_VSYNC == 1);
  		while(OV2640_HREF)//行同步信号,高代表正在传输行数据
       {
  			while(OV2640_PCLK == 0);
  			while(OV2640_PCLK == 1);//像素同步信号,高代表正在传输一个8位像素值
  			//在此处读取并存储像素值
  			ImageData = OV2640_DATA;
  		}
  	}
}

4.设置输出YUV422灰度图像

在车道线检测中通常只关心图像的轮廓,颜色意义不大,所以都以灰度图像作为源数据。OV2640支持直接输出YUV422格式的灰度图像,很方便,还节省了存储空间。设置方法如下:

void OV2640_YUV422_Mode(void)
{
	SCCB_WR_Reg(0xFF, 0x00);
	SCCB_WR_Reg(0xDA, 0x01);
}

设置完成后OV2640输出图像时会输出16bit的灰度值,我们只关心高字节即可(传输时低字节在前,高字节在后),接收函数如下:

  while(1)
  {
  	ImagePtr_W			= 0;
  	ImagePtr_H			= 0;
  	while(OV2640_VSYNC == 1);//丢弃传输到一半的图像
  	while(OV2640_VSYNC == 0);
  	while(OV2640_VSYNC == 1) //开始采集jpeg数据
  	{
  		ImagePtr_W			= 0;
  		while(OV2640_HREF == 0 && OV2640_VSYNC == 1);
  		while(OV2640_HREF)
        {
  			while(OV2640_PCLK == 0);
  			while(OV2640_PCLK == 1);
  			while(OV2640_PCLK == 0);
  			ImageData(ImagePtr_H, ImagePtr_W) = OV2640_DATA;
  			while(OV2640_PCLK == 1);
  			++ImagePtr_W;
  		}
  		++ImagePtr_H;
  	}

5.灰度图像与RGB565格式之间的相互转换

顺便研究了一下RBG565和YUV422格式之间的转化,注意这里的YUV422是16位的,和我们前文直接取的高字节不是一个概念。
RGB565转化为YUV422:

#define RGB565_RED      0xf800
#define RGB565_GREEN    0x07e0
#define RGB565_BLUE     0x001f
u16 RGB565_to_Gray(u16 RGB)
{
  u16 Gray;
  u16 R  = (RGB & RGB565_RED)    >> 3+8;
  u16 G  = (RGB & RGB565_GREEN)  >> 5;
  u16 B  = (RGB & RGB565_BLUE)   ;
  Gray=(u16)(( R*77 +  G * 150 +  B * 29 +128 )/256);
  return Gray;
}

YUV422转化为RGB565:

u16 yuv422_to_RGB565Gray(u16 yuv422)
{
	u16 Gray;
	Gray =(((yuv422>>(8+3))<<11)|((yuv422>>(8+2))<<5)|((yuv422>>(8+3))<<0));
	return Gray;
}

因为通常LCD显示还是需要RGB565格式,所以可能还需要将YUV422转化为RGB565格式,虽然格式不同但也还是灰色的。
有关OV2640的内容就是这些了,本文最后会和LCD一起贴一个本项目的引脚定义,可以结合驱动代码一起参考。

二、LCD

1.简介

本次使用的是3.2寸触摸屏,LCD驱动芯片是ILI9341,通信接口采用16位8080接口,触摸屏控制芯片是XPT2046,通讯接口是SPI,驱动中是用GPIO模拟的SPI。驱动程序如下:
https://download.csdn.net/download/weixin_42967006/12514444

2.使用

LCD的横竖屏和8位数据线还是16位数据线可以通过LCD.h中的以下两个宏定义来设置:

#define USE_HORIZONTAL  	0	//定义是否使用横屏 		0,不使用.1,使用.
#define LCD_USE8BIT_MODEL   0    //定义数据总线是否使用8位模式 0,使用16位模式.1,使用8位模式

在显示图像前需要先初始化,在之后的显示过程中主要有以下几个函数比较常用:

//设置显示图像的窗口大小,必须先设置大小再发送像素数据
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd);
//设置当前坐标值,设置完成后,再写入一个像素值,LCD就会在设置的坐标位置显示写入的像素
void LCD_SetCursor(u16 Xpos, u16 Ypos);
//向当前坐标处写一个像素值
void LCD_DrawPoint_16Bit(u16 color);
//显示一幅16位真彩图像
void LCD_Drawbmp16(u16 x,u16 y,u16 width,u16 length,const unsigned char *p);

这里分享一个图片取模软件,可以直接生成.h文件中的数组,作为上面最后一个函数的*p输入即可,下载链接:
https://download.csdn.net/download/weixin_42967006/12514757
使用方法:
在这里插入图片描述
有关LCD没有太多需要注意的地方,就是模块引脚太多了,接线的时候要十分细心,我当时就是因为接线接错了被卡了一段时间。只要硬件连接没问题,用上面的驱动程序应该是可以正常显示和触摸的。关于触摸有一点需要注意的是按下屏幕时会存在类似于按键的抖动问题,如果想避免这种情况,就需要像按键一样做一个消斗的步骤。

贴一张本项目的简要引脚图,绿色是LCD的引脚,黄色是OV2640的引脚,供参考:
在这里插入图片描述
最后来几张集成好的图吧,接了摄像头和LCD之后,电流可能较大,最好采用外部电源供电,避免用AT-Link供电:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老孟的孟不是很老的孟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值