> 文章列表 > PAJ7620U2手势识别——配置手势数据寄存器(6)

PAJ7620U2手势识别——配置手势数据寄存器(6)

PAJ7620U2手势识别——配置手势数据寄存器(6)

文章目录

  • 前言
  • 一、手势数据寄存器简介
  • 二、配置步骤
    • 1.突发读操作步骤图
    • 2.模块状态转移图绘制
    • 3.模块波形图绘制
    • 4.上板验证
    • 5.参考代码(i2c_ctrl)
  • 总结

前言

  我们已经把所有操作寄存器配置好了,接下来就可以读取手势数据了。本章教程会带领各位读者完成对手势数据寄存器的配置,内容比较简单。

一、手势数据寄存器简介

  结合官方数据手册:
PAJ7620U2手势识别——配置手势数据寄存器(6)
  我们读取0x43或者0x44寄存器内的数据,挥手动作将会被这两个寄存器捕捉到,捕捉完成后读取即可。下面是0x43寄存器8bit数据每位置1的含义:
PAJ7620U2手势识别——配置手势数据寄存器(6)
  我们在这里读取0x43寄存器即可,0x44寄存器主要是执行中断操作,我们不使用该寄存器,在编写代码时检测到数据变化,做输出即可。

二、配置步骤

1.突发读操作步骤图

PAJ7620U2手势识别——配置手势数据寄存器(6)
  因为要进行连续捕获挥手动作,因此在这里必须要使用到连续读操作。我们看第一个START状态到第一个STOP状态,这部分的波形图与我们配置0x00寄存器绘制的波形图类似,因此在原有的波形图和状态转移图上修改即可。

2.模块状态转移图绘制

PAJ7620U2手势识别——配置手势数据寄存器(6)

  这里是确定访问0x43寄存器,表示将要对0x43寄存器操作。

3.模块波形图绘制

PAJ7620U2手势识别——配置手势数据寄存器(6)

PAJ7620U2手势识别——配置手势数据寄存器(6)

  波形图绘制结束,参考波形图编写代码即可。

4.上板验证

  上板抓取信号波形,设置skip_en_5上升沿为触发条件:
PAJ7620U2手势识别——配置手势数据寄存器(6)
  抓取到的信号波形如下所示:

PAJ7620U2手势识别——配置手势数据寄存器(6)

  如图所示,结束信号拉高,mode自增1,代码验证通过。

