[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA基础篇连载-29基于FPGA实现触摸屏实验

文档创建者:FPGA课程
浏览次数:269
最后更新:2024-09-05
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-FPGA部分 » 2_FPGA实验篇(仅旗舰) » 1-FPGA基础入门实验
本帖最后由 FPGA课程 于 2024-9-5 10:11 编辑

​ 软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!



1概述
常规情况下我们会使用CPU通过I2C接口实现触控液晶触摸方案的实现,也可以上LINUX,一般LINUX下也有对于各大厂家触摸液晶屏的方案支持。但是如果我们在一些情况下不方便使用CPU或者我们压根不会使用CPU的方式或者也不会LINUX的方式,我们要实现一些简单的触摸控制,用FPGA实现是不是没有办法吗?答案当然是“NO”。因为通过对触摸液晶的硬件分析和驱动代码分析,笔者发现只要通过I2C接口实现对触摸液晶寄存器的控制和访问一样可以实现液晶屏的触控。笔者前面已经编写了非常好的I2C控制器,实现了EEPROM和RTC时钟芯片的读取,那么在本文中,我们也可以利用这个控制器实现和液晶屏触控芯片的通信。
关于I2C总线的细节笔者就不再介绍了,读者如果没有掌握好,请学习我们前面相关课程。
2GT9X系列触摸芯片使用2.1接口说明
GT9 非单层多点系列(以下简称GT9 系列)与主机接口共有6 PIN,分别为:VDD、GND、SCL、SDA、INT、RESET。
主控的INT 口线需具有上升沿或下降沿中断触发功能,并且当其在输入状态时,主控端必需设为悬浮态, 取消内部上下拉功能;主机通过输出高、低来控制GT9 系列的RESET口为高或低。为保证可靠复位,建议RESET 脚输出低100μ s 以上。
GT9 系列与主机通信采用标准I2C 通信,最高速率可以支持至400K bps。当主机采用200K 以上的通信速率时,需要特别注意I2C 口的外部上拉电阻阻值,以保证SCL、SDA 边沿足够陡峭。GT9 系列在通信中始终作为从设备,其I2C 设备地址由7 位设备地址加1 位读写控制位组成,高7 位为地址,bit 0 为读写控制位。GT9 系列有两个从设备地址可供选择,如下表:
                        
模式
                        
                        
7 位地址
                        
                        
8 位写地址
                        
                        
8 位读地址
                        
                        
1
                        
                        
0x5D
                        
                        
0XBA
                        
                        
0XBB
                        
                        
2
                        
                        
0x14
                        
                        
0X28
                        
                        
0X29
                        
这里大家可能奇怪有2套地址,这个地址触摸芯片会根据硬件电路对于INT脚的配置采用那一套地址。当INT在上电期间是低电平则使用模式1;当INT在上电期间是高电平则使用模式2;
2.2寄存器写时序
232b690d78764cfd880c5948c1187075.jpg
S:起始信号。
Address_W:带写控制位的从设备地址。
ACK:应答信号。
Register_H、Register_L:待写入的16 位寄存器首地址。
Data_1 至Data_n:数据字节1-n。
E:停止信号。
设定了写操作寄存器首地址后,可以只写1 字节数据,也可以一次性写入多个字节数据,GT9 系列自动将其往高地址顺序存储。
2.3寄存器读时序
先通过前述写操作时序设定需要读取的寄存器首地址,重新发送起始信号进行读寻址,读取寄存器数据。
3ca02e44fc1743a9a261bb40764edbe9.jpg
Address_R:带读控制位的从设备地址。
NACK:最后1 字节读完主控回NACK。
设定了读操作寄存器地址后,主控可以一次读取1 字节,也可以一次性读取多个字节数据,GT91XX 自动递增寄存器地址,将后续数据顺序发送。
设定完读操作寄存器地址后的停止信号(上图中的第一个E 信号)可发可不发,但是重新开始I2C 通信的起始信号必须再次发送。
2.4重要寄存器
我们这里只对使用到的寄存器进行说明,没有使用到的,可以看我整理的资料里面有一个“GT9非单层多点系列编程指南文件.pdf”的文档比较详细描述了GT9X的触摸芯片如何使用。
                        
寄存器
                        
                        
命令
                        
                        
描述
                        
                        
0X8040
                        
                        
Command
                        
                        
0:读坐标状态           1:差值原始值           2:软件复位
                        
3:基准更新(内部测试) 4:基准校准(内部测试) 5:关屏
                        
其余值无效
                        
                        
0X8047
                        
                        
Config_ Version
                        
                        
配置起始地址寄存器,配置文件的版本号(新下发的配置版本号大于原版本,或等于原版本号但配置内容有变化时保存,版本号版本正常范围:'A'~'Z',发送0x00则将版本号初始化为'A')
                        
                        
0X80FF
                        
                        
Config_Chksum
                        
                        
校验和寄存器,配置信息校验(0x8047到0x80FE之字节和的补码)
                        
                        
0X8140
                        
                        
Product ID
                        
                        
产品ID寄存器
                        
                        
0X814E
                        
                        
触摸状态寄存器
                        
                        
Bit7: Buffer status,1表示坐标(或按键)已经准备好,主控可以读取;0表示未就绪,数据无效。当主控读取完坐标后,必须通过I2C将此标志(或整个字节)写为0。
                        
Bit4: HaveKey, 1表示有按键,0表示无按键(已经松键)。
                        
Bit3~0: Number of touch points, 屏上的坐标点个数
                        
                        
0X8150
                        
                        
第1个触摸点X
                        
                        
X坐标低字节
                        
                        
0X8151
                        
                        
第1个触摸点X
                        
                        
X坐标低字节
                        
                        
0X8152
                        
                        
第1个触摸点Y
                        
                        
Y坐标低字节
                        
                        
0X8153
                        
                        
第1个触摸点Y
                        
                        
Y坐标高字节
                        
                        
0X8158
                        
                        
第2个触摸点X
                        
                        
X坐标低字节
                        
                        
0X8159
                        
                        
第2个触摸点X
                        
                        
X坐标低字节
                        
                        
0X815A
                        
                        
第2个触摸点Y
                        
                        
Y坐标低字节
                        
                        
0X815B
                        
                        
第2个触摸点Y
                        
                        
Y坐标高字节
                        
                        
0X8160
                        
                        
第3个触摸点X
                        
                        
X坐标低字节
                        
                        
0X8161
                        
                        
第3个触摸点X
                        
                        
X坐标低字节
                        
                        
0X8162
                        
                        
第3个触摸点Y
                        
                        
Y坐标低字节
                        
                        
0X8163
                        
                        
第3个触摸点Y
                        
                        
Y坐标高字节
                        
以上就是我们主要用到的寄存器,由于我们默认采用1024X600分辨率,所以0X8047,0X80FF ,0X8140寄存器也是无需考虑的。
2.5上电时序
主机上电后,需要控制GT9X的AVDD、VDDIO、INT、Reset等脚位,控制时序请遵从如下时序图:
5f903b315524447e8b6ddfb679266575.jpg
1)、INT T2 时间后,主控是要输出高,还是低,取决于主机要用何I2C 从设备地址与GT9 芯片通信,若用地址0x28/0x29,则输出高;若用地址0xBA/0xBB,则输出低。
2)、主机控制GT9上电过程中,当主控将自身INT 转化为悬浮输入态后,需要延时50ms 再发送配置信息。
2.6坐标读取
本文的设计方案采用轮询的方式读取触控液晶的坐标寄存器,当然也可以采用更高效的中断方式。读者可以去尝试下。以下是关于中断方式和轮询方式的方法介绍。
主控可以采取轮询或INT 中断触发方式来读取坐标,采用轮询方式时可采取如下步骤读取:
1、按第二节时序,先读取寄存器0x814E,若当前buffer(buffer status 为1)数据准备好,则依据手指个数读按键状态取相应个数的坐标、按键信息。
2、若在1中发现buffer 数据(buffer status 为0)未准备好,则等待1ms 再进行读取。
采用中断读取方式,触发中断后按上述轮询过程读取坐标。
GT9 中断信号输出时序为(以输出上升沿为例,下降沿与此时序类同):
1、 待机时INT 脚输出低。
2、 有坐标更新时,输出上升沿。
3、2 中输出上升沿后,INT 脚会保持高直到下一个周期(该周期可由配置Refresh_Rate 决定)。请在一个周期内将坐标读走并将buffer status(0x814E)写为0。
4、2 中输出上升沿后,若主控未在一个周期内读走坐标,下次GT9 即使检测到坐标更新会再输出一个INT 脉冲但不更新坐标。
5、若主控一直未读走坐标,则GT9会一直打INT 脉冲。
2.7工作模式
关于GT9芯片的工作模式,本文中使用的是Normal模式,下面是关于各种模式的介绍。
GT9 工作模式分为Normal、Low Power(Green)、Sleep 三种,各种工作状态间相互转换关系如下图所示:
399c01bfb2b04d9788a73c7c17c1636d.jpg


