前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开发者成长激励计划-基于TencentOS Tiny 的隔空手势PAJ7620传感器智能家居控制应用

开发者成长激励计划-基于TencentOS Tiny 的隔空手势PAJ7620传感器智能家居控制应用

原创
作者头像
用户9104757
修改2022-08-28 22:26:57
4070
修改2022-08-28 22:26:57
举报
文章被收录于专栏:TencentOS Tiny开发TencentOS Tiny开发

一、开篇

感谢主办方提供这次活动,对TencentOS Tiny能有一次全面学习,这次的经历非常不错,从中也学习到了很多知识与经验,讨论群里全国各地开发者也是非常活跃,氛围非常友好。

二、应用场景及主要功能描述:

疫情当下,非接触性地设备启动,应用场景越来越适应市场的需求,手势传感器PAJ7620U2是其中的代表之一,我的大致思路如下:

1. 学习手势传感器PAJ7620U2驱动;

2. 基于TencentOS Tiny CH32V_EVB RISC-V开发套件(采用WCH的RISC-V CH32V307VCT6 MCU)整合手势传感器PAJ7620U2;

3. 借助板载LED灯,做应用的原型产品测试;

三、产品方案设计:

四、硬件及沁恒CH32V307_EVB开发板使用到的引脚

1、手势传感PAJ7620U2

2、CH32V307_EVB开发板

五、部分核心代码:

paj7620u2_iic.h文件:

代码语言:javascript
复制
#define SDA_GPIO    GPIO_Pin_11
#define SDA_PORT    GPIOB
#define SDA_RCC     RCC_APB2Periph_GPIOB
#define SCL_GPIO    GPIO_Pin_10
#define SCL_PORT    GPIOB
#define SCL_RCC     RCC_APB2Periph_GPIOB
#define DELAY_US(x) Delay_Us(x)
#define DELAY_MS(x) Delay_Ms(x)

//SDA       PB11
//SCL       PB10
#define SDA_H   GPIO_SetBits(SDA_PORT,SDA_GPIO)
#define SDA_L   GPIO_ResetBits(SDA_PORT,SDA_GPIO)
#define SDA_R   GPIO_ReadInputDataBit(SDA_PORT,SDA_GPIO)

#define SCL_H   GPIO_SetBits(SCL_PORT,SCL_GPIO)
#define SCL_L   GPIO_ResetBits(SCL_PORT,SCL_GPIO)



u8 GS_Write_Byte(u8 REG_Address,u8 REG_data);
u8 GS_Read_Byte(u8 REG_Address);
u8 GS_Read_nByte(u8 REG_Address,u16 len,u8 *buf);
void GS_i2c_init(void);
void GS_WakeUp(void);
void IIC_SpeedCtl(unsigned short speed);
void SDA_SetGpioMode(uint8_t mode);
void SCL_SetGpioMode(uint8_t mode);
void IIC_delay(uint16_t n);

paj7620u2_iic.c文件:

代码语言:javascript
复制
//PAJ2670 I2C初始化
void GS_i2c_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(SCL_RCC|SDA_RCC,ENABLE);

    //SDA
    GPIO_InitStructure.GPIO_Pin=SDA_GPIO;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(SDA_PORT,&GPIO_InitStructure);
    GPIO_SetBits(SDA_PORT,SDA_GPIO);

    //SCL
    GPIO_InitStructure.GPIO_Pin=SCL_GPIO;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(SCL_PORT,&GPIO_InitStructure);
    GPIO_SetBits(SCL_PORT,SCL_GPIO);

}

/***************************************************************************************************************
*switch SDA GPIO input or output
****************************************************************************************************************/
void SDA_SetGpioMode(uint8_t mode)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(SDA_RCC,ENABLE);

    GPIO_InitStructure.GPIO_Pin=SDA_GPIO;

    if(mode==1)
    {
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    }
    else
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_Init(SDA_PORT,&GPIO_InitStructure);
}

void SCL_SetGpioMode(uint8_t mode)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(SCL_RCC,ENABLE);

    GPIO_InitStructure.GPIO_Pin=SCL_GPIO;

    if(mode==1)
    {
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    }
    else
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
    GPIO_Init(SCL_PORT,&GPIO_InitStructure);
}

//产生IIC起始信号
static void GS_IIC_Start(void)
{
    SDA_SetGpioMode(1);
    SDA_H;
    SCL_H;
    Delay_Us(4);
    SDA_L;
    Delay_Us(4);
    SCL_L;
}

