PAJ7620手势传感器快速驱动- -基于涂鸦CBU模组开发板
正在,或是想要开发物联网小产品的你是否会觉得一些常用的控制需要繁琐地掏出手机会让你的产品体验不佳?添加实体按键又显得太 low ?不妨来试试既能满足线下控制又能让你的小产品变酷炫的手势传感器吧!
硬件方案
使用的传感器型号为PAJ7260,可以识别上、下、左、右、向前、向后、顺时针、逆时针和挥动9种手势,并将手势信号通过IIC协议通信传输给主控,功能相当强大。
主控部分选用的是一块搭载了涂鸦CBU模组的开发板,模组详细信息可查看模组规格书。
由于 CBU 模组没有硬件IIC,所以传感器的SDA和SCL引脚可以连接用模组任意两个IO口,用模拟IIC的方式与传感器通信。INT引脚是中断输出脚,本文例程用的是轮询获取传感器数据的方式,所以可以不接。
软件实现
首先是根据IIC通信基本协议实现起始信号、停止信号、应答信号、单字节数据等相关的发送、接收操作:
STATIC int __iic_start(VOID)
{
vI2CSDASet();
vI2CSCLSet();
vI2CDelay(5);
vI2CSDAReset();
vI2CDelay(5);
vI2CSCLReset();
return 0;
}
STATIC int __iic_stop(VOID)
{
vI2CSCLReset();
vI2CSDAReset();
vI2CDelay(5);
vI2CSCLSet();
vI2CSDASet();
vI2CDelay(5);
return 0;
}
STATIC VOID __iic_send_ack(VOID)
{
vI2CSCLReset();
vI2CSDAReset();
vI2CDelay(2);
vI2CSCLSet();
vI2CDelay(2);
vI2CSCLReset();
}
STATIC VOID __iic_send_nack(VOID)
{
vI2CSCLReset();
vI2CSDASet();
vI2CDelay(2);
vI2CSCLSet();
vI2CDelay(2);
vI2CSCLReset();
}
STATIC UINT8_T __iic_recv_ack(VOID)
{
UINT8_T ucErrTime=0;
UINT8_T recv_ack;
vI2CSDARelease();
vI2CSCLSet();
vI2CDelay(5);
while(ucI2CSDAInputRead()) {
ucErrTime++;
if(ucErrTime>250) {
__iic_stop();
PR_NOTICE("-------iic ack error-----");
return 1;
}
}
vI2CSCLReset();
return 0;
}
STATIC VOID __iic_send_byte(UCHAR_T sendbyte)
{
UCHAR_T i = 0;
vI2CSCLReset;
for(i = 0x80; i > 0; i >>= 1)
{
if((sendbyte & i) == 0) {
vI2CSDAReset();
} else {
vI2CSDASet();
}
vI2CDelay(2);
vI2CSCLSet();
vI2CDelay(2);
vI2CSCLReset();
vI2CDelay(2);
}
}
STATIC UINT8_T __iic_read_byte(UCHAR_T ack)
{
UCHAR_T i = 0;
UCHAR_T readbyte = 0;
vI2CSDARelease();
for(i = 0x80; i > 0; i >>= 1)
{
vI2CSCLReset();
vI2CDelay(2);
vI2CSCLSet();
if(ucI2CSDAInputRead()) {
readbyte |= i;
}
vI2CDelay(2);
}
if(!ack) {
__iic_send_nack();
}else {
__iic_send_ack();
}
return readbyte;
}
然后,使用上面实现好的操作函数搭出 PAJ7620 的完整一帧数据的发送和读取函数:
VOID paj7620_iic_write(UINT8_T drv_addr, UINT8_T reg_addr, UINT8_T reg_data)
{
__iic_start();
__iic_send_byte((drv_addr << 1)); //发送从机地址写命令
__iic_recv_ack();
__iic_send_byte(reg_addr);
__iic_recv_ack();
__iic_send_byte(reg_data);
__iic_recv_ack();
__iic_stop();
}
VOID paj7620_iic_read(UINT8_T drv_addr, UINT8_T reg_addr, UINT8_T *p_data)
{
__iic_start();
__iic_send_byte((drv_addr << 1) | 0x00); //发送从机地址写命令
__iic_recv_ack();
__iic_send_byte(reg_addr);
__iic_recv_ack();
__iic_send_byte((drv_addr << 1) | 0x01); //发送从机地址读命令
__iic_recv_ack();
*p_data = __iic_read_byte(1);
__iic_stop();
}
PAJ7620 在初始化时需要唤醒,唤醒方法就是发送地址后直接发送停止就可以了,不用等待 PAJ7620 的应答。发送完唤醒后,读取 PAJ7620 的 0x00 寄存器,若数值为 0x20 则表示唤醒成功:
VOID paj7620_wake_up(VOID)
{
UINT8_T data = 0x0a;
UINT8_T i =0;
__iic_start();
__iic_send_byte(PAJ7620_I2C_ADDR << 1);
__iic_stop();
vI2CDelay(1000);
__iic_start();
__iic_send_byte(PAJ7620_I2C_ADDR << 1);
__iic_stop();
paj7620_iic_write(PAJ7620_I2C_ADDR,PAJ7620_ADDR_BASE,PAJ7620_BANK0);
paj7620_iic_read(PAJ7620_I2C_ADDR, 0x00, &data);
if(data!= 0x20) {
PR_NOTICE("PAJ7620 init failed");
}
}
然后是 PAJ7620 的初始化函数:
VOID paj7620_init(PAJ7620_init_t* param)
{
UINT8_T flag;
UINT8_T i;
i2c_pin_t i2c_config = {
.ucSDA_IO = param ->SDA_PIN,
.ucSCL_IO = param ->SCL_PIN,
};
opSocI2CInit(&i2c_config); /* SDA&SCL GPIO INIT */
vI2CDelay(100);
paj7620_wake_up();
//进入BANK0寄存器区域
paj7620_iic_write(PAJ7620_I2C_ADDR,PAJ7620_ADDR_BASE,PAJ7620_BANK0);
//发送 PAJ7620 初始化命令
for(i = 0; i < 51; i++) {
paj7620_iic_write(PAJ7620_I2C_ADDR,PAJ7620Global_InitArray[i][0], PAJ7620Global_InitArray[i][1]);
}
paj7620_iic_write(PAJ7620_I2C_ADDR,PAJ7620_ADDR_BASE,PAJ7620_BANK0);
paj7620_wake_up();
paj7620_iic_write(PAJ7620_I2C_ADDR,PAJ7620_ADDR_BASE,PAJ7620_BANK0);
//发送手势识别模式初始化命令
for(i = 0; i < 30; i++) {
paj7620_iic_write(PAJ7620_I2C_ADDR,PAJ7620Gesture_InitArray[i][0], PAJ7620Gesture_InitArray[i][1]);
}
}
最后是实现手势信号的读取接口:
UINT16_T paj7620_get_data(UINT8_T reg_addr)
{
UINT8_T i = 0;
UINT8_T data;
__iic_start();
__iic_send_byte((PAJ7620_I2C_ADDR << 1) | 0x00); //发送从机地址写命令
__iic_recv_ack();
__iic_send_byte(reg_addr);
__iic_recv_ack();
__iic_start();
__iic_send_byte((PAJ7620_I2C_ADDR << 1) + 1);
__iic_recv_ack();
data = __iic_read_byte(0);
__iic_stop();
paj7620_iic_write(PAJ7620_I2C_ADDR,PAJ7620_ADDR_BASE,PAJ7620_BANK0);
return data;
}
UINT8_T paj7620_read_gesture_state(VOID)
{
switch (paj7620_get_data(PAJ_GET_INT_FLAG1))
{
case GES_UP://向上
return 1;
case GES_DOWM://向下
return 2;
case GES_LEFT://向左
return 3;
case GES_RIGHT://向右
return 4;
case GES_FORWARD://向前
return 5;
case GES_BACKWARD: //向后
return 6;
case GES_CLOCKWISE://顺时针
return 7;
case GES_COUNT_CLOCKWISE://逆时针
return 8;
case GES_WAVE://挥动
return 9;
default:
return 0;
}
}
至此,PAJ7260 的驱动代码就全部完成啦,使用时只需调用一次paj7620_init(&paj7620_init_param)初始化传感器,然后在循环内调用paj7620_read_gesture_state()来不停获取识别到的手势,再根据手势值来进行想要执行的功能即可。
总结
PAJ7620 传感器功能强大,适用场景广泛,在各类智能产品中都能找到应用之处。挥挥手打开风扇,划一下打开台灯… … 各种常用操作都可以变成“举手之劳”。
若想使用涂鸦 CBU 模组SOC开发方案体验PAJ7620传感器的话,可以去本文例程的github库里参照 readme 文档进行编译烧录。
本文例程:github