PAJ7620U2手势识别——激活BANK0(2)

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


前言

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

一、为啥要激活BANK0?

  相信很多读者都会有这样的疑问,我们参考一下正点原子提供的文档教程:

PAJ7620U2手势识别——激活BANK0(2)
  同时参考一下官方的文档:

PAJ7620U2手势识别——激活BANK0(2)
  我们发现,在手势识别内部是有很多寄存器的,但是官方和正点原子教程只列出了一部分寄存器,而这些寄存器呢,是分布在两个BANK区域。如果操作者要想访问某个寄存器,则需要先要激活该寄存器对应的BANK区域,激活之后才能访问。小编在前一章教程中列出了使用这个模块的部分操作步骤,现在我们接着看官方教程:

PAJ7620U2手势识别——激活BANK0(2)

  这里说明了,唤醒操作结束后,需要访问0x00寄存器,读取其内部数据,看读取出来的数据是否为0x20.如果是0x20的话,则代表唤醒操作成功,如果不为0x20,则代表唤醒失败,继续重新唤醒。但是0x00寄存器,归属于BANK0区域,上电后BANK0区域是未被激活的,因此首先要激活BANK0区域,激活后才可以访问内部的0x00寄存器,从而根据返回值来判断是否激活成功。

二、激活步骤

1.单个写操作步骤图

  参考官方数据手册,我们需要用到单个写指令:

PAJ7620U2手势识别——激活BANK0(2)

2.模块状态转移图绘制

PAJ7620U2手势识别——激活BANK0(2)
  结合模块状态转移图我们可以大致了解整个过程:初始状态延迟1000us后,跳转到开始状态,检测到开始信号后,跳转到发送从设备地址状态,从设备地址8’b1110_0110发送成功,返回一个响应值。检测到响应值有效,跳转到发送BANK0地址,BANK0地址8’b1110_1111发送完成之后,又接收到一个响应值。检测到响应值有效,跳转到发送寄存器地址状态,寄存器地址0x00数据发送完成,接收到响应信号,响应信号有效,跳转到停止状态。

3.模块波形图绘制

  首先,是模块的空闲状态和起始状态:
PAJ7620U2手势识别——激活BANK0(2)
  空闲状态延迟1000us后,跳转到开始状态,在SCL信号为高电平,SDA信号发生下降沿变化时,跳转到发送从设备地址状态。从设备地址状态如下:

PAJ7620U2手势识别——激活BANK0(2)
  从设备地址8’b1110_0110发送完成,主机即FPGA放弃对SDA总线的控制,从机PAJ7620U2控制SDA总线,接收到主机发送的数据以后向主机发送一个ACK响应信号,如果响应信号取反为高电平,则代表从机返回的是有效的响应数据,反之无效,主机发送的数据从机没有接收到。ACK响应状态如下:

PAJ7620U2手势识别——激活BANK0(2)
  响应数据有效,跳转到发送BANK0地址状态,因为后续发送BANK0地址并响应和发送寄存器0x00地址并响应,与上述发送从机地址并响应的波形图一致,因此后续的波形图我们不再绘制。只需要参考上述波形图即可在唤醒操作基础上修改代码,比起唤醒操作,激活BANK0操作只是多了几个状态,信号基本没有发生多少变化。

4.上板验证

  上板抓取信号波形,设置skip_en_2上升沿为出发条件,设置如下:

PAJ7620U2手势识别——激活BANK0(2)
  抓取到的信号波形如下:

PAJ7620U2手势识别——激活BANK0(2)
  我们发现,从IDLE状态到STOP状态,每个状态高电平持续情况都是按照我们所设置的进行变化,且在STOP状态下,结束信号拉高,模式自增1,表示配置BANK0结束,跳转到另一个模式。因此我们编写的代码验证通过。

5.参考代码

module  i2c_ctrl
#(
	parameter	SLAVE_ID	=	7'b111_0011		,
				SENSOR_ADDR	=	8'hEF			,
				SYS_CLK_FREQ=	26'd50_000_000	,
				SCL_FREQ	=	23'd250_000
)                                                                                                              
(
	input	wire			sys_clk		,
	input	wire			sys_rst_n	,
	
	output	wire			scl			,
	
	inout	wire			sda		
);

