news 2026/2/4 11:06:40

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[STM32L5] 【STM32L562E-DK测评活动】by clever:04-硬件IIC读取手势模块

一: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
四:手势模块的主要代码如下所示:

复制

  1. /**************************************************************************************************
  2. * 函数功能: static unsigned char PAJ7620_send_byte(unsigned char dta)
  3. * 输入参数: data
  4. * 返 回 值: 1:正常 0:异常
  5. * 说 明: 通过IIC向模块发送一个字节
  6. *
  7. ***************************************************************************************************/
  8. static unsigned char PAJ7620_send_byte(unsigned char data)
  9. {
  10. if (HAL_I2C_Master_Transmit(&hi2c1, PAJ7620_I2C_ADDR, &data, 1, 100) != HAL_OK)
  11. {
  12. return 0;
  13. }
  14. return 1;
  15. }
  16. /**************************************************************************************************
  17. * 函数功能: static unsigned char PAJ7620_send_byteS(unsigned char *data, unsigned char length)
  18. * 输入参数: data length
  19. * 返 回 值: 1:正常 0:异常
  20. * 说 明: 通过IIC向模块发送 长度为length 的数据
  21. *
  22. ***************************************************************************************************/
  23. static unsigned char PAJ7620_send_byteS(unsigned char *data, unsigned char length)
  24. {
  25. if (HAL_I2C_Master_Transmit(&hi2c1, PAJ7620_I2C_ADDR, data, length, 100) != HAL_OK)
  26. {
  27. return 0;
  28. }
  29. return 1;
  30. }
  31. /**************************************************************************************************
  32. * 函数功能: static unsigned char PAJ7620_read_byteS(unsigned char *data, unsigned char length)
  33. * 输入参数: data length
  34. * 返 回 值: 1:正常 0:异常
  35. * 说 明: 通过IIC向模块读取 长度为length 的数据
  36. *
  37. ***************************************************************************************************/
  38. static unsigned char PAJ7620_read_byteS(unsigned char *data, unsigned char length)
  39. {
  40. /* Do the read */
  41. if (HAL_I2C_Master_Receive(&hi2c1, PAJ7620_I2C_ADDR, data, length, 100) != HAL_OK)
  42. {
  43. return 0;
  44. }
  45. return 1;
  46. }
  47. /**************************************************************************************************
  48. * 函数功能: static void writeReg(uint8_t addr, uint8_t value)
  49. * 输入参数: addr value
  50. * 返 回 值: 无
  51. * 说 明: 通过 IIC 向模块的指定寄存器写入数据
  52. *
  53. ***************************************************************************************************/
  54. static void writeReg(uint8_t addr, uint8_t value)
  55. {
  56. unsigned char dta[2] = {0};
  57. dta[0] = addr;
  58. dta[1] = value;
  59. PAJ7620_send_byteS(dta, 2);
  60. }
  61. /**************************************************************************************************
  62. * 函数功能: static unsigned char readRegs(uint8_t addr, uint8_t *values, int size)
  63. * 输入参数: addr values size
  64. * 返 回 值: 无
  65. * 说 明: 通过 IIC 向模块的读取 指定寄存器及其该寄存器的之后的数据长度
  66. *
  67. ***************************************************************************************************/
  68. static unsigned char readRegs(uint8_t addr, uint8_t *values, int size)
  69. {
  70. if (PAJ7620_send_byte(addr) != 1)
  71. return 0;
  72. if (PAJ7620_read_byteS(values, size) != 1)
  73. return 0;
  74. return 1;
  75. }
  76. /**************************************************************************************************
  77. * 函数功能: static unsigned char readReg(uint8_t addr)
  78. * 输入参数: addr
  79. * 返 回 值: 无
  80. * 说 明: 通过 IIC 向模块的读取 指定寄存器的数据
  81. *
  82. ***************************************************************************************************/
  83. static unsigned char readReg(uint8_t addr)
  84. {
  85. uint8_t values;
  86. readRegs(addr, &values, 1);
  87. return values;
  88. }
  89. /**************************************************************************************************
  90. * 函数功能: void paj7620u2_selectBank(bank_e bank)
  91. * 输入参数: bank
  92. * 返 回 值: 无
  93. * 说 明: 通过 IIC 向模块的读取 指定寄存器的数据
  94. *
  95. ***************************************************************************************************/
  96. void paj7620u2_selectBank(bank_e bank)
  97. {
  98. switch (bank)
  99. {
  100. case BANK0:
  101. writeReg(PAJ_REGITER_BANK_SEL, PAJ_BANK0);
  102. break; // BANK0
  103. case BANK1:
  104. writeReg(PAJ_REGITER_BANK_SEL, PAJ_BANK1);
  105. break; // BANK1
  106. }
  107. }
  108. void GS_WakeUp()
  109. {
  110. PAJ7620_send_byte(0);
  111. }
  112. /**************************************************************************************************
  113. * 函数功能: unsigned char paj7620u2_wakeup()
  114. * 输入参数: bank
  115. * 返 回 值: 无
  116. * 说 明: 唤醒手势模块
  117. *
  118. ***************************************************************************************************/
  119. unsigned char paj7620u2_wakeup()
  120. {
  121. unsigned char data1 = 0x0a;
  122. unsigned char data2 = 0x0a;
  123. GS_WakeUp(); // wake PAJ7620U2
  124. HAL_Delay(5); // wake time >400us
  125. GS_WakeUp(); // wake PAJ7620U2
  126. HAL_Delay(5); // wake time>400us
  127. paj7620u2_selectBank(BANK0); //进入BANK0
  128. /* check ID */
  129. data1 = readReg(0x00); //读取id
  130. data2 = readReg(0x01); //读取id
  131. if ((data2 != 0x76) || (data1 != 0x20))
  132. return 0;
  133. return 1;
  134. }
  135. /**************************************************************************************************
  136. * 函数功能: unsigned char PAJ7620u2_init(void)
  137. * 输入参数:
  138. * 返 回 值: 无
  139. * 说 明: 模块初始化
  140. *
  141. ***************************************************************************************************/
  142. unsigned char PAJ7620u2_init(void)
  143. {
  144. unsigned char status;
  145. HAL_Delay(10);
  146. status = paj7620u2_wakeup(); //唤醒PAJ7620U2
  147. if (!status)
  148. return 0;
  149. paj7620u2_selectBank(BANK0); // enter BANK0
  150. HAL_Delay(50);
  151. /* Load the registers data */
  152. for (uint8_t i = 0; i < INIT_REG_ARRAY_SIZE; i++)
  153. writeReg(initRegisterArray[i][0], initRegisterArray[i][1]); // init PAJ7620U2
  154. paj7620u2_selectBank(BANK0); // enter BANK0
  155. return 1;
  156. }
  157. /**************************************************************************************************
  158. * 函数功能: void Gesture_Init(void)
  159. * 输入参数:
  160. * 返 回 值: 无
  161. * 说 明: 模块初始化
  162. *
  163. ***************************************************************************************************/
  164. void Gesture_Init(void)
  165. {
  166. unsigned char i;
  167. paj7620u2_selectBank(BANK0); //
  168. for (i = 0; i < GESTURE_SIZE; i++)
  169. {
  170. writeReg(gesture_arry[i][0], gesture_arry[i][1]);
  171. }
  172. paj7620u2_selectBank(BANK0); //
  173. memset(&gesture, 0, sizeof(GestureData));
  174. }
  175. /**************************************************************************************************
  176. * 函数功能: void Gesture_Init(void)
  177. * 输入参数:
  178. * 返 回 值: 无
  179. * 说 明: 模块初始化
  180. *
  181. ***************************************************************************************************/
  182. void PAJ7620_Init(void)
  183. {
  184. while (!PAJ7620u2_init()) // PAJ7620U2初始化
  185. {
  186. printf("PAJ7620U2_B Error!!!\r\n");
  187. HAL_Delay(500);
  188. }
  189. HAL_Delay(1000);
  190. printf("PAJ7620U2 OK\r\n"); //
  191. }
  192. unsigned char PAJ7620_Read_nByte(unsigned char addr, unsigned short len, unsigned char *buf)
  193. {
  194. return readRegs(addr, &buf[0], len);
  195. }
  196. /**************************************************************************************************
  197. * 函数功能: unsigned char GetCurrentGesture(void)
  198. * 输入参数:
  199. * 返 回 值: 无
  200. * 说 明: 读取模块的手势地址
  201. *
  202. ***************************************************************************************************/
  203. unsigned char GetCurrentGesture(void)
  204. {
  205. uint8_t Data[2]={0,0};
  206. uint16_t Gesture_Data;
  207. uint8_t state ;
  208. uint8_t i ;
  209. // Gesture_Init();
  210. // 此处判断读取来当前手势不为0时,进行处理
  211. state = PAJ7620_Read_nByte(PAJ_GET_INT_FLAG1, 2, &gesture.data[0]); //
  212. if(state != 0)
  213. {
  214. Gesture_Data = (gesture.data[1]<<8) | gesture.data[0];
  215. switch(Gesture_Data)
  216. {
  217. case PAJ_UP: printf("Up\r\n"); break;
  218. case PAJ_DOWN: printf("Down\r\n"); break;
  219. case PAJ_LEFT: printf("Left\r\n"); break;
  220. case PAJ_RIGHT: printf("Right\r\n"); break;
  221. case PAJ_FORWARD: printf("Forward\r\n"); break;
  222. case PAJ_BACKWARD: printf("Backward\r\n"); break;
  223. case PAJ_CLOCKWISE: printf("Clockwise\r\n"); break;
  224. case PAJ_COUNT_CLOCKWISE: printf("AntiClockwise\r\n");break;
  225. case PAJ_WAVE: printf("Wave\r\n"); break;
  226. default: break;
  227. }
  228. Gesture_Data = 0;
  229. }
  230. return 0;
  231. }