//产生IIC停止信号
static void GS_IIC_Stop(void)
{
    SDA_SetGpioMode(1);//sda线输出
    SCL_L;
    SDA_L;
    Delay_Us(4);
    SCL_H;
    SDA_H;
    Delay_Us(4);
}

//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
static u8 GS_IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_SetGpioMode(0);  //SDA设置为输入
	SDA_H;Delay_Us(3);
	SCL_H;Delay_Us(3);
    while(SDA_R)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            GS_IIC_Stop();
            return 1;
        }
    }
    SCL_L;
    return 0;
}

//产生ACK应答
static void GS_IIC_Ack(void)
{
    SCL_L;
    SDA_SetGpioMode(1);
    SDA_L;
    Delay_Us(3);
    SCL_H;
    Delay_Us(3);
    SCL_L;
}

//不产生ACK应答		    
static void GS_IIC_NAck(void)
{
    SCL_L;
    SDA_SetGpioMode(1);
    SDA_H;
    Delay_Us(2);
    SCL_H;
    Delay_Us(2);
    SCL_L;
}

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
static void GS_IIC_Send_Byte(u8 txd)
{
    u8 t;
    SDA_SetGpioMode(1);
    SCL_L;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {
      if((txd&0x80)>>7)
          SDA_H;
      else
          SDA_L;
      txd<<=1;
      Delay_Us(5);
      SCL_H;
      Delay_Us(5);
      SCL_L;
      Delay_Us(5);
    }
} 

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
static u8 GS_IIC_Read_Byte(u8 ack)
{
    u8 i,receive=0;
    SDA_SetGpioMode(0);//SDA设置为输入
    for(i=0;i<8;i++ )
    {
        SCL_L;
        Delay_Us(4);
        SCL_H;
        receive<<=1;
        if(SDA_R)receive++;
        Delay_Us(4);
    }
    if (!ack)
        GS_IIC_NAck();//发送nACK
    else
        GS_IIC_Ack(); //发送ACK
    return receive;
}

//PAJ7620U2写一个字节数据
u8 GS_Write_Byte(u8 REG_Address,u8 REG_data)
{
	GS_IIC_Start();
	GS_IIC_Send_Byte(PAJ7620_ID);
	if(GS_IIC_Wait_Ack())
	{
		GS_IIC_Stop();//释放总线
		return 1;//没应答则退出

	}
	GS_IIC_Send_Byte(REG_Address);
	GS_IIC_Wait_Ack();	
	GS_IIC_Send_Byte(REG_data);
	GS_IIC_Wait_Ack();	
	GS_IIC_Stop();

	return 0;
}

//PAJ7620U2读一个字节数据
u8 GS_Read_Byte(u8 REG_Address)
{
	u8 REG_data;
	
	GS_IIC_Start();
	GS_IIC_Send_Byte(PAJ7620_ID);//发写命令
	if(GS_IIC_Wait_Ack())
	{
		 GS_IIC_Stop();//释放总线
		 return 0;//没应答则退出
	}		
	GS_IIC_Send_Byte(REG_Address);
	GS_IIC_Wait_Ack();
	GS_IIC_Start(); 
	GS_IIC_Send_Byte(PAJ7620_ID|0x01);//发读命令
	GS_IIC_Wait_Ack();
	REG_data = GS_IIC_Read_Byte(0);
	GS_IIC_Stop();

	return REG_data;
}
//PAJ7620U2读n个字节数据
u8 GS_Read_nByte(u8 REG_Address,u16 len,u8 *buf)
{
	GS_IIC_Start();
	GS_IIC_Send_Byte(PAJ7620_ID);//发写命令
	if(GS_IIC_Wait_Ack()) 
	{
		GS_IIC_Stop();//释放总线
		return 1;//没应答则退出
	}
	GS_IIC_Send_Byte(REG_Address);
	GS_IIC_Wait_Ack();

	GS_IIC_Start();
	GS_IIC_Send_Byte(PAJ7620_ID|0x01);//发读命令
	GS_IIC_Wait_Ack();
	while(len)
	{
		if(len==1)
		{
			*buf = GS_IIC_Read_Byte(0);
		}
		else
		{
			*buf = GS_IIC_Read_Byte(1);
		}
		buf++;
		len--;
	}
	GS_IIC_Stop();//释放总线

	return 0;
	
}
//PAJ7620唤醒
void GS_WakeUp(void)
{
	GS_IIC_Start();
	GS_IIC_Send_Byte(PAJ7620_ID);//发写命令
	GS_IIC_Stop();//释放总线
}

