• Home
Name Date Size #Lines LOC

..--

include/12-May-2024-12723

src/12-May-2024-796511

BUILD.gnD12-May-2024862 2723

README_zh.mdD12-May-202410.9 KiB357282

e53_gesture_sensor_example.cD12-May-20243.1 KiB9973

README_zh.md

1# 小凌派-RK2206开发板E53模块开发——智能手势
2
3本示例将演示如何在小凌派-RK2206开发板上实现智能手势的应用案例。
4
5![小凌派-RK2206开发板](../../docs/figures/lockzhiner-rk2206.jpg)
6
7## 硬件资源
8
9硬件资源图如下所示:
10![智能手势模块硬件资源](/vendor/lockzhiner/lingpi/docs/figures/e53_sg01/e53_sg01_resource_map.jpg)
11
12EEPROM 24C02的设备地址为:0x1010001* ;
13手势传感器 PAJ7620U2 的设备地址为:0x0111001*
14
15## 硬件接口说明
16
17引脚名称开发者可在硬件资源图中查看,也可在人体感应模块背面查看。
18
19| 引脚名称  | 功能描述                        |
20| :-------- | :------------------------------ |
21| LED_UP    | 向上,LED灯控制线,低电平有效   |
22| LED_DOWN  | 向下,LED灯控制线,低电平有效   |
23| LED_LEFT  | 向左,LED灯控制线,低电平有效   |
24| LED_RIGHT | 向右,LED灯控制线,低电平有效   |
25| INT_N     | 中断信号,低电平有效            |
26| I2C_SCL   | I2C时钟信号线                   |
27| I2C-SDA   | I2C数据信号线                   |
28| LED_CW    | 顺时针,LED灯控制线,低电平有效 |
29| LED_CCW   | 逆时针,LED灯控制线,低电平有效 |
30| LED_WAVE  | 摆动,LED灯控制线,低电平有效   |
31| GND       | 电源地引脚                      |
32| 3V3       | 3.3V电源输入引脚                |
33| GND       | 电源地引脚                      |
34| 5V        | 5V电源输入引脚                  |
35
36## 硬件设计
37
38硬件电路如下图所示:
39![智能手势模块硬件电路图](/vendor/lockzhiner/lingpi/docs/figures/e53_sg01/lz_e53_sg01_sch.jpg)
40
41模块整体硬件电路如上图所示,电路中包含了E53接口连接器,EEPROM存储器、手势识别传感器电路,灯光指示电路。电路比较简单,本文不再过多说明。
42
43### 硬件连接
44
45小凌派开发板与模块均带有防呆设计,故很容易区分安装方向,直接将模块插入到开发板的E53母座接口上即可,安装图如下所示:
46![智能手势模块硬件连接图](/vendor/lockzhiner/lingpi/docs/figures/e53_sg01/e53_sg01_connection_diagram.png)
47
48## 程序设计
49
50### API分析
51
52#### GPIO接口
53
54[GPIO接口文档](/device/rockchip/hardware/docs/GPIO.md)
55
56#### I2C接口
57
58[I2C接口文档](/device/rockchip/hardware/docs/I2C.md)
59
60#### LiteOS任务管理
61
62[LiteOS任务管理接口文档](/vendor/lockzhiner/lingpi/samples/a1_kernel_task/task.md)
63
64### 主要代码分析
65
66#### 初始化代码分析
67
68**初始化GPIO**
69
70本模块使用以下引脚作为LED灯。具体如下所示:
71
72| 引脚      | 功能         |
73| :-------- | :----------- |
74| GPIO0_PB1 | LED_UP       |
75| GPIO0_PB0 | LED_DOWN     |
76| GPIO0_PA2 | LED_LEFT     |
77| GPIO0_PC4 | LED_RIGHT    |
78| GPIO0_PB4 | LED_FORWARD  |
79| GPIO0_PB7 | LED_BACKWARD |
80| GPIO0_PB6 | LED_CW       |
81| GPIO0_PB5 | LED_CCW      |
82| GPIO0_PB2 | LED_WAVE     |
83
84初始化引脚为GPIO。首先通过 `LzGpioInit()`初始化GPIO引脚,其次通过 `LzGpioSetDir()`设置GPIO为输出模式,最后通过 `LzGpioSetVal()`设置输出高电平/低电平。
85
86```c
87/***************************************************************
88* 函数名称: gesture_sensor_led_init
89* 说    明: 初始化LED的GPIO引脚
90* 参    数: 无
91* 返 回 值: 无
92***************************************************************/
93static void gesture_sensor_led_init()
94{
95    PinctrlSet(GPIO_LED_UP, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
96    LzGpioInit(GPIO_LED_UP);
97    LzGpioSetDir(GPIO_LED_UP, LZGPIO_DIR_OUT);
98    gesture_sensor_led_up(0);
99
100    PinctrlSet(GPIO_LED_DOWN, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
101    LzGpioInit(GPIO_LED_DOWN);
102    LzGpioSetDir(GPIO_LED_DOWN, LZGPIO_DIR_OUT);
103    gesture_sensor_led_down(0);
104
105    PinctrlSet(GPIO_LED_LEFT, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
106    LzGpioInit(GPIO_LED_LEFT);
107    LzGpioSetDir(GPIO_LED_LEFT, LZGPIO_DIR_OUT);
108    gesture_sensor_led_left(0);
109
110    PinctrlSet(GPIO_LED_RIGHT, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
111    LzGpioInit(GPIO_LED_RIGHT);
112    LzGpioSetDir(GPIO_LED_RIGHT, LZGPIO_DIR_OUT);
113    gesture_sensor_led_right(0);
114
115    PinctrlSet(GPIO_LED_FORWARD, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
116    LzGpioInit(GPIO_LED_FORWARD);
117    LzGpioSetDir(GPIO_LED_FORWARD, LZGPIO_DIR_OUT);
118    gesture_sensor_led_forward(0);
119
120    PinctrlSet(GPIO_LED_BACKWARD, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
121    LzGpioInit(GPIO_LED_BACKWARD);
122    LzGpioSetDir(GPIO_LED_BACKWARD, LZGPIO_DIR_OUT);
123    gesture_sensor_led_backward(0);
124
125    PinctrlSet(GPIO_LED_CW, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
126    LzGpioInit(GPIO_LED_CW);
127    LzGpioSetDir(GPIO_LED_CW, LZGPIO_DIR_OUT);
128    gesture_sensor_led_cw(0);
129
130    PinctrlSet(GPIO_LED_CCW, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
131    LzGpioInit(GPIO_LED_CCW);
132    LzGpioSetDir(GPIO_LED_CCW, LZGPIO_DIR_OUT);
133    gesture_sensor_led_ccw(0);
134
135    PinctrlSet(GPIO_LED_WAVE, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
136    LzGpioInit(GPIO_LED_WAVE);
137    LzGpioSetDir(GPIO_LED_WAVE, LZGPIO_DIR_OUT);
138    gesture_sensor_led_wave(0);
139}
140```
141
142**初始化i2c**
143
144初始化GPIO0_PA1和GPIO0_PA0为I2C0。首先通过 `I2cIoInit()`初始化i2c通道,最后通过 `LzI2cInit()`设置i2c配置。具体代码如下所示:
145
146```c
147/***************************************************************
148* 函数名称: paj7620u2_i2c_init
149* 说    明: 初始化与PAJ7620U2通信的i2c
150* 参    数: 无
151* 返 回 值: 无
152***************************************************************/
153static void paj7620u2_i2c_init()
154{
155    if (I2cIoInit(m_i2cBus) != LZ_HARDWARE_SUCCESS)
156    {
157        printf("%s, %d: I2cIoInit failed!\n", __FILE__, __LINE__);
158        return;
159    }
160    if (LzI2cInit(E53_I2C_BUS, m_i2c_freq) != LZ_HARDWARE_SUCCESS)
161    {
162        printf("%s, %d: I2cIoInit failed!\n", __FILE__, __LINE__);
163        return;
164    }
165
166    PinctrlSet(GPIO0_PA1, MUX_FUNC3, PULL_KEEP, DRIVE_KEEP);
167    PinctrlSet(GPIO0_PA0, MUX_FUNC3, PULL_KEEP, DRIVE_KEEP);
168}
169```
170
171**配置PAJ7620U2**
172
173通过i2c通信协议,配置PAJ7620U2。具体代码如下所示:
174
175```c
176/***************************************************************
177* 函数名称: paj7620u2_init_config
178* 说    明: 配置PAJ7620U2为手势感应模式
179* 参    数: 无
180* 返 回 值: 无
181***************************************************************/
182static void paj7620u2_init_config()
183{
184    uint8_t ret = 0;
185    uint32_t size;
186
187    ret = paj7620u2_wake_up();
188    if (ret != 0)
189    {
190        printf("%s, %s, %d: paj7620u2_wake_up failed(%d)\n", __FILE__, __func__, __LINE__, ret);
191    }
192
193    /* 初始化PAJ7620U2 */
194    size = sizeof(m_Paj7620u2_InitRegisterConfig) / (sizeof(uint8_t) * 2);
195    for (uint32_t i = 0; i < size; i++)
196    {
197        paj7620u2_write_data(m_Paj7620u2_InitRegisterConfig[i][0], m_Paj7620u2_InitRegisterConfig[i][1]);
198    }
199
200    /* 设置为手势识别模式 */
201    size = sizeof(m_Paj7620u2_SetGestureModeConfig) / (sizeof(uint8_t) * 2);
202    for (uint32_t i = 0; i < size; i++)
203    {
204        paj7620u2_write_data(m_Paj7620u2_SetGestureModeConfig[i][0], m_Paj7620u2_SetGestureModeConfig[i][1]);
205    }
206
207    paj7620u2_select_bank(BANK0);
208}
209```
210
211**创建轮询任务**
212
213通过 `LOS_TaskCreate()`创建任务,每隔100msec轮询PAJ7620U2的手势寄存器。具体代码如下所示:
214
215```c
216/***************************************************************
217* 函数名称: paj7620u2_poll_task_init
218* 说    明: 初始化轮询PAJ7620U2手势的任务
219* 参    数: 无
220* 返 回 值: 无
221***************************************************************/
222static void paj7620u2_poll_task_init()
223{
224    TSK_INIT_PARAM_S task;
225    uint8_t int_flag1, int_flag2;
226    UINT32 ret;
227
228    /* 初始化先进先出缓冲区 */
229    m_fifo_intflags.offset_read = 0;
230    m_fifo_intflags.offset_write = 0;
231
232    /* 锁任务调度 */
233    LOS_TaskLock();
234
235    /* 创建中断之后的i2c读取中断标记寄存器的任务 */
236    (VOID)memset_s(&task, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
237    task.pfnTaskEntry   = (TSK_ENTRY_FUNC)paj7620u2_poll_task;
238    task.pcName         = "InterruptSemTask";
239    task.uwStackSize    = TASK_STACK_SIZE;
240    task.usTaskPrio     = 10;
241    ret = LOS_TaskCreate(&m_pollTaskId, &task);
242    if (ret != LOS_OK)
243    {
244        printf("%s, %d: LOS_TaskCreate failed(%d)\n", __func__, __LINE__, ret);
245        /* 解锁任务调度 */
246        LOS_TaskUnlock();
247        return;
248    }
249
250    /* 解锁任务调度 */
251    LOS_TaskUnlock();
252
253    /* 先清空PAJ7620U2的中断标记寄存器 */
254    paj7620u2_select_bank(BANK0);
255    paj7620u2_read_data(PAJ_REG_GET_INT_FLAG1, &int_flag1);
256    paj7620u2_read_data(PAJ_REG_GET_INT_FLAG2, &int_flag2);
257}
258```
259
260#### 查询手势感应代码分析
261
262首先,通过 `LOS_TaskCreate()`创建任务,每隔100msec轮询PAJ7620U2的手势寄存器。如果寄存器有数据,则存储到FIFO队列中。具体代码如下所示:
263
264```c
265/***************************************************************
266* 函数名称: paj7620u2_poll_task
267* 说    明: 轮询任务,每隔100msec访问PAJ7620U2的手势中断寄存器,
268*       如果有手势数据,则填写到m_fifo_intflags队列中。
269* 参    数: 无
270* 返 回 值: 无
271***************************************************************/
272static VOID paj7620u2_poll_task(VOID *args)
273{
274    uint8_t int_flag1 = 0;
275    uint8_t int_flag2 = 0;
276    uint16_t value = 0;
277
278    while (1)
279    {
280        /* 读取Paj7620U2的手势中断寄存器 */
281        paj7620u2_select_bank(BANK0);
282        paj7620u2_read_data(PAJ_REG_GET_INT_FLAG1, &int_flag1);
283        paj7620u2_read_data(PAJ_REG_GET_INT_FLAG2, &int_flag2);
284
285        value = 0;
286        if (int_flag1 != 0)
287        {
288            value |= (uint16_t)(int_flag1);
289        }
290        if (int_flag2 != 0)
291        {
292            value |= (uint16_t)(int_flag2 << 8);
293        }
294
295        if (value != 0)
296            FifoPut(&m_fifo_intflags, value);
297
298        LOS_Msleep(100);
299    }
300}
301```
302
303上层软件通过调用 `E53_GestureSensor_GetGestureState()`获知FIFO队列中的最新手势信息。具体代码如下:
304
305```c
306/***************************************************************
307 * 函数名称: gesture_sensor_get_gesture_state
308 * 说    明: 获取手势感应模块手势
309 * 参    数:
310 *      @flag:获取当前手势
311 * 返 回 值: 1为成功,0为失败
312 ***************************************************************/
313unsigned int gesture_sensor_get_gesture_state(unsigned short *flag)
314{
315    *flag = 0;
316
317    if (FifoGet(&m_fifo_intflags, flag) != 0)
318    {
319        return 1;
320    }
321    else
322    {
323        return 0;
324    }
325}
326```
327
328## 5. 编译调试
329
330### 5.1 修改 BUILD.gn 文件
331
332修改 `vendor/lockzhiner/lingpi/sample` 路径下 BUILD.gn 文件,指定 `e53_gs_example` 参与编译。
333
334```r
335"e53_gesture_sensor",
336```
337
338在主目录下输入编译命令。
339
340```shell
341hb build -f
342```
343
344### 5.2 运行结果
345
346示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,并请使用带有LCD屏幕显示如下:
347
348```c
349========== E53 Gesture Sensor Example ==========
350Get Gesture Statu: 0x1
351   Down
352========== E53 Gesture Sensor Example ==========
353Get Gesture Statu: 0x5
354   Down
355   Left
356```
357