打印
[STM32L5]

【STM32L562E-DK测评活动】by clever:04-硬件IIC读取手势模块

[复制链接]
370|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 聪聪哥哥 于 2025-2-27 15:13 编辑

#申请原创# @21小跑堂 @21ic小管家 使用STM32L562的硬件IIC读取手势模块的数据,为后期制作小产品做一个准备;硬件准备:STM32L562开发板、MB1280B拓展板、手势模块及mic-USB线
一:STM32L526 硬件IIC的知识分享:
该设备嵌入四个12C。请参阅表17:12C实现以了解功能实现。
12C总线接口处理微控制器和串行12C总线之间的通信。它控制所有12C总线特定的序列、协议、仲裁和定时。
L2C外围设备支持:
12C总线规范和用户手册第5版兼容性:
奴隶和主人模式,多主人能力
标准模式(Sm),比特率最高可达100 kbit/s
快速模式(Fm),比特率可达400 kbit/s
快速模式加(Fm+),具有高达1Mbit/s的比特率和20 mA输出驱动I/0
7位和10位寻址模式,多个7位从机地址
可编程设置和保持时间
可选时钟拉伸
系统管理总线(SMBus)规范修订版2.0兼容性:
硬件PEC(分组错误检查)生成和验证,带有ACK控制
地址解析协议(ARP)支持
SMBus警报
电力系统管理协议(PMBUS)规范修订版 1.1兼容性独立时钟:可以选择独立的时钟源,使12C通信速度独立于PCLK重编程。参见图7:STM32L562xx时钟树
地址匹配时从停止模式唤醒
可编程模拟和数字噪声滤波器
具有 DMA功能的1字节缓冲区

二:手势模块的资料分享:
模块资料介绍:PAJ7620U2 Gesture Sensor是一款基于PAJ7620U2的手势识别模块,可直接识别9种基本手势,支持I2C接口,兼容3.3V/5V电平。这里为了方式调试,我使用的是STM32硬件的IIC驱动代码,也加深了自己对IIC通讯的理解;
模块资料:
电源电压 : 3.3V/5V
工作原理:光学数组式环境亮度传感检测
通讯接口:I²C 接口,400Khz(Max)
识别速度:240Hz
工作环境光:<100K Lux(抗灯光干扰)
有效探测距离:5~15cm
检测角度范围:60°~180°
手势识别种类:内置 9 个手势类型:(上、下、左、右、前、后、顺时针旋转、逆时针旋转、挥动)
功耗:3~10mA(待机功耗电流 15u)
红外LED手势识别原理:传感器工作时通过内部 LED 驱动器,驱动红外 LED 向外发射红外线信号,当传感器阵列在有效的距离中探测到物体时,目标信息提取阵列会对探测目标进行特征原始数据的获取,采集到的数据被保存在寄存器中,同时手势识别阵列会对原始数据进行识别处理,最后将手势结果存到寄存器中。
根据 PAJ7620U2传感器数据手册,用户可通过I²C接口总线采集信号并迅速识别出UP、Down、Right、Left等9种常用手势。另外PAJ7620U2还提供内置的接近检测功能,用于检测物体的接近或离开。
实物图片如下所示:

三:硬件连接:
3.1 原理图查看:

1脚  GND   供电负极
2脚 VCC  供电正极 设计的是3V3
3脚 SDA  IIC的数据线   PB6    
4脚 SCL  IIC的时钟线      PB7 

3.2:STM32 cubeMX 软件配置如下所示:

