PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)

这篇具有很好参考价值的文章主要介绍了PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

  在前面的教程中呢,小编带领各位读者完成了对所有寄存器的配置,本章教程只需要完成对手势数据寄存器里面的数据读出即可,因为我们只检测上、下、左、右挥手数据,因此用四个led灯作为挥手数据结果指示即可。本章教程是基于FPGA的PAJ7620U2手势识别的最后一章教程,具体实现方法请继续往下浏览。

一、如何读取手势数据寄存器数据?

  在上一章教程中,我们采用的是突发读操作的时序图来对模块进行配置的,但是本章教程我们采用单次读操作对模块进行配置,单次读操作与突发读操作在前半段配置方式都是一样的,都是要指定读取的寄存器:
PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
  但是在后半段,连续读操作是从DATA状态,跳转到主机返回ACK响应,再从ACK响应跳转到DATA状态,结合官方数据手册:
PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
  我们发现,不管是采用哪种读方式,读取到数据后,都不会自动停下,这时候结合前面的数据手册,需要我们设置“中断”,当读取到的8位数据不为全0时,则中断读操作。但是呢,我们采用的是FPGA来配置这个模块,对数据的处理就简单得多,因此只需要检测出该模块数据变化,将变化的数据作为LED灯亮起的触发信号,触发以后LED灯在下次触发信号到来时,一直保持亮起即可。
  这里呢,我们采用单次读操作,因为后续利用Singal Tap II触发波形信号的时候,可以观测到从IDLE到STOP一整个的执行周期,因为整个执行周期是非常短暂的,远远小于我们手势变化的时间,因此在这里使用单次读操作是完全可以采集到手势数据的变化情况。

二、配置步骤

1.模块状态转移图绘制

PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
  从图中可以看出,读取0x43寄存器数值状态转移图与读取0x00寄存器状态转移图绘制方式一样,因此各位读者如果学会了读取0x00寄存器数值操作后,本章教程对大家应该没有难度。

2.模块波形图绘制

PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
  从波形图可以看出,除了跳转信号外,我们还需要引入两路信号,一路是po_data_reg,这个信号主要是在DATA状态下寄存拼接的数据。第二路信号是po_data,这个信号是在po_data_reg信号拼接完成后,读取DATA状态末尾拼接完成的数据。我们取po_data信号低四位,这低四位数据,某位由0变化为1后,则代表上、下、左、右挥手动作被检测出来,我们利用这个变化来驱动LED灯亮起。因为驱动LED灯亮起非常简单,我们可以在顶层文件直接编写代码,就不再进行波形图的绘制。

3.上板验证

  设置skip_en_6信号为触发条件:
PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
  使用连续触发,抓取到的信号波形如图所示:
PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
  我们发现,在DATA状态下,一直没有采集到数据,并且4个LED灯也一直保持高电平,即熄灭状态。我们向左挥手,抓取到的信号波形如下:
PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
  可以看到,LED灯已经发生了变化,第二位已经由高电平变为低电平,变亮了。但是为什么DATA状态下,SDA还是为低电平呢?因为我们使用的是连续触发,触发时间非常短暂,po_data采集到数据以后,马上让LED灯点亮,在下次采集数据时,po_data已经归零了,但是LED灯还维持在点亮状态没有改变。接下来,我们分别朝右、上、下挥手,抓取到的信号波形如下:
PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)

PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)
  LED灯低三位数值都有变化,因此我们代码验证通过,且上板现象与预期一致(具体的实验现象各位读者可自行绑定引脚测试,在这里小编就不做演示了),整个工程验证通过。

4.参考代码(i2c_ctrl和paj7620_top)

module  i2c_ctrl
(
	input	wire			sys_clk		,
	input	wire			sys_rst_n	,
	input	wire	[23:0]	cfg_data	,
	input	wire			i2c_start	,
	input	wire	[5:0]	cfg_num		,
	
	output	wire			scl			,							
	output	reg				cfg_start	,
	output	reg				i2c_clk		,
	output	reg		[2:0]	mode		,
	output	reg		[7:0]	po_data		,
	
	inout	wire			sda
);