localparam	CNT_CLK_MAX		=	(SYS_CLK_FREQ/SCL_FREQ) >> 2'd3  ;
localparam	CNT_T1_MAX		=	'd1000  ,
			CNT_T2_MAX		=	'd1000	;
parameter	IDLE			=	'd0		,
			START			=	'd1		,
			SLAVE_ADDR		=	'd2		,
			ACK_1			=	'd3		,
			DEVICE_ADDR		=	'd4		,
			ACK_2			=	'd5		,
			DATA			=	'd6		,
			ACK_3			=	'd7		,
			WAIT			=	'd8		,
			STOP			=	'd9		;	
			
reg		[4:0]	n_state		;
reg		[4:0]	c_state		;
reg		[4:0]	cnt_clk		;
reg				i2c_clk		;
reg				skip_en_1	;
reg				skip_en_2	;
reg		[9:0]	cnt_wait	;
reg				i2c_scl		;
reg				i2c_sda		;
reg				i2c_end		;
reg		[1:0]	cnt_i2c_clk	;
reg		[2:0]	cnt_bit		;
reg				ack			;
reg		[9:0]	cnt_delay	;
reg		[2:0]	mode		;
reg		[7:0]	slave_addr	;
reg		[7:0]	device_addr	;
reg		[7:0]	wr_addr		;
wire			sda_en		;
wire			sda_in		;

