基于STM32F103的二维码识别项目——TFTLCD屏幕篇

无线手持二维码识别项目是中山大学电子与信息工程学院(微电子学院)的工程应用训练课程的设计要求。项目是基于STM32F103开发的,开源代码:stm32f103zet6-qrcode-detect,bilibili:基于STM32F1的无线手持二维码识别项目。CSDN总目录:基于STM32F103的二维码识别项目。项目移植了Zbar库进行二维码识别,而非使用二维码识别模块。

此篇文章讲述TFTLCD相关的设计。

一、 TFT-LCD概述

TFT-LCD(Thin Film Transistor)液晶显示屏是薄膜晶体管型液晶显示屏,也就是“真彩”(TFT)。TFT液晶为每个像素都设有一个半导体开关,每个像素都可以通过点脉冲直接控制,因而每个节点都相对独立,并可以连续控制,不仅提高了显示屏的反应速度,同时可以精确控制显示色阶。市面上的TFT-LCD有不同的芯片驱动类型,如:ILI9341 / ILI9325 / RM68042 等等。

博主使用的是ILI9341驱动的TFTLCD,使用的是SPI的方式传输数据。
在这里插入图片描述

二、 RGB565

在这里插入图片描述

举例帮助理解:

0xF800,对应二进制1111 1000 0000 0000,高5位都是1,其他位都是0,全是红色分量,没有另外两种颜色的分量,因此0xF800表示的就是纯红色。

0x07D0,对应二进制0000 0111 1110 0000,中6位都是1,其他位都是0,全是绿色分量,没有另外两种颜色的分量,因此0xF800表示的就是纯绿色。

0x001F,对应二进制0000 0000 0001 1111,后5位都是1,其他位都是0,全是蓝色分量,没有另外两种颜色的分量,因此0x001F表示的就是纯蓝色。

三、 关键指令

在这里插入图片描述
所有指令和大部分操作参数都是8位的,但是它们整体是16位的,只是高8位无效而已,另外,RGB565的颜色数据也是16位的,而且,颜色数据是主要的数据源,所以我们在使用DMA时,可以将操作的数据位数设置成16位的,从而实现统一操作。

现在我们就能明白为什么代码中有 &0XFF 的操作,因为我们需要的是低8位。

color=GPIOF->IDR&0XFF;	//读数据

下面具体介绍一些常用指令。

1. 0xD3指令

在这里插入图片描述

顺序列:这一列说明的是发指令还是读参数;

控制列:表示发送当前数据时,各控制位需要处于什么样的状态,例如第一行发送指令时,RS要置0,RD要置1,WR是有效的并且会在上升沿时写入;

各位描述列:指令对应的控制字。

HEX列:各位描述列对应的十六进制数。

注意:发指令时RD置1,在WR的上升沿写入;读参数时WR置1,在RD的上升沿读出;

2. 0x36指令

在这里插入图片描述

这个指令用来控制GRAM自增方向。这里的三种关键控制位MY,MX,MV,决定了GRAM自增的方向,也就是LCD的扫描方向。这个指令很重要。正常我们如果想要往LCD上刷个像素点,就设置该点的坐标,然后刷上颜色值。如果是想要刷一个区域的点最基础的方式就只能是设置一下坐标,刷一个点,再设置一下坐标,再刷一个点……如此循环往复,一次刷一个点,每次都要设置坐标。

GRAM自增指令就能让我们只用设置一个整体区域的开始和结束坐标,然后发送颜色数据时,GRAM坐标就会自动增长。这也是我们实现批量发送颜色数据的重要基础,我们可以通过DMA将数据批量发送出去,LCD收到数据时,就会按照设置好的坐标来刷新屏幕。

MY,MX,MV不同的设置带来的后果如下图。

在这里插入图片描述

在这里插入图片描述

我们来看代码,可以看到代码封装为了一个 LCD_direction 函数,所以使用者能直接改变 direction 的值而无需关心底层实现。注释有写出BGR,MY,MX,MV的取值,对应上表可以很清晰地看出表达的意思。