5.参考代码(i2c_ctrl)

  在上一章教程中,已经列出了详细的代码,本章教程只对i2c_ctrl模块进行修改,因此本章参考代码为i2c控制部分的代码。

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]	reg_num		,output	wire			scl			,output	reg				cfg_start	,output	reg				i2c_clk		,output	reg		[2:0]	mode		,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				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]	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))) ? 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  ;elsecfg_start  <=  i2c_end  ;always@(*)case(mode)3'd0	:slave_addr	=	{SLAVE_ID,1'b0}  ;3'd1	:beginslave_addr  =	{SLAVE_ID,1'b0}  ;device_addr	=	SENSOR_ADDR  ;wr_data		=	8'h00  ;end3'd2	:beginslave_addr  =	{SLAVE_ID,1'b0}  ;device_addr	=	8'h00  ;		end3'd3	:slave_addr  = 	{SLAVE_ID,1'b1}  ;3'd4	:	beginslave_addr	<=  cfg_data[23:16]  ;device_addr	<=  cfg_data[15:8]   ;wr_data	    <=  cfg_data[7:0]	 ;end3'd5	:	begin	slave_addr  <=  {SLAVE_ID,1'b0}  ;device_addr	<=  DATA_ADDR  ;endendcase//
//分频计数器进行计数
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  ;elsecnt_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  ;elsei2c_clk  <=  i2c_clk  ;
////状态机第一段
always@(posedge i2c_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)c_state  <=  IDLE  ;elsec_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))n_state  =  START  ;elsen_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))n_state  =  SLAVE_ADDR  ;elsen_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))n_state  =  ACK_1  ;elsen_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)n_state  =  DATA  ;elsen_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  ;elsen_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  ;elsen_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)n_state  =  NACK  ;else  if(error_en == 1'b1)n_state  =  IDLE  ;elsen_state  =  DATA  ;ACK_3		:	if((skip_en_1 == 1'b1)||(skip_en_4 == 1'b1))n_state  =  STOP  ;elsen_state  =  ACK_3  ;WAIT		:	if(skip_en_0 == 1'b1)n_state  =  STOP  ;elsen_state  =  WAIT  ;NACK		:	if(skip_en_3 == 1'b1)n_state  =  STOP  ;elsen_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))n_state  =  IDLE  ;elsen_state  =  STOP  ;default		:	n_state  =  IDLE  ;endcase//状态机第三段	
always@(posedge i2c_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)begincnt_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	;error_en	<=  1'b0	;cnt_i2c_clk	<=  2'd0	;cnt_bit		<=  3'd0	;cnt_delay	<=  10'd0	;mode		<=  3'd0	;i2c_end		<=  1'b0	;endelsecase(c_state)IDLE		:begincnt_wait  <=  cnt_wait + 1'b1  ;if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd0))skip_en_0  <=  1'b1  ;elseskip_en_0  <=  1'b0  ;if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd1))skip_en_1  <=  1'b1  ;elseskip_en_1  <=  1'b0  ;	if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd2))skip_en_2  <=  1'b1  ;elseskip_en_2  <=  1'b0  ;	if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd3))skip_en_3  <=  1'b1  ;elseskip_en_3  <=  1'b0  ;	if((i2c_start == 1'b1)&&(mode == 3'd4))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;	if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd5))skip_en_5  <=  1'b1  ;elseskip_en_5  <=  1'b0  ;		endSTART		:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;			if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))skip_en_0  <=  1'b1  ;elseskip_en_0  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))skip_en_1  <=  1'b1  ;elseskip_en_1  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2))skip_en_2  <=  1'b1  ;elseskip_en_2  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3))skip_en_3  <=  1'b1  ;elseskip_en_3  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5))skip_en_5  <=  1'b1  ;elseskip_en_5  <=  1'b0  ;								endSLAVE_ADDR	:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;if(cnt_i2c_clk == 2'd3)cnt_bit  <=  cnt_bit + 1'b1  ;elsecnt_bit  <=  cnt_bit  ;			if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd0))skip_en_0  <=  1'b1  ;elseskip_en_0  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))skip_en_1  <=  1'b1  ;elseskip_en_1  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd2))skip_en_2  <=  1'b1  ;elseskip_en_2  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3))skip_en_3  <=  1'b1  ;elseskip_en_3  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd5))skip_en_5  <=  1'b1  ;elseskip_en_5  <=  1'b0  ;								endACK_1		:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))skip_en_1  <=  1'b1  ;elseskip_en_1  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2)&&(ack == 1'b1))skip_en_2  <=  1'b1  ;elseskip_en_2  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3)&&(ack == 1'b1))skip_en_3  <=  1'b1  ;elseskip_en_3  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5)&&(ack == 1'b1))skip_en_5  <=  1'b1  ;elseskip_en_5  <=  1'b0  ;								endDEVICE_ADDR	:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;if(cnt_i2c_clk == 2'd3)cnt_bit  <=  cnt_bit + 1'b1  ;elsecnt_bit  <=  cnt_bit  ;								if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))skip_en_1  <=  1'b1  ;elseskip_en_1  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd2))skip_en_2  <=  1'b1  ;elseskip_en_2  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd5))skip_en_5  <=  1'b1  ;elseskip_en_5  <=  1'b0  ;								endACK_2		:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))skip_en_1  <=  1'b1  ;elseskip_en_1  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2)&&(ack == 1'b1))skip_en_2  <=  1'b1  ;elseskip_en_2  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5)&&(ack == 1'b1))skip_en_5  <=  1'b1  ;elseskip_en_5  <=  1'b0  ;								endDATA		:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;if(cnt_i2c_clk == 2'd3)cnt_bit  <=  cnt_bit + 1'b1  ;elsecnt_bit  <=  cnt_bit  ;				if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))skip_en_1  <=  1'b1  ;elseskip_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  ;elseskip_en_3  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;								if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3)&&(rec_data != 8'h20))beginerror_en  <=  1'b1  ;mode	  <=  3'd0  ;endelsebeginerror_en  <=  1'b0  ;mode	  <=  mode  ;end							endACK_3		:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))skip_en_1  <=  1'b1  ;elseskip_en_1  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;								end						 WAIT		:beginif((cnt_delay == CNT_DELAY_MAX - 2'd2)&&(mode == 3'd0))skip_en_0  <=  1'b1  ;elseskip_en_0  <=  1'b0  ;cnt_delay  <=  cnt_delay + 1'b1  ;endNACK		:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3)&&(ack == 1'b1))skip_en_3  <=  1'b1  ;elseskip_en_3  <=  1'b0  ;							endSTOP		:begincnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;			if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))skip_en_0  <=  1'b1  ;elseskip_en_0  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))skip_en_1  <=  1'b1  ;elseskip_en_1  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2))skip_en_2  <=  1'b1  ;elseskip_en_2  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3))skip_en_3  <=  1'b1  ;elseskip_en_3  <=  1'b0  ;	if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4))skip_en_4  <=  1'b1  ;elseskip_en_4  <=  1'b0  ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5))skip_en_5  <=  1'b1  ;elseskip_en_5  <=  1'b0  ;								if(cnt_i2c_clk == 2'd2)i2c_end  <=  1'b1  ;elsei2c_end  <=  1'b0  ;						    if((i2c_end == 1'b1)&&(mode <= 3'd3))mode  <=  mode + 1'b1  ;else  if((mode == 3'd4)&&(i2c_end == 1'b1)&&(reg_num == 6'd51))mode  <=  mode + 1'b1  ;else  if((i2c_end == 1'b1)&&(mode == 3'd5))mode  <=  mode + 1'b1  ;elsemode  <=  mode  ;enddefault		:begincnt_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	;error_en	<=  1'b0	;cnt_i2c_clk	<=  2'd0	;cnt_bit		<=  3'd0	;cnt_delay	<=  10'd0	;mode		<=  mode	;i2c_end		<=  1'b0	;endendcasealways@(posedge i2c_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)rec_data  <=  8'd0  ;elsecase(c_state)DATA	:	if((mode == 3'd3)&&(cnt_i2c_clk == 2'd1))rec_data  <=  {rec_data[6:0],sda_in}  ;elserec_data  <=  rec_data  ;default	:	rec_data  <=  8'd0  ;endcasealways@(*)case(c_state)ACK_1,ACK_2,ACK_3  :  ack  =  ~sda_in  ;NACK			   :  ack  =  i2c_sda  ;default	:	ack  =  1'b0  ;endcasealways@(*)case(c_state)IDLE		:	i2c_scl  =  1'b1  ;START		:	if(cnt_i2c_clk == 2'd3)i2c_scl  =  1'b0  ;elsei2c_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  ;elsei2c_scl  =  1'b1  ;WAIT		:	i2c_scl  =  1'b0  ;STOP		:	if(cnt_i2c_clk == 2'd0)i2c_scl  =  1'b0  ;elsei2c_scl  =  1'b1  ;default		:	i2c_scl  =  1'b1  ;endcasealways@(*)case(c_state)IDLE		:	i2c_sda  =  1'b1  ;START		:	if(cnt_i2c_clk == 2'd0)i2c_sda  =  1'b1  ;elsei2c_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  ;elsei2c_sda  <=  1'b1  ;default		:	i2c_sda  <=  1'b1  ;endcaseendmodule

总结

  下一章是最后一章教程,PAJ7620U2手势识别——读取手势数据寄存器数据(7),敬请期待。