在主程序中,首先初始化模块信息,在主程序中,不停的调用模块当前状态就可以,如下所示:

复制

  1. /* USER CODE BEGIN 2 */
  2. printf("autor by congconggege\r\n");
  3. HAL_Delay(1000);
  4. printf("PAJ7620U2 Gesture Sensor Test Program ...\r\n");
  5. PAJ7620_Init();
  6. printf("PAJ7620U2 Gesture Sensor OK \r\n");
  7. // CorMark_main();
  8. /* USER CODE END 2 */
  9. /* Infinite loop */
  10. /* USER CODE BEGIN WHILE */
  11. while (1)
  12. {
  13. /* USER CODE END WHILE */
  14. /* USER CODE BEGIN 3 */
  15. HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_12);
  16. HAL_Delay(500);
  17. GetCurrentGesture();//
  18. }

五:实物测试图片和PC截图如下所示:



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

---------------------
作者:聪聪哥哥
链接:https://bbs.21ic.com/icview-3435158-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/4 11:03:10

GEO优化崛起:超三成企业布局生成式AI内容策略

生成式人工智能技术迅速普及&#xff0c;一种新的优化概念就是GEO优化&#xff0c;渐渐进入人们视野。2025年有一项行业调查&#xff0c;显示全球已经有超过37%的企业开始关注或者尝试实施GEO优化策略&#xff0c;这个数字和2024年初的12%相比&#xff0c;增长了超过三倍。 生…