void LCD_direction(u8 direction)
{ 
			lcddev.setxcmd=0x2A;
			lcddev.setycmd=0x2B;
			lcddev.wramcmd=0x2C;
	switch(direction){		  
		case 0:						 	 		
			lcddev.width=LCD_W;
			lcddev.height=LCD_H;		
			LCD_WriteReg(0x36,(1<<3)|(0<<6)|(0<<7));//BGR==1,MY==0,MX==0,MV==0
		break;
		case 1:
			lcddev.width=LCD_H;
			lcddev.height=LCD_W;
			LCD_WriteReg(0x36,(1<<3)|(0<<7)|(1<<6)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
		break;
		case 2:						 	 		
			lcddev.width=LCD_W;
			lcddev.height=LCD_H;	
			LCD_WriteReg(0x36,(1<<3)|(1<<6)|(1<<7));//BGR==1,MY==0,MX==0,MV==0
		break;
		case 3:
			lcddev.width=LCD_H;
			lcddev.height=LCD_W;
			LCD_WriteReg(0x36,(1<<3)|(1<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
		break;	
		default:break;
	}		
}	 

3. 0x2A指令

设置x的开始和x的结束坐标
在这里插入图片描述

4. 0x2B指令

设置y的开始和y的结束坐标

在这里插入图片描述

我们来看代码,lcddev.setxcmd 就是设置 x 坐标的,lcddev.setycmd 是设置 y 坐标的。封装好了后直接通过 LCD_SetWindows 函数的 xStar 和 yStar传入进行修改,达到了设置窗口位置的效果。

void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{	
	LCD_WR_REG(lcddev.setxcmd);	
	LCD_WR_DATA(xStar>>8);
	LCD_WR_DATA(0x00FF&xStar);		
	LCD_WR_DATA(xEnd>>8);
	LCD_WR_DATA(0x00FF&xEnd);

	LCD_WR_REG(lcddev.setycmd);	
	LCD_WR_DATA(yStar>>8);
	LCD_WR_DATA(0x00FF&yStar);		
	LCD_WR_DATA(yEnd>>8);
	LCD_WR_DATA(0x00FF&yEnd);

	LCD_WriteRAM_Prepare();	//开始写入GRAM			
}   

5. 0x2C指令

GRAM是否自增是这个指令决定的,上面的0x36设置的是自增的方向。
在这里插入图片描述

6. 0x2E指令

在这里插入图片描述

四、 核心程序

当你买了一块TFTLCD屏幕后,跟商家要一下程序例程即可,一般来说商家都会给你封装成易于使用的函数,无需你自己手动进行海量的底层编写。所以我们只需要管上层应用即可。

我们来看二维码识别时核心的部分:如何实现摄像头的内容显示到TFTLCD上:

if(ov_sta)//有帧中断更新
	{
		LCD_direction(1);
		LCD_SetWindows(0,0,320-1,240-1);
		
		OV7670_RRST=0;				//开始复位读指针 
		OV7670_RCK_L;
		OV7670_RCK_H;
		OV7670_RCK_L;
		OV7670_RRST=1;				//复位读指针结束 
		OV7670_RCK_H;

		u32 a = 0;
					
		for(j=0;j<76800;j++)   //此种方式需清楚TFT内部显示方向控制寄存器值 速度较快
		{
			OV7670_RCK_L;
			color=GPIOF->IDR&0XFF;	//读数据
			OV7670_RCK_H; 
			color<<=8;  
			OV7670_RCK_L;
			color|=GPIOF->IDR&0XFF;	//读数据
			OV7670_RCK_H;
			
			//二值化
			if(color > 0x4500)
			{
				color = 0xffff;
				colorQR = 0xff;
			}
			else
			{
				color = 0x0000;
			  colorQR = 0x00;
			}


          // 检查是否在范围内
          if ((j <= 239) || (j >= 320 && ((j - 320) % 320 <= 239))) {
            // 在范围内,执行你的操作
           data_buf[a] = colorQR;
		   a++;
		   Lcd_WriteData_16Bit(color);
           }
			else {Lcd_WriteData_16Bit(0xffff);}//白色
		}  
	} 
}

检查是否在范围内的部分是我为了减轻RAM的负担,让处理二维码的区域变为240×240。二值化的部分去掉就是正常的视频显示。

具体代码见开源链接的 lcd.c,SPI.c

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值