这里i为了方便,我们使用默认的参数就可以,然后在生成的代码中,添加对手势模块的驱动程序就可以。
3.3 添加串口1的配置信息
本款开发板,已将串口1连接到调试器的串口上面,我们只需要使用引脚的PA9,PA10配置好,使用printf重映射就可以。直接把调试信息输出到串口就可以。
具体的配置过程,大家可以参考我之前写的帖子就可以,这里就不再重复介绍
https://bbs.21ic.com/icview-3434762-1-1.html
四:手势模块的主要代码如下所示:
/**************************************************************************************************
  * 函数功能: static unsigned char PAJ7620_send_byte(unsigned char dta)
  * 输入参数: data
  * 返 回 值: 1:正常 0:异常
  * 说    明: 通过IIC向模块发送一个字节
  *
***************************************************************************************************/
static unsigned char PAJ7620_send_byte(unsigned char data)
{        
        if (HAL_I2C_Master_Transmit(&hi2c1, PAJ7620_I2C_ADDR, &data, 1, 100) != HAL_OK)
        {
                return 0;
        }
        return 1;        
}
/**************************************************************************************************
  * 函数功能: static unsigned char PAJ7620_send_byteS(unsigned char *data, unsigned char length)
  * 输入参数: data  length
  * 返 回 值: 1:正常 0:异常
  * 说    明: 通过IIC向模块发送 长度为length 的数据
  *
***************************************************************************************************/
static unsigned char PAJ7620_send_byteS(unsigned char *data, unsigned char length)
{
        if (HAL_I2C_Master_Transmit(&hi2c1, PAJ7620_I2C_ADDR, data, length, 100) != HAL_OK)
        {
                return 0;
        }
        return 1;
}
/**************************************************************************************************
  * 函数功能: static unsigned char PAJ7620_read_byteS(unsigned char *data, unsigned char length)
  * 输入参数: data  length
  * 返 回 值: 1:正常 0:异常
        * 说    明: 通过IIC向模块读取 长度为length 的数据
  *
***************************************************************************************************/
static unsigned char PAJ7620_read_byteS(unsigned char *data, unsigned char length)
{
        /* Do the read */
        if (HAL_I2C_Master_Receive(&hi2c1, PAJ7620_I2C_ADDR, data, length, 100) != HAL_OK)
        {
                return 0;
        }
        return 1;
}
/**************************************************************************************************
  * 函数功能: static void writeReg(uint8_t addr, uint8_t value)
  * 输入参数: addr  value
  * 返 回 值: 无
        * 说    明: 通过 IIC 向模块的指定寄存器写入数据
  *
***************************************************************************************************/
static void writeReg(uint8_t addr, uint8_t value)
{
        unsigned char dta[2] = {0};
        dta[0] = addr;
        dta[1] = value;
        PAJ7620_send_byteS(dta, 2);
}
/**************************************************************************************************
  * 函数功能: static unsigned char readRegs(uint8_t addr, uint8_t *values, int size)
  * 输入参数: addr  values  size
  * 返 回 值: 无
        * 说    明: 通过 IIC 向模块的读取 指定寄存器及其该寄存器的之后的数据长度
  *
***************************************************************************************************/
static unsigned char readRegs(uint8_t addr, uint8_t *values, int size)
{
        if (PAJ7620_send_byte(addr) != 1)
                return 0;
        if (PAJ7620_read_byteS(values, size) != 1)
                return 0;
        return 1;
}
/**************************************************************************************************
  * 函数功能: static unsigned char readReg(uint8_t addr)
  * 输入参数: addr  
  * 返 回 值: 无
        * 说    明: 通过 IIC 向模块的读取 指定寄存器的数据
  *
***************************************************************************************************/
static unsigned char readReg(uint8_t addr)
{
        uint8_t values;
        readRegs(addr, &values, 1);
        return values;
}
/**************************************************************************************************
  * 函数功能: void paj7620u2_selectBank(bank_e bank)
  * 输入参数: bank  
  * 返 回 值: 无
        * 说    明: 通过 IIC 向模块的读取 指定寄存器的数据
  *
***************************************************************************************************/
void paj7620u2_selectBank(bank_e bank)
{
        switch (bank)
        {
        case BANK0:
                writeReg(PAJ_REGITER_BANK_SEL, PAJ_BANK0);
                break; // BANK0
        case BANK1:
                writeReg(PAJ_REGITER_BANK_SEL, PAJ_BANK1);
                break; // BANK1
        }
}
void GS_WakeUp()
{
        PAJ7620_send_byte(0);
}
/**************************************************************************************************
  * 函数功能: unsigned char paj7620u2_wakeup()
  * 输入参数: bank  
  * 返 回 值: 无
        * 说    明: 唤醒手势模块
  *
***************************************************************************************************/
unsigned char paj7620u2_wakeup()
{
        unsigned char data1 = 0x0a;
        unsigned char data2 = 0x0a;
        GS_WakeUp();                                 // wake PAJ7620U2
        HAL_Delay(5);                                 // wake time >400us
        GS_WakeUp();                                 // wake PAJ7620U2
        HAL_Delay(5);                                 // wake time>400us
        paj7620u2_selectBank(BANK0); //进入BANK0
        /* check ID */
        data1 = readReg(0x00); //读取id
        data2 = readReg(0x01); //读取id
        if ((data2 != 0x76) || (data1 != 0x20))
                return 0;
        return 1;
}
/**************************************************************************************************
  * 函数功能: unsigned char PAJ7620u2_init(void)
  * 输入参数:   
  * 返 回 值: 无
        * 说    明: 模块初始化
  *
***************************************************************************************************/
unsigned char PAJ7620u2_init(void)
{
        unsigned char status;
        HAL_Delay(10);
        status = paj7620u2_wakeup(); //唤醒PAJ7620U2
        if (!status)
                return 0;
        paj7620u2_selectBank(BANK0); // enter BANK0
        HAL_Delay(50);
        /* Load the registers data */
        for (uint8_t i = 0; i < INIT_REG_ARRAY_SIZE; i++)
                writeReg(initRegisterArray[i][0], initRegisterArray[i][1]); // init PAJ7620U2
        paj7620u2_selectBank(BANK0);                                                                        // enter BANK0
        return 1;
}
/**************************************************************************************************
  * 函数功能: void Gesture_Init(void)
  * 输入参数:   
  * 返 回 值: 无
        * 说    明: 模块初始化
  *
***************************************************************************************************/
void Gesture_Init(void)
{
        unsigned char i;
        paj7620u2_selectBank(BANK0); //
        for (i = 0; i < GESTURE_SIZE; i++)
        {
                writeReg(gesture_arry[i][0], gesture_arry[i][1]);
        }
        paj7620u2_selectBank(BANK0); //
        memset(&gesture, 0, sizeof(GestureData));
}
/**************************************************************************************************
  * 函数功能: void Gesture_Init(void)
  * 输入参数:   
  * 返 回 值: 无
        * 说    明: 模块初始化
  *
***************************************************************************************************/
void PAJ7620_Init(void)
{
        while (!PAJ7620u2_init()) // PAJ7620U2初始化
        {
                printf("PAJ7620U2_B Error!!!\r\n");
                HAL_Delay(500);
        }
        HAL_Delay(1000);
        printf("PAJ7620U2 OK\r\n"); //
}
unsigned char PAJ7620_Read_nByte(unsigned char addr, unsigned short len, unsigned char *buf)
{

        return readRegs(addr, &buf[0], len);
}
/**************************************************************************************************
  * 函数功能: unsigned char GetCurrentGesture(void)
  * 输入参数:   
  * 返 回 值: 无
        * 说    明: 读取模块的手势地址
  *
***************************************************************************************************/
unsigned char GetCurrentGesture(void)
{        
        uint8_t Data[2]={0,0};
        uint16_t Gesture_Data;        
        uint8_t state ;
        uint8_t i ;        
//        Gesture_Init();
//        此处判断读取来当前手势不为0时,进行处理
        state = PAJ7620_Read_nByte(PAJ_GET_INT_FLAG1, 2, &gesture.data[0]); //               

        if(state != 0)
        {
                        Gesture_Data = (gesture.data[1]<<8) | gesture.data[0];
                switch(Gesture_Data)
                {
                        
                        case PAJ_UP:                                      printf("Up\r\n");            break;
                        case PAJ_DOWN:                                printf("Down\r\n");        break;
                        case PAJ_LEFT:                                   printf("Left\r\n");          break;
                        case PAJ_RIGHT:                                 printf("Right\r\n");        break;
                        case PAJ_FORWARD:                           printf("Forward\r\n");     break;
                        case PAJ_BACKWARD:                         printf("Backward\r\n");    break;
                        case PAJ_CLOCKWISE:                        printf("Clockwise\r\n");    break;
                        case PAJ_COUNT_CLOCKWISE:            printf("AntiClockwise\r\n");break;
                        case PAJ_WAVE:                                  printf("Wave\r\n");          break;                                               
                        default: break;
                }
                Gesture_Data = 0;
        }
                return 0;
}
在主程序中,首先初始化模块信息,在主程序中,不停的调用模块当前状态就可以,如下所示:
  /* USER CODE BEGIN 2 */
        printf("autor  by congconggege\r\n");
        HAL_Delay(1000);
        printf("PAJ7620U2 Gesture Sensor Test Program ...\r\n");
        PAJ7620_Init();
        printf("PAJ7620U2 Gesture Sensor OK \r\n");
//        CorMark_main();
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
    HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_12);
    HAL_Delay(500);
    GetCurrentGesture();//
  }
五:实物测试图片和PC截图如下所示:


如图所示:在模块前做不同指令,串口接收窗口,显示当前的模块信息了。
至此,硬件IIC读取手势模块,调试完毕。


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

55

主题

157

帖子

1

粉丝