paj7620u2.c文件:

代码语言:javascript
复制
//手势识别测试
void Gesture_test(void)
{
	u8 i;
    u8 status;
	u8 key;
	u8 data[2]={0x00};
	u16 gesture_data;
	u8 ledflash=0;
	
	paj7620u2_selectBank(BANK0);//进入BANK0寄存器区域
	for(i=0;i<GESTURE_SIZE;i++)
	{
		GS_Write_Byte(gesture_arry[i][0],gesture_arry[i][1]);//手势识别模式初始化
	}
	paj7620u2_selectBank(BANK0);//切换回BANK0寄存器区域
	i=0;
	LCD_Fill(30,170,300,300,WHITE);

	LCD_ShowString(0,70,"---  Gesture show  ---",WHITE,BLACK,16,0);

	while(1)
	{
        status = GS_Read_nByte(PAJ_GET_INT_FLAG1,2,&data[0]);//读取手势状态			
		if(!status)
		{   
			gesture_data =(u16)data[1]<<8 | data[0];
			if(gesture_data) 
			{
				switch(gesture_data)
				{
					case GES_UP:
					    LCD_ShowString(0,100,"UP:                 ",WHITE,BLACK,32,0);
					    LCD_ShowString(0,130,"    LED1 ON      ",WHITE,BLACK,32,0);
					    printf("Up\r\n");
					    ledflash=1;
					    GPIO_WriteBit(GPIOE, GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5, 1);
					    GPIO_WriteBit(GPIOE, GPIO_Pin_2, 0);
					    break; //向上
					case GES_DOWM:
					    LCD_ShowString(0,100,"Dowm:               ",WHITE,BLACK,32,0);
					    LCD_ShowString(0,130,"    LED2 ON      ",WHITE,BLACK,32,0);
               			printf("Dowm\r\n");
               			ledflash=1;
               			GPIO_WriteBit(GPIOE, GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5, 1);
               			GPIO_WriteBit(GPIOE, GPIO_Pin_3, 0);
               			break; //向下
					case GES_LEFT:
					    LCD_ShowString(0,100,"Left:               ",WHITE,BLACK,32,0);
					    LCD_ShowString(0,130,"    LED3 ON      ",WHITE,BLACK,32,0);
  						printf("Left\r\n");
  						ledflash=1;
  						GPIO_WriteBit(GPIOE, GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5, 1);
  						GPIO_WriteBit(GPIOE, GPIO_Pin_4, 0);
  						break; //向左
					case GES_RIGHT:
					    LCD_ShowString(0,100,"Right:              ",WHITE,BLACK,32,0);
					    LCD_ShowString(0,130,"    LED4 ON      ",WHITE,BLACK,32,0);
                		printf("Right\r\n");
                		ledflash=1;
                		GPIO_WriteBit(GPIOE, GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5, 1);
                		GPIO_WriteBit(GPIOE, GPIO_Pin_5, 0);
                		break; //向右
					default:                    LCD_ShowString(0,100,"check          ",WHITE,BLACK,16,0);
					    ledflash=0; break;
					
				}	
			}
			
		}
		Delay_Ms(300);
		i++;
		printf("### check %d\r\n",i);
		if(i==500)
		{
			//LED0=!LED0;//提示系统正在运行
			i=0;
		}		   
	}
}

源代码项目工程文件:

六、视频展示:

https://www.bilibili.com/video/BV1MP411L7K4 B站链接

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、开篇
  • 二、应用场景及主要功能描述:
  • 三、产品方案设计:
  • 四、硬件及沁恒CH32V307_EVB开发板使用到的引脚
    • 1、手势传感PAJ7620U2
      • 2、CH32V307_EVB开发板
      • 五、部分核心代码:
        • paj7620u2_iic.h文件:
          • paj7620u2_iic.c文件:
            • paj7620u2.c文件:
            • 六、视频展示:
            相关产品与服务
            TencentOS Server
            TencentOS Server 是腾讯云推出的 Linux 操作系统,它旨在为云上运行的应用程序提供稳定、安全和高性能的执行环境。它可以运行在腾讯云 CVM 全规格实例上,包括黑石物理服务器2.0。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档