localparam	CNT_CLK_MAX		=	5'd25	;
localparam	CNT_WAIT_MAX	=	10'd1000;
localparam	CNT_DELAY_MAX	=	10'd1000;
localparam	SLAVE_ID		=	7'h73	;
localparam	SENSOR_ADDR		=	8'hEF	;
localparam	DATA_ADDR		=	8'h43	;
localparam	IDLE		=	4'd0	,
			START		=	4'd1	,
			SLAVE_ADDR	=	4'd2	,
			WAIT		=	4'd3	,
			STOP		=	4'd4	,
			ACK_1		=	4'd5	,
			DEVICE_ADDR	=	4'd6	,
			ACK_2		=	4'd7	,
			DATA		=	4'd8	,
			ACK_3		=	4'd9	,
			NACK		=	4'd10	;

reg		[4:0]	cnt_clk		;	//分频计数器
reg		[9:0]	cnt_wait	;	//开始状态等待1000us计数器
reg				skip_en_0	;	//唤醒状态跳转信号
reg				skip_en_1	;	//激活bank0跳转信号
reg				skip_en_2	;	//配置0x00寄存器状态跳转信号
reg				skip_en_3	;	//读取0x00寄存器状态跳转信号
reg				skip_en_4	;	//配置51个操作寄存器
reg				skip_en_5	;	//配置0x43寄存器状态跳转信号
reg				skip_en_6	;	//读取0x43寄存器状态跳转信号
reg				error_en	;	//读取出来的值不是0x20,错误信号
reg		[3:0]	n_state		;	//次态
reg		[3:0]	c_state		;	//现态	
reg		[1:0]	cnt_i2c_clk	;	//对i2c_clk分频时钟个数计数			
reg		[2:0]	cnt_bit		;	//对传输的8bit数据进行计数	
reg				i2c_scl		;	//就是SCL		
reg				i2c_sda		;	//SDA赋值给i2c_sda
reg		[9:0]	cnt_delay	;	//发送完指令后等待1000us计数器			
reg				i2c_end		;	//i2c结束信号	
reg		[7:0]	po_data_reg	;	//采集数据,拼接完成后赋值给po_data
reg		[7:0]	slave_addr	;	//不同模式下7'h73+1'bx
reg		[7:0]	device_addr	;	//不同模式下寄存器地址变化
reg		[7:0]	wr_data		;	//向地址写入的数据
reg		[7:0]	rec_data	;	//唤醒操作读取0x00寄存器数据寄存
reg				ack			;
wire			sda_in		;
wire			sda_en		;

