从原子那买了一个手势识别模块,自己做了个东西。用的标准库。
由于模块自带上拉电阻,所以没有再外接,直接CON2用了一个插座。
PB6-SCL PB7-SDA 而INT没有使用
单片机:STM32F103RCT6
首先是IIC底层程序,写过很多IIC了,直接拿来使用:
void GS_i2c_init(void) //PB6-SCL PB7-SDA
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50Mhz速度
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //输出高
}
void GS_SDA_IN() //PB7
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
void GS_SDA_OUT()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
//产生IIC起始信号
static void GS_IIC_Start(void)
{
GS_SDA_OUT();//sda线输出
GS_IIC_SDA = 1;
GS_IIC_SCL = 1;
delay_us(4);
GS_IIC_SDA = 0;//START:when CLK is high,DATA change form high to low
delay_us(4);
GS_IIC_SCL = 0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
static void GS_IIC_Stop(void)
{
GS_SDA_OUT();//sda线输出
GS_IIC_SCL = 0;
GS_IIC_SDA = 0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
GS_IIC_SCL = 1;
GS_IIC_SDA = 1;//发送I2C总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
static u8 GS_IIC_Wait_Ack(void)
{
u8 ucErrTime = 0;
GS_SDA_IN(); //SDA设置为输入
GS_IIC_SDA = 1;
delay_us(3);
GS_IIC_SCL = 1;
delay_us(3);
while(GS_READ_SDA)
{
ucErrTime++;
if(ucErrTime > 250)
{
GS_IIC_Stop();
return 1;
}
}
GS_IIC_SCL = 0;//时钟输出0
return 0;
}
//产生ACK应答
static void GS_IIC_Ack(void)
{
GS_IIC_SCL = 0;
GS_SDA_OUT();
GS_IIC_SDA = 0;
delay_us(3);
GS_IIC_SCL = 1;
delay_us(3);
GS_IIC_SCL = 0;
}
//不产生ACK应答
static void GS_IIC_NAck(void)
{
GS_IIC_SCL = 0;
GS_SDA_OUT();
GS_IIC_SDA = 1;
delay_us(2);
GS_IIC_SCL = 1;
delay_us(2);
GS_IIC_SCL = 0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
static void GS_IIC_Send_Byte(u8 txd)
{
u8 t;
GS_SDA_OUT();
GS_IIC_SCL = 0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
if((txd & 0x80) >> 7)
GS_IIC_SDA = 1;
else
GS_IIC_SDA = 0;
txd <<= 1;
delay_us(5);
GS_IIC_SCL = 1;
delay_us(5);
GS_IIC_SCL = 0;
delay_us(5);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
static u8 GS_IIC_Read_Byte(u8 ack)
{
u8 i,receive = 0;
GS_SDA_IN();//SDA设置为输入
for(i = 0;i < 8;i++ )
{
GS_IIC_SCL = 0;
delay_us(4);
GS_IIC_SCL = 1;
receive <<= 1;
if(GS_READ_SDA)
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();//释放总线
}
.h文件定义:
//BANK寄存器枚举
typedef enum{
BANK0 = 0, //BANK0寄存器
BANK1, //BANK1寄存器
}bank_e;
extern u8 change;
#define PAJ7620_ID 0x73<<1 //设备地址
#define PAJ_REGITER_BANK_SEL 0XEF //BANK选择寄存器
#define PAJ_BANK0 0X00 //BANK0
#define PAJ_BANK1 0X01 //BANK1
//BANK0 寄存器组
#define PAJ_SUSPEND_CMD 0X03 //设置设备挂起
#define PAJ_SET_INT_FLAG1 0X41 //设置手势检测中断寄存器1
#define PAJ_SET_INT_FLAG2 0X42 //设置手势检测中断寄存器2
#define PAJ_GET_INT_FLAG1 0X43 //获取手势检测中断标志寄存器1(获取手势结果)
#define PAJ_GET_INT_FLAG2 0X44 //获取手势检测中断标志寄存器2(获取手势结果)
#define PAJ_GET_STATE 0X45 //获取手势检测工作状态
#define PAJ_SET_HIGH_THRESHOLD 0x69 //设置滞后高阀值(仅在接近检测模式下)
#define PAJ_SET_LOW_THRESEHOLD 0X6A //设置滞后低阀值
#define PAJ_GET_APPROACH_STATE 0X6B //获取接近状态 (1:PS data>= PS threshold ,0:PS data<= Low threshold)
#define PAJ_GET_GESTURE_DATA 0X6C //获取接近数据
#define PAJ_GET_OBJECT_BRIGHTNESS 0XB0 //获取被照物体亮度(最大255)
#define PAJ_GET_OBJECT_SIZE_1 0XB1 //获取被照物体大小低八位(bit7:0)(最大900)
#define PAJ_GET_OBJECT_SIZE_2 0XB2 //获取被照物体大小高四位(bit3:0)
//BANK1 寄存器组
#define PAJ_SET_PS_GAIN 0X44 //设置检测增益大小 (0:1x gain 1:2x gain)
#define PAJ_SET_IDLE_S1_STEP_0 0x67 //设置S1的响应因子
#define PAJ_SET_IDLE_S1_STEP_1 0x68
#define PAJ_SET_IDLE_S2_STEP_0 0X69 //设置S2的响应因子
#define PAJ_SET_IDLE_S2_STEP_1 0X6A
#define PAJ_SET_OP_TO_S1_STEP_0 0X6B //设置OP到S1的过度时间
#define PAJ_SET_OP_TO_S1_STEP_1 0X6C
#define PAJ_SET_S1_TO_S2_STEP_0 0X6D //设置S1到S2的过度时间
#define PAJ_SET_S1_TO_S2_STEP_1 0X6E
#define PAJ_OPERATION_ENABLE 0X72 //设置PAJ7620U2使能寄存器
//手势识别效果
#define BIT(x) 1<<(x)
#define GES_UP BIT(0) //向上
#define GES_DOWM BIT(1) //向下
#define GES_LEFT BIT(2) //向左
#define GES_RIGHT BIT(3) //向右
#define GES_FORWARD BIT(4) //向前
#define GES_BACKWARD BIT(5) //向后
#define GES_CLOCKWISE BIT(6) //顺时针
#define GES_COUNT_CLOCKWISE BIT(7) //逆时针
#define GES_WAVE BIT(8) //挥动
extern u8 printfbuff[40];
extern u8 printlen;
extern u8 change_mu;
void paj7620u2_selectBank(bank_e bank);
u8 paj7620u2_wakeup(void);
void Gesture_test(void);
void Gesture_test_mu(void);
u8 paj7620u2_init(void);