作者头像 李华
网站建设 2026/2/4 10:59:13

主流消息队列(MQ)的核心架构、底层原理

一、主流 MQ 架构与核心原理详解1. RabbitMQ&#xff08;1&#xff09;核心架构&#xff08;AMQP 协议 交换机路由&#xff09;基于 Erlang 语言开发&#xff0c;遵循 AMQP&#xff08;高级消息队列协议&#xff09;&#xff0c;核心组件分工明确&#xff1a;组件核心作用Brok…

作者头像 李华
网站建设 2026/2/4 10:53:53

嵌入式之C/C++(四)预处理

嵌入式开发中&#xff0c;C/C 预处理&#xff08;Preprocessor&#xff09; 是非常核心且经常被低估的部分&#xff0c;尤其在资源受限的 MCU 项目中&#xff0c;它直接影响代码体积、可维护性、可移植性、调试难度和最终生成的 .hex / .bin 大小。 下面从嵌入式视角给你一个系…

作者头像 李华
网站建设 2026/2/4 10:53:46

SpringBoot静态资源管理:从默认配置到自定义与WebJars

Spring Boot 静态资源管理详解&#xff08;2026 年视角&#xff0c;基于 Spring Boot 3.x&#xff09; Spring Boot 对静态资源&#xff08;CSS、JS、图片、字体、HTML 等&#xff09;的处理非常友好&#xff0c;默认配置已经覆盖了绝大多数场景&#xff0c;但自定义需求也很常…

作者头像 李华
网站建设 2026/2/4 10:53:37

C语言初阶——手把手教零基础/新手入门(万字心得笔记)

C语言初阶——手把手教零基础/新手入门&#xff08;2025-2026版&#xff09; 这是一篇给完全零基础或者刚接触编程不久的人准备的超详细入门笔记。 目标不是让你“看完就懂”&#xff0c;而是让你能自己敲出代码、看到结果、逐渐建立编程直觉。 预计阅读动手时间&#xff1a;…

作者头像 李华
网站建设 2026/2/4 10:52:23

工业显示屏:发展历程与组成结构

工业显示屏的发展历程与组成结构 工业显示屏是工业自动化、人机交互的关键部件,其发展与工业需求和技术进步紧密相连。 1.工业显示屏的发展历程 工业显示屏的发展大致经历了四个时代,其核心驱动力是显示技术和工业应用需求的演进。 1.1. 早期阶段:单色CRT与LED指示时代(…

作者头像 李华