默认情况下,GT9 工作自动切换Normal 和Low Power 工作模式,按键时及松键后的一段时间(这段时间由配置参数Low_Power_Control 设定,0~15 秒可设)工作在Normal mode,若该段时间后还处于无按键状态,则进入Low Power 工作模式(低速扫描)
Normal 模式
GT9 在Normal mode 时,最快的坐标刷新周期为5ms-20ms 间(依赖于配置信息的设定,配置信息可控周期步进长度为1ms)。
Normal mode 下,一段时间无触摸事件发生,GT9将自动转入Low Power mode,以降低功耗。GT9无触摸自动进入Low Power mode 的时间可通过配置信息设置,范围为0~15s,步进为1s。
Low Power(Green) mode
在LowPower mode 下,GT9扫描周期固定为40ms,若检测到有触摸动作发生,自动进入Normal mode。
Sleep mode及唤醒
主CPU通过I2C命令,使GT9进入Sleep mode(需要先将INT脚输出低电平)。当需要GT9退出Sleep mode时,主机可采用INT高电平唤醒或reset唤醒。若采用INT高电平唤醒,操作时序为:输出高电平到INT脚(主机打高INT脚2~5ms,然后转悬浮输入态),唤醒后GT9将进入Normal mode;当采用reset脚唤醒时,需要按前述上电初始化过程控制INT脚和reset脚。
3硬件电路分析
硬件接口和子卡模块请阅读“附录 1”
配套工程的 FPGA PIN 脚定义路径为 fpga_prj/uisrc/04_pin/ fpga_pin.xdc。
4系统框图
f2a60a97917345648768b2db9b7eb9c1.jpg

