UART串口传图LCD显示----图像处理

UART串口传图LCD显示----图像处理

设计介绍

首先需要准备一个txt文本,里面存储一个16进制200* 200的图片数据,通过串口调试助手使用串口传输一个200* 200图片,然后通过开发板上的480* 272LCD屏幕显示此图片(数据格式为RGB565)。本篇博客也是图像处理的基础篇,在此基础上可以做一些图像处理项目然后通过LCD屏幕观察实验效果。整体效果如下图所示,因为图片大小为200* 200而显示屏为480* 272,所以剩余部分填充为黑色。
在这里插入图片描述

设计思路

通过串口接收模块输出的po_flag信号高电平作为写使能,po_data信号作为写数据,往lcd显示模块中的RAMIP核中写入200*200个图片数据,然后通过po_flag信号低电平作为读使能从RAMIP核中读出数据,通过LCD屏幕显示(这里为了方便,写使能和读使能采用一个数据线的高低电平,要是不理解可以看一下RAMIP核的使用方法)。下图为整体设计流程框图。
在这里插入图片描述
工程生成rtl视图如下所示。
在这里插入图片描述

具体设计步骤

下面代码所实现的就是把一个500* 500RGB888格式图片转换为200* 200RGB332格式的图片(数据位宽为8位)然后生成TXT文本,为什么要转换成RGB332格式而不是RGB565格式的呢,因为怕麻烦哈哈,RGB332格式数据为8位,串口一字节就传输过去了,要是RGB565格式的数据为16位,需要串口传输两个字节的数据然后进行拼接。在LCDdisplay模块将串口输出的RGB332格式得8位数据转换成RGB565格式得16位数据然后传递给下一模块。

500* 500RGB888转换为200* 200RGB332代码如下(不懂可以看注释很详细哈哈)

clc;
clear;
img = imread('cat.jpg');
i = imresize(img,[200,200]); %500*500的图片裁剪为200*200的图片
 
R1 = i(:,:,1);
G1 = i(:,:,2);
B1 = i(:,:,3);
R2 = R1/32 - 1 ;             %8位的R分量数据按比例转换为3位数据,以数据255为例255/32-1=6.968取整为7
G2 = G1/32 - 1 ;             %8位的G分量数据按比例转换为3位数据
B2 = B1/64 - 1 ;             %8位的B分量数据按比例转换为2位数据
b = uint8(zeros(200,200));   %产生一个大小200*200数据位宽为8位的全零矩阵b
b = bitor(bitand(bitshift(R2, 5),224),b); %十进制 224 为二进制 1110 0000
%上一条语句执行的操作如下条注释
%以R2的数据为7(二进制位111)为例 左移五位为1110_0000然后和28(二进制位1110_0000)相与然后再和0000_0000相或最后结果为1110_0000
b = bitor(bitand(bitshift(G2, 2),28),b); %十进制 28 为二进制   0001 1100
b = bitor(bitand(bitshift(B2, 0), 3),b); %十进制 3 为二进制    0000 0011