assign	scl		=	i2c_scl		;
assign	sda_in	=	sda			;	//从设备发送到主机的数据
assign	sda_en	=	((c_state == ACK_1)||(c_state == ACK_2)||(c_state == ACK_3)||((c_state == DATA)&&(mode == 3'd3))||((c_state == DATA)&&(mode == 3'd6))) ? 1'b0 : 1'b1		;	//主机控制sda有效
assign	sda		=	(sda_en == 1'b1) ? i2c_sda : 1'bz  ;

always@(posedge i2c_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		cfg_start  <=  1'b0  ;
	else
		cfg_start  <=  i2c_end  ;

always@(*)
	case(mode)
		3'd0	:slave_addr	=	{SLAVE_ID,1'b0}  ;
		3'd1	:begin
					slave_addr  =	{SLAVE_ID,1'b0}  ;
					device_addr	=	SENSOR_ADDR  ;
					wr_data		=	8'h00  ;
				 end
		3'd2	:begin
					slave_addr  =	{SLAVE_ID,1'b0}  ;
					device_addr	=	8'h00  ;		
				 end
		3'd3	:slave_addr  = 	{SLAVE_ID,1'b1}  ;
		3'd4	:begin
					slave_addr	<=  cfg_data[23:16]  ;
					device_addr	<=  cfg_data[15:8]   ;
					wr_data	    <=  cfg_data[7:0]	 ;
				 end
		3'd5	:begin	
					slave_addr  <=  {SLAVE_ID,1'b0}  ;
					device_addr	<=  DATA_ADDR  ;
				 end
		3'd6	:slave_addr  =  {SLAVE_ID,1'b1}  ;
		default	:begin
					slave_addr	<=  8'd0 ;
					device_addr	<=  8'd0 ;
					wr_data	    <=  8'd0 ;		
				 end
    endcase

//
//分频计数器进行计数
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		cnt_clk  <=  5'd0  ;
	else  if(cnt_clk == CNT_CLK_MAX - 1'b1)  
		cnt_clk  <=  5'd0  ;
	else
		cnt_clk  <=  cnt_clk + 1'b1  ;
	
//产生i2c驱动时钟	
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		i2c_clk  <=  1'b0  ;
	else  if(cnt_clk == CNT_CLK_MAX - 1'b1)
		i2c_clk  <=  ~i2c_clk  ;
	else
		i2c_clk  <=  i2c_clk  ;
//

//状态机第一段
always@(posedge i2c_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		c_state  <=  IDLE  ;
	else
		c_state  <=  n_state  ;
		
//状态机第二段
always@(*)
	case(c_state)
		IDLE		:	if((skip_en_0 == 1'b1)||(skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_3 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1)||(skip_en_6 == 1'b1))
							n_state  =  START  ;
						else
							n_state  =  IDLE  ;
		START		:	if((skip_en_0 == 1'b1)||(skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_3 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1)||(skip_en_6 == 1'b1))
							n_state  =  SLAVE_ADDR  ;
						else
							n_state  =  START  ;
		SLAVE_ADDR	:	if(skip_en_0 == 1'b1)
							n_state  =  WAIT  ;
						else  if((skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_3 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1)||(skip_en_6 == 1'b1))
							n_state  =  ACK_1  ;
						else
							n_state  =  SLAVE_ADDR  ;
		ACK_1		:	if((skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1))
							n_state  =  DEVICE_ADDR  ;
						else  if((skip_en_3 == 1'b1)||(skip_en_6 == 1'b1))
							n_state  =  DATA  ;
						else
							n_state  =  ACK_1  ;
		DEVICE_ADDR	:	if((skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1))
							n_state  =  ACK_2  ;
						else
							n_state  =  DEVICE_ADDR  ;
		ACK_2		:	if((skip_en_1 == 1'b1)||(skip_en_4 == 1'b1))
							n_state  =  DATA  ;
						else  if((skip_en_2 == 1'b1)||(skip_en_5 == 1'b1))
							n_state  =  STOP  ;
						else
							n_state  =  ACK_2  ;
		DATA		:	if((skip_en_1 == 1'b1)||(skip_en_4 == 1'b1))
							n_state  =  ACK_3  ;
						else  if((skip_en_3 == 1'b1)||(skip_en_6 == 1'b1))
							n_state  =  NACK  ;
						else  if(error_en == 1'b1)
							n_state  =  IDLE  ;
						else
							n_state  =  DATA  ;
		ACK_3		:	if((skip_en_1 == 1'b1)||(skip_en_4 == 1'b1))
							n_state  =  STOP  ;
						else
							n_state  =  ACK_3  ;
		WAIT		:	if(skip_en_0 == 1'b1)
							n_state  =  STOP  ;
						else
							n_state  =  WAIT  ;
		NACK		:	if((skip_en_3 == 1'b1)||(skip_en_6 == 1'b1))
							n_state  =  STOP  ;
						else
							n_state  =  NACK  ;
	    STOP		:	if((skip_en_0 == 1'b1)||(skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_3 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1)||(skip_en_6 == 1'b1))
							n_state  =  IDLE  ;
						else
							n_state  =  STOP  ;
		default		:	n_state  =  IDLE  ;
    endcase

//状态机第三段	
always@(posedge i2c_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		begin
			cnt_wait	<=  10'd0	;
			skip_en_0	<=  1'b0	;
			skip_en_1	<=  1'b0	;
			skip_en_2   <=  1'b0	;
			skip_en_3   <=  1'b0 	;
			skip_en_4   <=  1'b0	;
			skip_en_5   <=  1'b0	;
			skip_en_6	<=  1'b0	;
			error_en	<=  1'b0	;
			cnt_i2c_clk	<=  2'd0	;
			cnt_bit		<=  3'd0	;
			cnt_delay	<=  10'd0	;
			mode		<=  3'd0	;
			i2c_end		<=  1'b0	;
		end
	else
		case(c_state)
			IDLE		:begin
							cnt_wait  <=  cnt_wait + 1'b1  ;
							if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd0))
								skip_en_0  <=  1'b1  ;
							else
								skip_en_0  <=  1'b0  ;
							if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;	
							if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd2))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;	
							if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd3))
								skip_en_3  <=  1'b1  ;
							else
								skip_en_3  <=  1'b0  ;	
							if((i2c_start == 1'b1)&&(mode == 3'd4))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;	
							if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd5))
								skip_en_5  <=  1'b1  ;
							else
								skip_en_5  <=  1'b0  ;
							if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd6))
								skip_en_6  <=  1'b1  ;
							else
								skip_en_6  <=  1'b0  ;								
						 end
			START		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;			
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))
								skip_en_0  <=  1'b1  ;
							else
								skip_en_0  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3))
								skip_en_3  <=  1'b1  ;
							else
								skip_en_3  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5))
								skip_en_5  <=  1'b1  ;
							else
								skip_en_5  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6))
								skip_en_6  <=  1'b1  ;
							else
								skip_en_6  <=  1'b0  ;								
						 end
			SLAVE_ADDR	:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if(cnt_i2c_clk == 2'd3)
								cnt_bit  <=  cnt_bit + 1'b1  ;
							else
								cnt_bit  <=  cnt_bit  ;			
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd0))
								skip_en_0  <=  1'b1  ;
							else
								skip_en_0  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd2))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3))
								skip_en_3  <=  1'b1  ;
							else
								skip_en_3  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd5))
								skip_en_5  <=  1'b1  ;
							else
								skip_en_5  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd6))
								skip_en_6  <=  1'b1  ;
							else
								skip_en_6  <=  1'b0  ;									
						 end
			ACK_1		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2)&&(ack == 1'b1))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3)&&(ack == 1'b1))
								skip_en_3  <=  1'b1  ;
							else
								skip_en_3  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5)&&(ack == 1'b1))
								skip_en_5  <=  1'b1  ;
							else
								skip_en_5  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6)&&(ack == 1'b1))
								skip_en_6  <=  1'b1  ;
							else
								skip_en_6  <=  1'b0  ;									
						 end
			DEVICE_ADDR	:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if(cnt_i2c_clk == 2'd3)
								cnt_bit  <=  cnt_bit + 1'b1  ;
							else
								cnt_bit  <=  cnt_bit  ;								
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd2))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd5))
								skip_en_5  <=  1'b1  ;
							else
								skip_en_5  <=  1'b0  ;								
						 end
			ACK_2		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2)&&(ack == 1'b1))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5)&&(ack == 1'b1))
								skip_en_5  <=  1'b1  ;
							else
								skip_en_5  <=  1'b0  ;								
						 end
			DATA		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if(cnt_i2c_clk == 2'd3)
								cnt_bit  <=  cnt_bit + 1'b1  ;
							else
								cnt_bit  <=  cnt_bit  ;				
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3)&&(rec_data == 8'h20))
								skip_en_3  <=  1'b1  ;
							else
								skip_en_3  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd6))
								skip_en_6  <=  1'b1  ;
							else
								skip_en_6  <=  1'b0  ;								
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3)&&(rec_data != 8'h20))
								begin
									error_en  <=  1'b1  ;
									mode	  <=  3'd0  ;
								end
							else
								begin
									error_en  <=  1'b0  ;
									mode	  <=  mode  ;
								end							
						 end
			ACK_3		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;								
						 end						 
			WAIT		:begin
							if((cnt_delay == CNT_DELAY_MAX - 2'd2)&&(mode == 3'd0))
								skip_en_0  <=  1'b1  ;
							else
								skip_en_0  <=  1'b0  ;
							cnt_delay  <=  cnt_delay + 1'b1  ;
						 end
			NACK		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3)&&(ack == 1'b1))
								skip_en_3  <=  1'b1  ;
							else
								skip_en_3  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6)&&(ack == 1'b1))
								skip_en_6  <=  1'b1  ;
							else
								skip_en_6  <=  1'b0  ;								
						 end
			STOP		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;			
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))
								skip_en_0  <=  1'b1  ;
							else
								skip_en_0  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3))
								skip_en_3  <=  1'b1  ;
							else
								skip_en_3  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4))
								skip_en_4  <=  1'b1  ;
							else
								skip_en_4  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5))
								skip_en_5  <=  1'b1  ;
							else
								skip_en_5  <=  1'b0  ;	
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6))
								skip_en_6  <=  1'b1  ;
							else
								skip_en_6  <=  1'b0  ;									
							if(cnt_i2c_clk == 2'd2)
								i2c_end  <=  1'b1  ;
							else
								i2c_end  <=  1'b0  ;						    
							if((i2c_end == 1'b1)&&(mode <= 3'd3))
								mode  <=  mode + 1'b1  ;
							else  if((mode == 3'd4)&&(i2c_end == 1'b1)&&(cfg_num == 6'd51))
								mode  <=  mode + 1'b1  ;
							else  if((i2c_end == 1'b1)&&(mode == 3'd5))
								mode  <=  mode + 1'b1  ;
							else
								mode  <=  mode  ;
						 end
			default		:begin
							cnt_wait  	<=  10'd0   ;
							skip_en_0	<=  1'b0	;
							skip_en_1	<=  1'b0	;
							skip_en_2   <=  1'b0	;
							skip_en_3   <=  1'b0	;
							skip_en_4   <=  1'b0	;
							skip_en_5   <=  1'b0	;
							skip_en_6   <=  1'b0	;
							error_en	<=  1'b0	;
							cnt_i2c_clk	<=  2'd0	;
							cnt_bit		<=  3'd0	;
							cnt_delay	<=  10'd0	;
							mode		<=  mode	;
							i2c_end		<=  1'b0	;
						 end
		endcase
		
always@(posedge i2c_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		rec_data  <=  8'd0  ;
	else
		case(c_state)
			DATA	:	if((mode == 3'd3)&&(cnt_i2c_clk == 2'd1))
							rec_data  <=  {rec_data[6:0],sda_in}  ;
						else
							rec_data  <=  rec_data  ;
			default	:	rec_data  <=  8'd0  ;
		endcase
		
always@(posedge i2c_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		po_data_reg  <=  8'd0  ;
	else  
		case(c_state)
			DATA	:	if((mode == 3'd6)&&(cnt_i2c_clk == 2'd1))
							po_data_reg  <=  {po_data_reg[6:0],sda_in}  ;
						else
							po_data_reg  <=  po_data_reg  ;
			default	:	po_data_reg  <=  po_data_reg  ;
		endcase
		
always@(posedge i2c_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		po_data  <=  8'd0  ;
	else  if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd6))
		po_data  <=  po_data_reg  ;
	else
		po_data  <=  po_data  ;
		
always@(*)
	case(c_state)
		ACK_1,ACK_2,ACK_3  :  ack  =  ~sda_in  ;
		NACK			   :  ack  =  i2c_sda  ;
		default	:	ack  =  1'b0  ;
	endcase
		
always@(*)
	case(c_state)
		IDLE		:	i2c_scl  =  1'b1  ;
		START		:	if(cnt_i2c_clk == 2'd3)
							i2c_scl  =  1'b0  ;
						else
							i2c_scl  =  1'b1  ;
		SLAVE_ADDR,ACK_1,DEVICE_ADDR,ACK_2,DATA,ACK_3,NACK
					:	if((cnt_i2c_clk == 2'd0)||(cnt_i2c_clk == 2'd3))
							i2c_scl  =  1'b0  ;
						else
							i2c_scl  =  1'b1  ;
		WAIT		:	i2c_scl  =  1'b0  ;
		STOP		:	if(cnt_i2c_clk == 2'd0)
							i2c_scl  =  1'b0  ;
						else
							i2c_scl  =  1'b1  ;
		default		:	i2c_scl  =  1'b1  ;
    endcase
	
always@(*)
	case(c_state)
		IDLE		:	i2c_sda  =  1'b1  ;
		START		:	if(cnt_i2c_clk == 2'd0)
							i2c_sda  =  1'b1  ;
						else
							i2c_sda  =  1'b0  ;
		SLAVE_ADDR	:	i2c_sda  =  slave_addr[7 - cnt_bit]  ;
		ACK_1,ACK_2,ACK_3,
					:	i2c_sda	 =  1'b0  ;
		NACK		:	i2c_sda  =  1'b1  ;
		DEVICE_ADDR	:	i2c_sda  =  device_addr[7 - cnt_bit]  ;
		DATA		:	i2c_sda  =  wr_data[7 - cnt_bit]  ;
		WAIT		:	i2c_sda  =  1'b0  ;
		STOP		:	if((cnt_i2c_clk == 2'd0)||(cnt_i2c_clk == 2'd1))
							i2c_sda  <=  1'b0  ;
						else
							i2c_sda  <=  1'b1  ;
		default		:	i2c_sda  <=  1'b1  ;
    endcase

endmodule
module  paj7620_top
(	
	input	wire			sys_clk		,
	input	wire			sys_rst_n	,
	
	output	wire			scl			,
	output	reg		[3:0]	led			,
	
	inout	wire			sda	
);

wire	[23:0]	cfg_data	;
wire			i2c_start	;
wire	[5:0]	cfg_num		;
wire			i2c_clk		;
wire	[2:0]	mode		;
wire			cfg_start	;
wire	[7:0]	po_data		;

always@(posedge i2c_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		led  <=  4'b1111  ;
	else  if(po_data[3:0] == 4'b0001)
		led  <=  4'b1110  ;
	else  if(po_data[3:0] == 4'b0010)
		led  <=  4'b1101  ;
	else  if(po_data[3:0] == 4'b0100)
		led  <=  4'b1011  ;	
	else  if(po_data[3:0] == 4'b1000)
		led  <=  4'b0111  ;
	else
		led  <=  led  ;

i2c_ctrl  i2c_ctrl_inst
(
	.sys_clk	(sys_clk	)	,
	.sys_rst_n	(sys_rst_n	)	,
	.cfg_data	(cfg_data	)	,
	.i2c_start	(i2c_start	)	,
	.cfg_num	(cfg_num	)	,
	.scl		(scl		)	,
	.i2c_clk	(i2c_clk	)	,
	.mode		(mode		)	,
	.cfg_start	(cfg_start	)	,
	.po_data	(po_data	)	,
	.sda        (sda        )
);

paj7620_cfg  paj7620_cfg_inst
(
	.i2c_clk	(i2c_clk	),
	.sys_rst_n	(sys_rst_n	),
	.cfg_start	(cfg_start	),
	.mode		(mode		),
	.cfg_data	(cfg_data	),
	.cfg_num	(cfg_num	),
	.i2c_start  (i2c_start  )
);

endmodule

总结

  小编在这里用了7章的教程,带领各位读者完成了对paj7620手势识别模块上、下、左、右的识别配置,感谢各位读者的支持,后续将为大家带来4x4矩阵键盘密码锁工程的实现,敬请期待。文章来源地址https://www.toymoban.com/news/detail-443262.html

到了这里,关于PAJ7620U2手势识别——读取手势数据寄存器数据与LED显示(完)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • PAJ7620U2手势识别——唤醒操作(1)

      本教程是基于FPGA的手势识别实现教程,使用到的手势识别模块是PAJ7620U2,本文主要向各位读者阐述如何通过I2C协议去唤醒该模块,从模块状态转移图、模块波形图的绘制,到最后代码的编写及验证,一步一步教会各位读者如何利用FPGA去实现。   下面我们简单介绍一下

    2024年02月05日
    浏览(47)
  • 基于FPGA的手势识别(PAJ7620U2)

    1.基本信息         PAJ7620U2 是原相科技(PixArt)公司推出的一款光学数组式传感器,内置光源和环境光抑制滤波器集成的 LED,镜头和手势感测器在一个小的立方体模组,能在黑暗或低光环境下工作。同时传感器内置手势识别,支持 9 个手势类型和输出的手势中断结果。并

    2024年04月09日
    浏览(40)
  • PAJ7620U2手势识别——激活BANK0(2)

      在前一章教程中,小编带领各位读者通过I2C协议配置了手势识别模块当中,较简单的唤醒操作。在本章教程中,小编会继续带领各位读者继续配置PAJ7620U2手势识别模块,本章主要是讲解如何激活BANK0,详细操作请各位读者继续浏览下去。   相信很多读者都会有这样的疑

    2024年02月08日
    浏览(37)
  • STM32 手势识别传感器模块(PAJ7620)学习

    目录 模块介绍: 基本部分: 引脚配置: 工作原理: 展示部分: 代码部分展示(在正点的基础上加了一个读手势去控制舵机): 视频展示: 基本部分: 手势模块搭载的芯片是PAJ7620,无论是正点原子的还是别的手势模块的底层是一致的,甚至代码也是通用的。 芯片内部集成了

    2024年02月07日
    浏览(41)
  • 10.1 调试事件读取寄存器

    当读者需要获取到特定进程内的寄存器信息时,则需要在上述代码中进行完善,首先需要编写 CREATE_PROCESS_DEBUG_EVENT 事件,程序被首次加载进入内存时会被触发此事件,在该事件内首先我们通过 lpStartAddress 属性获取到当前程序的入口地址,并通过 SuspendThread 暂停程序的运行,

    2024年02月08日
    浏览(38)
  • optee读取Arm系统寄存器的模板

    快速链接: . 👉👉👉 个人博客笔记导读目录(全部) 👈👈👈 付费专栏-付费课程 【购买须知】: 【精选】ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈 联系方式-加入交流群 ---- 联系方式-加入交流群 先写一个通用的内联函数模板,然后再通过宏控来定义各种读写函数。

    2024年02月12日
    浏览(58)
  • ZC-CLS381RGB颜色识别+8x8点阵指示——配置颜色识别寄存器组(上)

      在现代工业生产中,颜色识别技术已经成为了一个非常重要的技术。颜色识别可以用于产品质量检测、物料分类、机器视觉等领域。本文将介绍如何使用FPGA结合ZC-CLS381RGB进行颜色识别。   本教程通过对采集到的图像信息中,R、G、B三个颜色分量的占比,来判断识别到

    2024年02月03日
    浏览(132)
  • 三菱plc数据寄存器D

    在输入和输出处理、模拟控制和位置控制期间,需要许多数据寄存器来存储数据和参数。数据寄存器为16位,最高位为符号位。两个数据寄存器可以组合存储32位数据,最高位仍然是符号位。   数据寄存器分为以下几类: 通用数据寄存器D0 ~ D199有200个点。 断电/锁存寄存器D20

    2024年02月08日
    浏览(43)
  • PLC从HTTP服务端获取JSON文件,解析数据到寄存器

           智能网关IGT-DSER集成了多种PLC协议,方便实现各种PLC与HTTP服务端之间通讯。通过网关的参数配置软件绑定JSON文件的字段与PLC寄存器地址,配置URL,即可采用POST命令,将JSON文件提交给HTTP的服务端; 服务端有返回的JSON,或者GET命令获取到的JSON,网关进行解析后将数据

    2024年01月23日
    浏览(47)
  • Modbus协议的数据模型和地址模型,Modbus寄存器40001,30001是什么意思?

    在使用Modbus协议的时候,经常会遇到诸如40001、30001,10001之类的地址,这些数字代表什么含义呢? 这其实是Modbus协议的数据模型和地址模型。 Modbus协议的数据模型  数据模型是对从站设备可访问的数据进行抽象,Modbus协议的数据模型定义了四种可访问的数据: 数据区块 数据

    2024年02月05日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包