assign	scl		=	i2c_scl		;
assign	sda_in	=	sda			;
assign	sda_en	=	((c_state == ACK_1)||(c_state == ACK_2)||(c_state == ACK_3)) ? 1'b0 : 1'b1  ;
assign	sda		=	(sda_en == 1'b1) ? i2c_sda : 1'bz  ;

always@(*)
	case(mode)
		3'd0	:	begin
						slave_addr	<=  {SLAVE_ID,1'b0}  ;	//激活
						device_addr	<=  8'd0  ;
						wr_addr		<=  8'd0  ;					
					end
		3'd1	:	begin
						slave_addr	<=  {SLAVE_ID,1'b0}  ;	//写入0xEF 00
						device_addr	<=  SENSOR_ADDR  ;
						wr_addr		<=  8'd0  ;					
					end					
		default	:	begin
						slave_addr	<=  slave_addr   ;			
						device_addr	<=	device_addr  ;	
						wr_addr		<=	wr_addr		 ; 
					end
    endcase

///生成i2c设备驱动时钟/
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  ;	

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_1 == 1'b1)||(skip_en_2 == 1'b1))
							n_state  <=  START  ;
						else
							n_state  <=  IDLE  ;
		START		:	if((skip_en_1 == 1'b1)||(skip_en_2 == 1'b1))
							n_state  <=  SLAVE_ADDR  ;
						else
							n_state  <=  START  ;
	    SLAVE_ADDR	:	if(skip_en_1 == 1'b1)
							n_state  <=  WAIT  ;
						else  if(skip_en_2 == 1'b1)
							n_state  <=  ACK_1  ;
						else
							n_state  <=  SLAVE_ADDR  ;
		ACK_1		:	if(skip_en_2 == 1'b1)
							n_state  <=  DEVICE_ADDR  ;
						else
							n_state  <=  ACK_1  ;
		WAIT		:	if(skip_en_1 == 1'b1)
							n_state  <=  STOP  ;
						else
							n_state  <=  WAIT  ;
		DEVICE_ADDR	:	if(skip_en_2 == 1'b1)
							n_state  <=  ACK_2  ;
						else
							n_state  <=  DEVICE_ADDR  ;
		ACK_2		:	if(skip_en_2 == 1'b1)
							n_state  <=  DATA  ;
						else
							n_state  <=  ACK_2  ;
		DATA		:	if(skip_en_2 == 1'b1)
							n_state  <=  ACK_3  ;
						else
							n_state  <=  DATA  ;
		ACK_3		:	if(skip_en_2 == 1'b1)
							n_state  <=  STOP  ;
						else
							n_state  <=  ACK_3  ;
		STOP		:	if((skip_en_1 == 1'b1)||(skip_en_2 == 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_1	<=  1'b0    ;
			skip_en_2   <=  1'b0	;
			cnt_i2c_clk	<=  2'd0	;
			cnt_bit		<=  3'd0	;
			i2c_end		<=  1'b0	;
			mode		<=  3'd0	;
			cnt_delay	<=  10'd0	;
		end
	else
		case(c_state)
			IDLE		:begin
							if(cnt_wait == CNT_T1_MAX - 1'b1)
								cnt_wait  <=  10'd0  ;
							else
								cnt_wait  <=  cnt_wait + 1'b1  ;
							if((cnt_wait == CNT_T1_MAX - 2'd2)&&(mode == 3'd0))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_wait == CNT_T1_MAX - 2'd2)&&(mode == 3'd1))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
						 end
			START		:begin
							cnt_i2c_clk		<=  cnt_i2c_clk + 1'b1  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))
								skip_en_1  <=  1'b1  ;
						    else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
								skip_en_2  <=  1'b1  ;
						    else
								skip_en_2  <=  1'b0  ;
						 end
			SLAVE_ADDR	:begin
							cnt_i2c_clk		<=  cnt_i2c_clk + 1'b1  ;
							if((cnt_i2c_clk == 2'd3)&&(cnt_bit == 3'd7))
								cnt_bit  <=  3'd0  ;
							else  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_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
						 end
			ACK_1		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((ack == 1'b1)&&(cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
						 end
		    DEVICE_ADDR	:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((cnt_i2c_clk == 2'd3)&&(cnt_bit == 3'd7))
								cnt_bit  <=  3'd0  ;
							else  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_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
						 end
			ACK_2		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((ack == 1'b1)&&(cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;
						 end
			DATA		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((cnt_i2c_clk == 2'd3)&&(cnt_bit == 3'd7))
								cnt_bit  <=  3'd0  ;
							else  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_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;								
						 end
			ACK_3		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if((ack == 1'b1)&&(cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;							
						 end
			WAIT		:begin
							cnt_delay  <=  cnt_delay + 1'b1  ;
							if(cnt_delay == CNT_T2_MAX - 2'd2)
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
						 end
		    STOP		:begin
							cnt_i2c_clk  <=  cnt_i2c_clk + 1'b1  ;
							if(cnt_i2c_clk == 2'd2)
								i2c_end  <=  1'b1  ;
							else
								i2c_end  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))
								skip_en_1  <=  1'b1  ;
							else
								skip_en_1  <=  1'b0  ;
							if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
								skip_en_2  <=  1'b1  ;
							else
								skip_en_2  <=  1'b0  ;	
							if(i2c_end == 1'b1)
								mode  <=  mode + 1'b1  ;
							else
								mode  <=  mode  ;
						 end
			default		:begin
							cnt_wait 	<=  10'd0	;
							skip_en_1	<=	1'b0	;
							skip_en_2	<=  1'b0	;
							cnt_i2c_clk	<=  2'd0	;
							cnt_bit		<=  3'd0	;
							i2c_end		<=  1'b0	;
							mode		<=  mode	;
							cnt_delay	<=  10'd0	;
						 end
		endcase
		
always@(*)	
	case(c_state)
		ACK_1,ACK_2,ACK_3	:	ack  <=  ~sda_in  ;
		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:
						if((cnt_i2c_clk == 2'd1)||(cnt_i2c_clk == 2'd2))
							i2c_scl  <=  1'b1  ;
						else
							i2c_scl  <=  1'b0  ;
		WAIT		:	if((cnt_delay == 10'd0)||(cnt_delay == CNT_T2_MAX - 1'b1))
							i2c_scl  <=  1'b0  ;
						else
							i2c_scl  <=  1'b1  ;
		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  ;
		DEVICE_ADDR	:	i2c_sda  <=  device_addr[7-cnt_bit]  ;
		DATA		:	i2c_sda	 <=  wr_addr[7-cnt_bit]  ;
		WAIT		:	i2c_sda  <=  1'b1  ;
		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

总结

  以上就是激活BANK0操作流程,各位读者可以作一个参考,绘制出波形图,写出代码后抓取波形,观察波形变化是否与本教程一致,若有误差再利用Singal Tap抓取波形修改。下一篇文章将为各位读者讲解:PAJ7620U2手势识别——配置0x00寄存器(3),敬请期待。文章来源地址https://www.toymoban.com/news/detail-476764.html

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

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

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

相关文章

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

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

    2024年02月07日
    浏览(43)
  • PAJ7620U2手势识别——配置0x00寄存器(3)

      在前面的教程中,小编带领各位读者学习了如何通过I2C协议去唤醒PAJ7620U2,如何激活BANK0。本章教程,小编会继续一步一步带领各位读者,继续学习如何配置0x00寄存器,具体操作请仔细阅读本章教程。   在回答这个问题之前,我们先看一下正点原子给的该模块的文档:

    2024年02月04日
    浏览(41)
  • PAJ7620U2手势识别——读取0x00寄存器数据(4)

      在之前的教程中,小编带领各位读者完成了手势识别模块PAJ7620U2的基本设置,本章教程通过读取0x00寄存器内的值,判断该值是否为0x20,如果是,则代表唤醒成功,如果不是,则代表唤醒失败,需要重新回到唤醒操作。具体的操作步骤请各位读者继续往下浏览。   相信

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

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

    2024年02月07日
    浏览(48)
  • 手势识别(二) - 静态手势动作识别

    我公司的科室开始在公众号上规划一些对外的技术文章了,包括实战项目、模型优化、端侧部署和一些深度学习任务基础知识,而我负责人体图象相关技术这一系列文章,偶尔也会出一些应用/代码解读等相关的文章。 文章在同步发布至公众号和博客,顺带做一波宣传。有兴

    2024年02月04日
    浏览(59)
  • 手势识别-手势音量控制(opencv)

     本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等。 手势识别系列文章 1.opencv实现手部追踪(定位手部关键点) 2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用) 3.手势识别-手势音量控制(open

    2024年02月13日
    浏览(66)
  • 基于Mediapipe的Python手势识别项目(手势识别游戏)附项目源码

    基于Mediapipe的手势识别,完成的手势识别游戏。运行效果图如下: 首先是初始的界面效果图: 游戏规则:屏幕上会出现蚊子和蜜蜂,当手蜷曲握起时,表示抓的动作。如果抓到右边移动的蚊子,则会增加分数,如果抓到右边的蜜蜂,则会出现被蛰到的声音 :) 调用Mediapip

    2024年02月11日
    浏览(109)
  • opencv实战项目 手势识别-手势控制鼠标

    手势识别是一种人机交互技术,通过识别人的手势动作,从而实现对计算机、智能手机、智能电视等设备的操作和控制。 1.  opencv实现手部追踪(定位手部关键点) 2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用) 3.手势识别-手势音量控制(opencv) 4.opencv实战项目

    2024年02月13日
    浏览(50)
  • opencv实战项目 手势识别-手势控制键盘

    手势识别是一种人机交互技术,通过识别人的手势动作,从而实现对计算机、智能手机、智能电视等设备的操作和控制。 1.  opencv实现手部追踪(定位手部关键点) 2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用) 3.opencv实战项目 手势识别-手势控制鼠标 4.opencv实战

    2024年02月13日
    浏览(43)
  • 姿态识别、手势识别(附代码)

    姿态识别技术是一种基于计算机视觉的人体姿态分析方法,可以通过分析人体的姿态,提取出人体的关键点和骨架信息,并对人体的姿态进行建模和识别。随着深度学习技术的发展,近年来姿态识别技术得到了广泛的应用和研究,其中Pose是一种基于深度学习的姿态识别工具包

    2023年04月25日
    浏览(45)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包