fid=fopen('data_2.txt','w+'); %打开data_2.txt文件返回句柄
fprintf(fid,'%02x ',b') ;     %将图像转置行列对换(默认matlab 是11列打印会导致图像竖着的),向文件中写入16进制字符数据两个数据间加空格,为了串口发送做准备

figure(1)
subplot(1,3,1);imshow(img),title('原始图像'); %显示原始图像500*500*3
subplot(1,3,2);imshow(i),title('裁剪后图像'); %显示裁剪后图像200*200*3
subplot(1,3,3);imshow(b),title('修改后图像'); %显示裁剪后图像200*200*1

最后生成的TXT文本如下所示,其中就是8位的16进制图像数据。(只截取了一部分)
在这里插入图片描述

串口输出数据写入LCDdisplay模块的RAM中程序设计

这里就不一点点写代码了全部代码可以上资源里下载免费的哦,思路就是使用串口输出的po_flag信号的高电平作为RAM的写使能,低电平作为RAM的读使能。

写地址部分代码

//产生写地址
always @(posedge clk_50 or negedge sys_rst_n) begin
	if (sys_rst_n == 1'b0) begin
		// reset
		addra <= 'd0;
	end
	else if (pi_flag == 1'b1 && addra == 'd39999) begin
		addra <= 'd0;
	end
	else if (pi_flag == 1'b1) begin
		addra <= addra + 1'b1;
	end
end

读地址部分代码

//当前像素点坐标位于图案显示区域内时,读RAM使能信号拉高
assign ram_rd_en = (pixel_xpos >= POS_X) && (pixel_xpos < POS_X + WIDTH)
                    && (pixel_ypos >= POS_Y) && (pixel_ypos < POS_Y + HEIGHT)
                     ? 1'b1 : 1'b0;

//控制读地址
always @(posedge s_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n) begin
        ram_addr   <= 16'd0;
    end
    else if(ram_rd_en) begin
        if(ram_addr < TOTAL - 1'b1)
            ram_addr <= ram_addr + 1'b1;    //每次读ROM操作后,读地址加1
        else
            ram_addr <= 1'b0;               //读到ROM末地址后,从首地址重新开始读操作
    end
    else
        ram_addr <= ram_addr;
end

RGB332数据换为RGB565代码

assign  doutb_b = { doutb[7:5],2'b00,doutb[4:2],3'b000,doutb[1:0],3'b000} ;

把8位doutb的RGB三个分量的数据分别对应到16位的doutb_b上不够的位数补零
虽然这种方法还是有一些缺陷但是比价简单后面会接着更新比较严谨的转换方法

RGB565图像数据输出

//根据当前像素点坐标指定当前像素点颜色数据,在屏幕上显示彩条
always @(posedge s_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n)
        pixel_data <= 16'd0;
    else begin
	      if((pixel_xpos >= 10'd140) && (pixel_xpos <= 10'd339) && (pixel_ypos >= 10'd36) && (pixel_ypos <= 10'd235))      //显示图片区域                                            
            pixel_data <= doutb_b;
        else 
		      pixel_data <= BLACK;				
    end
end

这里需要注意RAM读出数据会落后地址一拍需要处理好从RAM中读出数据的问题。

上板验证

将data_2.txt文件中数据拷贝到串口调试助手然后发送,如下图所示,点击发送。
在这里插入图片描述
等一会观察LCD显示屏上就会出现一个200* 200的图片了如下图所示。哈哈 代码可以私信我啊。
在这里插入图片描述

  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,这是一个比较复杂的需求,需要用到摄像头、图像处理和二维码识别等技术。不过,我们可以尝试使用一些现成的库来实现它。 首先,您需要在ESP32上安装支持摄像头和micropython的固件。然后,您需要安装以下库: - `utime`:用于延时等待。 - `framebuf`:用于显示图像。 - `ujson`:用于解析二维码数据。 - `machine`:用于控制硬件。 安装上述库后,您可以使用以下代码进行扫描二维码并显示图像: ```python import sensor import image import lcd import time import ujson from machine import UART # 初始化摄像头和LCD sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) sensor.set_vflip(True) sensor.run(1) lcd.init() # 初始化串口连接 uart = UART(2, baudrate=115200, tx=17, rx=16, timeout=2000) # 初始化二维码识别器 qr_decoder = image.ImageReader("/sd/qrcode.lstm") # 显示摄像头内容,并等待识别二维码 while True: img = sensor.snapshot() lcd.display(img) try: # 查找二维码 code = img.find_qrcode() if code: # 获取二维码信息 qr_data = qr_decoder.decode(code[0]).replace(b'\n', b'') # 显示二维码信息 lcd.draw_string(0, 0, "QR Data: %s" % qr_data, lcd.WHITE, lcd.BLACK) # 发送数据到串口 uart.write(ujson.dumps({'data': qr_data.decode()}).encode()) break # 找到二维码后退出 except Exception as e: print(e) time.sleep(0.1) # 关闭连接和摄像头 uart.deinit() sensor.shutdown() ``` 在这个例子中,我们使用了`sensor`和`image`库来控制摄像头和图像处理,使用`lcd`库来显示图像和二维码信息,使用`UART`连接来发送数据。我们还使用了一个预训练的二维码识别模型`/sd/qrcode.lstm`来识别二维码。 这是一个简单的例子,您可以根据自己的需求进行修改和扩展。注意,在使用摄像头和图像处理时,需要考虑到硬件性能和内存占用等问题。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值