5触摸控制FPGA实现
5.1gt9xx_config.v程序源码
  1. /************************gt9xx_config 触控驱动控制器*********************
  2. --1.上电后通过控制IO_t_ini和O_t_rst对触控芯片的工作模式进行设置,设置器件地址为0XBA
  3. --2.状态机中,通过轮询方式,不断访问触控芯片,读取坐标,这里读取3组坐标信息
  4. *********************************************************************/

  5. `timescale 1ns / 1ns

  6. module gt9xx_config
  7. (
  8. input              I_clk,   //系统时钟输入
  9. input              I_rstn,  //系统复位
  10. output             O_t_rst,   //触控屏中断信号,也用于上电初始化
  11. inout              IO_t_ini,   //触控屏复位信号,也用于上电初始化
  12. output reg         O_iic_req, //I2C总线读写请求
  13. output reg [31:0]  O_wr_data, //I2C写数据
  14. output reg  [7:0]  O_wr_cnt,  //I2C写数据长度
  15. input      [31:0]  I_rd_data, //I2C读数据
  16. output reg  [7:0]  O_rd_cnt,  //I2C读数据长度
  17. input              I_iic_busy,//I2C总线忙
  18. output  [15:0]     O_tp1_x,   //触控坐标1 X轴坐标
  19. output  [15:0]     O_tp1_y,   //触控坐标1 y轴坐标
  20. output  [15:0]     O_tp2_x,   //触控坐标2 X轴坐标
  21. output  [15:0]     O_tp2_y,   //触控坐标2 y轴坐标
  22. output  [15:0]     O_tp3_x,   //触控坐标3 X轴坐标
  23. output  [15:0]     O_tp3_y    //触控坐标3 y轴坐标
  24. );

  25. `define GT_CTRL_REG     16'h4080    //GT9xx控制寄存器
  26. `define GT_CFGS_REG     16'h4780    //GT9xx配置起始地址寄存器   
  27. `define GT_CHECK_REG    16'hFF80    //GT9xx校验和寄存器
  28. `define GT_PID_REG      16'h4081    //GT9xx产品ID寄存器

  29. `define GT_GSTID_REG    16'h4E81    //GT9xx当前检测到的触摸状态寄存器
  30. `define GT_TP1_REG      16'h5081    //第一个触摸点数据地址  
  31. `define GT_TP2_REG      16'h5881    //第二个触摸点数据地址
  32. `define GT_TP3_REG      16'h6081    //第三个触摸点数据地址
  33. //`define GT_TP4_REG    16'h6881    //第四个触摸点数据地址
  34. //`define GT_TP5_REG    16'h7081    //第五个触摸点数据地址

  35. //reset counter for delay time

  36. reg         t_ini_r=0 ;
  37. reg [24:0]  rst_cnt = 25'd0;

  38. assign  O_t_rst = (rst_cnt[24] | rst_cnt[23]); // 触控芯片的复位,上电期间用于设置工作模式

  39. assign  IO_t_ini = (t_ini_r == 1'b0) ?  1'b0 : 1'bz; //中断信号上电期间用于设置工作模式

  40. //上电后复位计数器
  41. always@(posedge I_clk or negedge I_rstn) begin
  42.     if(I_rstn == 1'b0)
  43.         rst_cnt <= 0;
  44.     else if(!rst_cnt[24])
  45.         rst_cnt <= rst_cnt + 1'b1;
  46.     else
  47.         rst_cnt <= rst_cnt;
  48. end

  49. //触控芯片上电复位计数器
  50. always@(posedge I_clk  or negedge I_rstn) begin
  51.     if(I_rstn == 1'b0 || rst_cnt[24] == 1'b0)
  52.         t_ini_r <= 1'b0;   
  53.     else  if(rst_cnt[24])
  54.         t_ini_r <= 1'b1;
  55.     else
  56.         t_ini_r <= t_ini_r;
  57. end

  58. reg [3:0]TS_S; //状态机寄存器
  59. reg [7:0]i;    //计数器寄存器
  60. reg [47:0] touch_x; //X坐标寄存器,保存3组X坐标数据,每组16bits
  61. reg [47:0] touch_y; //X坐标寄存器,保存3组y坐标数据,每组16bits

  62. //把坐标分离开,方便观察和使用
  63. wire [15:0]touch_x1 = touch_x[15:0];  
  64. wire [15:0]touch_x2 = touch_x[31:16];
  65. wire [15:0]touch_x3 = touch_x[47:32];
  66. wire [15:0]touch_y1 = touch_y[15:0];
  67. wire [15:0]touch_y2 = touch_y[31:16];
  68. wire [15:0]touch_y3 = touch_y[47:32];

  69. assign O_tp1_x = touch_x1;
  70. assign O_tp1_y = touch_y1;
  71. assign O_tp2_x = touch_x2;
  72. assign O_tp2_y = touch_y2;
  73. assign O_tp3_x = touch_x3;
  74. assign O_tp3_y = touch_y3;

  75. reg [7 :0] ctstate; //坐标状态寄存器
  76. wire [47:0] GT9XX_TPX_TBL = {`GT_TP3_REG,`GT_TP2_REG,`GT_TP1_REG};//触控芯片相关寄存器初始化

  77. //vio 观察坐标
  78. vio_0 vio_dg (.clk(I_clk), .probe_in0(touch_x1), .probe_in1(touch_y1), .probe_in2(touch_x2), .probe_in3(touch_y2), .probe_in4(touch_x3), .probe_in5(touch_y3));
  79. //ila 在线逻辑分析仪观察状内部信号和状态机
  80. ila_0 ila_dg (.clk(I_clk),.probe0({TS_S,O_t_rst,O_iic_req,ctstate}));

  81. //状态机
  82. always@(posedge I_clk) begin
  83.     if(!rst_cnt[24])begin //复位初始化信号和寄存器
  84.         i         <= 8'd0;
  85.         O_iic_req   <= 1'b0;
  86.         O_rd_cnt    <= 8'd0;
  87.         O_wr_data[31:0] <= {24'd0,8'hba};//8'hba为芯片的器件地址
  88.         touch_x   <= 48'd0;
  89.         touch_y   <= 48'd0;
  90.         ctstate   <= 8'd0;
  91.         TS_S      <= 4'd0;   
  92.     end
  93.     else begin
  94.         case(TS_S)
  95.         0:begin//设置触控芯片的软件复位
  96.             O_iic_req  <= 1'b1; //发送I2C总线操作请求
  97.             O_wr_cnt   <= 8'd4; //写入4个数据
  98.             O_wr_data[23 :8] <= `GT_CTRL_REG; //GT9xx控制寄存器地址  
  99.             O_wr_data[31:24] <= 8'd2; //软件复位值
  100.             if(I_iic_busy)     //等在总线忙
  101.             TS_S    <= 4'd1; //下一个状态
  102.         end
  103.         1:begin //等待I2C总线空闲
  104.             O_iic_req  <= 1'b0;
  105.             if(!I_iic_busy)begin //等待I2C总线空闲,代表I2C操作完成,软件复位完成
  106.             TS_S    <= 4'd2;//下一个状态
  107.             end
  108.         end
  109.         2:begin//重置触控屏芯片的控制寄存器
  110.            O_iic_req  <= 1'b1;//发送I2C总线操作请求
  111.            O_wr_cnt  <= 8'd4;//写入4个数据
  112.            O_wr_data[23 :8] <= `GT_CTRL_REG;  //GT9xx控制寄存器地址   
  113.            O_wr_data[31:24] <= 8'd0; //重置控制寄存器为0
  114.            if(I_iic_busy)   //等在总线忙
  115.            TS_S    <= 4'd3; //下一个状态   
  116.         end        
  117.         3:begin //等待I2C总线空闲
  118.             O_iic_req  <= 1'b0;
  119.             if(!I_iic_busy)//等待I2C总线空闲,代表I2C操作完成,软件复位完成
  120.             TS_S    <= 4'd4;//下一个状态
  121.         end
  122.         4:begin//读取坐标值
  123.            O_iic_req  <= 1'b1;
  124.            O_wr_data[23 :8] <= `GT_GSTID_REG;  //GT9xx触摸状态寄存器
  125.            O_wr_cnt <= 8'd3;  //写入3个数据,器件地址,寄存器地址
  126.            O_rd_cnt <= 8'd1;  //读出1个数据,状态寄存器
  127.            i      <= 8'd0;  //i用于计数
  128.            if(I_iic_busy)     //等在总线忙
  129.            TS_S   <= 4'd5;  //下一个状态
  130.         end
  131.         5:begin //等待I2C总线空闲
  132.             O_iic_req  <= 1'b0;
  133.             if(!I_iic_busy)//等待I2C总线空闲,代表I2C操作完成,已经读到`GT_GSTID_REG状态寄存器
  134.             TS_S  <= 4'd6;//下一个状态
  135.         end
  136.         6:begin //判断状态寄存器
  137.             if(I_rd_data[7:0]&8'h80)begin //确认状态寄存器是否有触控事件发生
  138.             ctstate <= I_rd_data[7:0]&8'h07;//触控状态,有多少触控点事件发生
  139.             TS_S  <= 4'd7; //下一个状态
  140.             end
  141.             else
  142.             TS_S  <= 4'd4; //如果没有触控事件发生,继续回到前一个状态,继续读状态寄存器   
  143.         end        
  144.         7:begin//重置触控状态寄存器
  145.            O_iic_req  <= 1'b1;
  146.            O_wr_data[23 :8] <= `GT_GSTID_REG; //GT9xx触摸状态寄存器
  147.            O_wr_data[31:24] <= 8'd0; //设置寄存器值为0
  148.            O_wr_cnt <= 8'd4;  //I2C写入4BYTES
  149.            O_rd_cnt <= 8'd0;  //I2C不需要读数据
  150.            i      <= 8'd0;  //i计数器清零
  151.            if(I_iic_busy)     //等待总线忙 ,代表I2C控制器开始工作     
  152.            TS_S   <= 4'd8;
  153.         end
  154.         8:begin //等待I2C总线空闲
  155.             O_iic_req  <= 1'b0;
  156.             if(!I_iic_busy) //等待I2C总线空闲,代表I2C完成 `GT_GSTID_REG的重置
  157.             TS_S    <= 4'd9;
  158.         end        
  159.         9:begin //读取1个坐标
  160.             O_iic_req  <= 1'b1;
  161.             O_wr_data[23 :8] <= GT9XX_TPX_TBL[i*16 +: 16]; //坐标的寄存器地址  
  162.             O_wr_cnt <= 8'd3; //I2C 写3BYTES
  163.             O_rd_cnt <= 8'd4; //i2c 读4BYTES
  164.             if(I_iic_busy)//等待总线忙 ,代表I2C控制器开始工作     
  165.             TS_S    <= 4'd10;           
  166.         end
  167.         10:begin//等待I2C总线空闲
  168.             O_iic_req  <= 1'b0;
  169.             if(!I_iic_busy)//等待I2C总线空闲,代表I2C完成 GT9XX_TPX_TBL中对应的坐标寄存器读
  170.             TS_S    <= 4'd11;
  171.         end     
  172.         11:begin //保存坐标值
  173.             touch_x[i*16 +: 16] <= I_rd_data[15: 0];
  174.             touch_y[i*16 +: 16] <= I_rd_data[31:16];
  175.             i <= i + 1'b1;  //i计数器+1   
  176.             if(i<8'd2)      //判断本次是否读完3组坐标
  177.             TS_S <= 4'd9;   //如果没读完,继续读
  178.             else
  179.             TS_S <= 4'd4;   //如果读完了,回到状态4
  180.         end
  181.         default:TS_S <= 4'd0;   
  182.         endcase
  183.    end
  184. end

  185. endmodule
复制代码

5.2代码分析
以上代码中关键是利用了米联客开发的I2C控制器,然后结合我们前面对GT9X系列触控芯片寄存器的以及如何使用的认识,来通过I2C总线对GT9X系列芯片配置,和读取触控的坐标值。
状态0~3:是对控制寄存器配置,首先配置GT_CTRL_RE(0X8040)为2,对GT9X触控芯片软件复位,然后再配置GT_CTRL_REG为0,表示进入读坐标状态。
状态4~6:进入读坐标状态后,先读取GT_GSTID_REG(0X8047)寄存器的值,这个寄存器是保持了触控状态,当触摸液晶感知到已经被触控了,相关的寄存器位会被置位。
状态7~11:当我们通过4~6读取到了有触控行为发生,那么就读取相关坐标寄存器的值,我们这里只读取3组触控寄存器的值,这样就实现了3点触控
6实现三点触控图形绘制
  1. /************************uitpg 测试数据发生器*********************
  2. --1.该方案用于演示触控坐标读取方案
  3. --2.通过输入的坐标信息,产生RED BLUE GREEN 方格,当在触摸屏上移动手指,方格会跟随移动
  4. *********************************************************************/
  5. `timescale 1ns / 1ns //仿真时间间隔/精度

  6. module uitpg
  7. (
  8. input            I_tpg_clk, //系统时钟
  9. //input            tpg_rstn_i,//系统复位输入
  10. input            I_tpg_vs,  //场同步输入
  11. input            I_tpg_hs,  //行同步输入
  12. input            I_tpg_de,  //视频数据有效输入  
  13. output           O_tpg_vs,  //场同步输出
  14. output           O_tpg_hs,  //行同步输出
  15. output           O_tpg_de,  //视频数据有效输出   
  16. output [23:0]    O_tpg_data, //有效测试数据
  17. input  [11:0]    I_tp1_x,     //坐标1的X轴坐标
  18. input  [11:0]    I_tp1_y,     //坐标1的y轴坐标
  19. input  [11:0]    I_tp2_x,     //坐标2的X轴坐标
  20. input  [11:0]    I_tp2_y,     //坐标2的y轴坐标
  21. input  [11:0]    I_tp3_x,     //坐标3的X轴坐标
  22. input  [11:0]    I_tp3_y      //坐标3的y轴坐标
  23. );

  24. reg[7:0]r_reg = 8'd0; // red 颜色寄存器
  25. reg[7:0]g_reg = 8'd0; // green 颜色寄存器
  26. reg[7:0]b_reg = 8'd0; // blue 颜色寄存器

  27. reg tpg_vs_r = 1'b0;//对vs信号寄存
  28. reg tpg_hs_r = 1'b0;//对hs信号寄存

  29. reg [11:0]v_cnt = 12'd0; //场像素计数器
  30. reg [11:0]h_cnt = 12'd0; //行像素计数器

  31. always @(posedge I_tpg_clk)begin
  32.     tpg_vs_r <= I_tpg_vs; //对vs信号寄存一次
  33.     tpg_hs_r <= I_tpg_hs; //对hs信号寄存一次
  34. end

  35. //h_cnt计数器模块
  36. always @(posedge I_tpg_clk)
  37.     h_cnt <= I_tpg_de ? h_cnt + 1'b1 : 12'd0; //计数行有效像素,//当de无效,重置 h_cnt=0

  38. //v_cnt计数器模块
  39. always @(posedge I_tpg_clk)
  40.   if(I_tpg_vs) //通过vs产生同步复位
  41.     v_cnt <= 12'd0; //重置v_cnt=0
  42.   else
  43.     v_cnt <= ((!tpg_hs_r)&&I_tpg_hs) ? v_cnt + 1'b1 : v_cnt; //hs信号的上升沿,v_cnt计数,这种方式可以不管hs有效是高电平还是低电平的情况,v_cnt 场像素计数器,计数行数量

  44.    
  45. //以触控坐标的中心绘制,第1个触控点的方格,大小为200*200像素
  46. wire[11:0] box1_x1 =  I_tp1_x - 100;
  47. wire[11:0] box1_x2 =  I_tp1_x + 100;
  48. wire[11:0] box1_y1 =  I_tp1_y - 100;
  49. wire[11:0] box1_y2 =  I_tp1_y + 100;

  50. //以触控坐标的中心绘制,第2个触控点的方格,大小为200*200像素
  51. wire[11:0] box2_x1 =  I_tp2_x - 100;
  52. wire[11:0] box2_x2 =  I_tp2_x + 100;
  53. wire[11:0] box2_y1 =  I_tp2_y - 100;
  54. wire[11:0] box2_y2 =  I_tp2_y + 100;

  55. //以触控坐标的中心绘制,第3个触控点的方格,大小为200*200像素
  56. wire[11:0] box3_x1 =  I_tp3_x - 100;
  57. wire[11:0] box3_x2 =  I_tp3_x + 100;
  58. wire[11:0] box3_y1 =  I_tp3_y - 100;
  59. wire[11:0] box3_y2 =  I_tp3_y + 100;

  60. wire box1_en=(h_cnt>box1_x1)&&(h_cnt<box1_x2)&&(v_cnt>box1_y1)&&(v_cnt<box1_y2);// 屏幕上,方格1的数据绘制使能
  61. wire box2_en=(h_cnt>box2_x1)&&(h_cnt<box2_x2)&&(v_cnt>box2_y1)&&(v_cnt<box2_y2);// 屏幕上,方格2的数据绘制使能
  62. wire box3_en=(h_cnt>box3_x1)&&(h_cnt<box3_x2)&&(v_cnt>box3_y1)&&(v_cnt<box3_y2);// 屏幕上,方格3的数据绘制使能

  63. //显示颜色
  64. always @(posedge I_tpg_clk)begin
  65.     if(box1_en)begin
  66.         r_reg   <=8'b11111111;      //显示区域为红色
  67.         g_reg   <=0;
  68.         b_reg   <=0;   
  69.     end
  70.     if(box2_en)begin
  71.         r_reg   <=0;               
  72.         g_reg   <=8'b11111111;     //显示区域为绿色
  73.         b_reg   <=0;   
  74.     end
  75.     if(box3_en)begin
  76.         r_reg   <=0;               
  77.         g_reg   <=0;
  78.         b_reg   <=8'b11111111;     //显示区域为蓝色
  79.     end         
  80.     if(!(box1_en||box2_en||box3_en))begin //背景为白色
  81.         r_reg   <=8'b11111111;     
  82.         g_reg   <=8'b11111111;
  83.         b_reg   <=8'b11111111;        
  84.     end
  85. end


  86. assign O_tpg_data = {r_reg,g_reg,b_reg};
  87. assign O_tpg_vs = I_tpg_vs;
  88. assign O_tpg_hs = I_tpg_hs;
  89. assign O_tpg_de = I_tpg_de;  

  90. endmodule
复制代码

当我们读取到了触控的坐标后,根据坐标的参数信息绘制矩形框,分别绘制红绿蓝三个矩形,这样我们就可以非常方便的测试触摸液晶屏是否可以正常工作。
7硬件接线
(该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。)
本实验注意采我们的cep跳线帽跳线1.8V,子卡采用1.8V BASE卡,接口使用的是我们液晶屏的LVDS口。下图是LVDS接线方式。请确保下载器和开发板已经正确连接,另外需要把核心板上的2P模式开关设置到JTAG模式,即ON ON,并且开发板已经上电。(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)
3f5d6735d9af46c297fdae5be0b7897b.jpg
7寸液晶屏的接口使用的是LVDS接口
75b6622ce2e1473e8321fb316047c649.jpg
8测试结果8.1VIO显示坐标值
未来观察方便,添加了VIO(虚拟IO)观察读取到的触控坐标值
64927f2fae144d719bbb55031f252069.jpg
8.2触摸演示
f0aed98e6cb74253840fb27c8e12efe0.jpg











您需要登录后才可以回帖 登录 | 立即注册

本版积分规则