第 18 篇 综合项目实战:基于 RK3568 的安卓智能门禁系统,全栈开发

第 18 篇 综合项目实战:基于 RK3568 的安卓智能门禁系统,全栈开发 目录一、项目需求与整体方案设计1. 核心功能需求2. 硬件方案选型基于 RK35683. 软件整体架构二、第一步全外设驱动适配与设备树配置1. 完整设备树配置2. 驱动编译与验证三、第二步HAL 层封装统一硬件控制接口1. HAL 层目录与文件结构2. 头文件door_access_hal.h3. 接口实现door_access_hal.c4. 编译脚本Android.bp5. 编译 HAL 层模块四、第三步JNI 封装与安卓门禁 App 开发1. JNI 接口封装2. 安卓门禁 App 开发五、项目优化与落地注意事项结尾说两句大家好我是黒漂技术佬。前面 17 篇内容我们从安卓驱动基础架构、设备树到 GPIO、中断、I2C、SPI、显示、音频、摄像头等全系列外设驱动再到全套调试方法已经把 RK 安卓驱动开发的核心技能全部讲透了。很多兄弟后台说“佬单个外设的驱动我都会了但是怎么把这些东西整合到一个完整的项目里有没有一个全流程的实战项目能把所有知识点串起来”安排今天这篇我们就做一个工业级的落地项目 ——基于 RK3568 的安卓智能门禁系统把前面所有学到的知识点全部整合起来从需求分析、硬件方案选型、全外设驱动适配、HAL 层封装、JNI 接口开发到最终的安卓门禁 App 全栈开发一步不落小白跟着走就能做出一个可直接落地的智能门禁产品。一、项目需求与整体方案设计1. 核心功能需求我们做的智能门禁系统要实现工业级场景的完整功能覆盖我们前面所有的知识点人脸识别开锁通过摄像头采集人脸本地 NPU 做人脸识别匹配成功后驱动继电器开锁密码 / 刷卡开锁支持电容按键输入密码、IC 卡刷卡开锁适配门禁常用场景音视频对讲支持门口机和室内机的音视频对讲用到摄像头、音频编解码、屏幕显示门禁状态显示7 寸 MIPI 屏实时显示摄像头画面、开锁状态、时间、提示信息开锁执行机构继电器控制电磁锁PWM 驱动蜂鸣器做按键 / 开锁提示音事件存储与上报所有开锁、报警事件本地存储支持网络上报到后台。2. 硬件方案选型基于 RK3568表格功能模块硬件选型对应前面的知识点核心主控RK3568 核心板 底板全系列驱动开发基础显示模块7 寸 MIPI LCD 屏800*1280第 14 篇 MIPI 显示驱动、DRM 框架摄像头GC2053 1080P MIPI 摄像头第 16 篇 摄像头驱动、V4L2 子系统音频模块ES8388 Codec 咪头 喇叭第 15 篇 音频驱动、ALSA 架构开锁执行5V 继电器 电磁锁第 8 篇 GPIO 输出驱动按键输入6 路电容触摸按键第 13 篇 input 子系统、按键中断驱动提示音无源蜂鸣器第 10 篇 PWM 驱动刷卡模块MFRC522 RFID 模块SPI 接口第 12 篇 SPI 驱动开发存储8GB EMMC系统与事件存储网络双网口 WiFi/BT 模块系统联网与事件上报3. 软件整体架构我们严格遵循安卓系统的标准分层架构和前面的单外设驱动开发完全一致整体分为 5 层从上到下依次是应用层安卓门禁 App实现 UI 交互、人脸识别逻辑、事件管理、音视频对讲Framework 层安卓系统 API 自定义 JNI 接口连接 Java 和 Native 层HAL 层硬件抽象层封装所有外设的控制接口给 JNI 层提供标准 C/C 接口内核驱动层基于 Linux 内核实现所有外设的标准驱动给 HAL 层提供设备文件操作接口硬件层RK3568 核心板 所有外设硬件。二、第一步全外设驱动适配与设备树配置这个项目的核心基础就是所有外设的驱动适配我们基于前面的单外设驱动知识完成整个项目的设备树配置和驱动适配所有外设的驱动内核都已经自带我们只需要修改设备树不用写一行驱动代码就能完成所有外设的适配。1. 完整设备树配置打开你的 RK3568 板级.dts 文件添加下面的完整设备树配置所有模块都加了详细注释直接对应我们的硬件方案dts/ { // 1. 门禁按键input驱动6路电容按键 gpio_keys: gpio-keys { compatible gpio-keys; status okay; autorepeat; pinctrl-names default; // 数字按键0-9、确认、取消对应标准键码 key_0 { label key-0; gpios gpio1 RK_PA0 GPIO_ACTIVE_LOW; linux,code KEY_0; debounce-interval 20; }; key_1 { label key-1; gpios gpio1 RK_PA1 GPIO_ACTIVE_LOW; linux,code KEY_1; debounce-interval 20; }; key_2 { label key-2; gpios gpio1 RK_PA2 GPIO_ACTIVE_LOW; linux,code KEY_2; debounce-interval 20; }; key_3 { label key-3; gpios gpio1 RK_PA3 GPIO_ACTIVE_LOW; linux,code KEY_3; debounce-interval 20; }; key_enter { label key-enter; gpios gpio1 RK_PA4 GPIO_ACTIVE_LOW; linux,code KEY_ENTER; debounce-interval 20; wakeup-source; }; key_cancel { label key-cancel; gpios gpio1 RK_PA5 GPIO_ACTIVE_LOW; linux,code KEY_ESC; debounce-interval 20; }; }; // 2. 继电器开锁控制 door_lock: door-lock { compatible gpio-leds; status okay; lock { label door-lock; gpios gpio1 RK_PB0 GPIO_ACTIVE_HIGH; default-state off; // 默认断开锁关闭 }; }; // 3. 蜂鸣器PWM控制 beeper: beeper { compatible pwm-beeper; status okay; pwms pwm0 0 500000 0; // 2kHz频率适合蜂鸣器 amp-supply vcc3v3_sys; beeper-hz 2000; }; }; // 4. MIPI 7寸屏显示驱动 dsi0 { status okay; rockchip,lane-count 2; rockchip,max-bandwidth 800; rockchip,format MIPI_DSI_FMT_RGB888; rockchip,mode MIPI_DSI_MODE_VIDEO; rockchip,video-mode MIPI_DSI_VIDEO_MODE_BURST; panel0 { compatible simple-mipi-dsi-panel; reg 0; status okay; // 7寸屏800*1280时序参数根据屏幕规格书修改 display-timings { native-mode timing0; timing0: timing0 { clock-frequency 78000000; hactive 800; hfront-porch 20; hback-porch 20; hsync-len 10; vactive 1280; vfront-porch 10; vback-porch 10; vsync-len 2; hsync-active 0; vsync-active 0; de-active 1; pixelclk-active 0; }; }; power-supply vcc3v3_lcd0; reset-gpios gpio4 RK_PA0 GPIO_ACTIVE_LOW; reset-delay-ms 10; prepare-delay-ms 10; init-delay-ms 120; // 屏幕初始化命令根据屏幕规格书添加 dsi,init-commands [ 15 00 02 78 00 05 00 01 29 00 ]; }; }; route_dsi0 { status okay; connect vopb_out_dsi0; }; vopb { status okay; }; vopb_out_dsi0 { status okay; }; backlight { status okay; pwms pwm1 0 50000 0; brightness-levels 0 20 40 60 80 100 120 140 160 180 200 220 240 255; default-brightness 200; }; // 5. GC2053摄像头驱动 i2c2 { status okay; clock-frequency 400000; gc2053: gc205337 { compatible galaxycore,gc2053; reg 0x37; status okay; clocks cru CLK_CAM_OUT0; clock-names xvclk; assigned-clocks cru CLK_CAM_OUT0; assigned-clock-rates 24000000; pwdn-gpios gpio4 RK_PA1 GPIO_ACTIVE_HIGH; reset-gpios gpio4 RK_PA2 GPIO_ACTIVE_LOW; rotation 0; orientation 0; >2. 驱动编译与验证设备树修改完成后编译内核和设备树bash运行./build.sh -CKu烧录 boot.img 到开发板重启后按下面的步骤验证所有外设驱动是否正常bash运行# 1. 验证按键input设备 cat /proc/bus/input/devices | grep gpio-keys getevent # 按下按键能看到对应的事件上报 # 2. 验证MIPI屏 # 开机屏幕正常点亮显示安卓桌面说明显示驱动正常 # 3. 验证摄像头 v4l2-ctl --list-devices # 能看到GC2053摄像头设备 # 4. 验证音频 aplay -l # 能看到声卡设备tinyplay播放测试音频正常 # 5. 验证继电器 echo 1 /sys/class/leds/door-lock/brightness # 继电器吸合锁打开 echo 0 /sys/class/leds/door-lock/brightness # 继电器断开锁关闭 # 6. 验证蜂鸣器 echo 2000 /sys/class/input/eventX/device/beeper/hz # 蜂鸣器响所有外设验证通过后我们的驱动层就全部完成了接下来进入 HAL 层的封装。三、第二步HAL 层封装统一硬件控制接口我们把所有外设的控制逻辑封装成标准的 HAL 层动态库给上层 JNI 提供统一的 C/C 接口避免上层直接操作设备文件符合安卓系统的架构规范。1. HAL 层目录与文件结构在 SDK 的hardware/rockchip/目录下创建door_access_hal目录创建以下文件plaintextdoor_access_hal/ ├── include │ └── door_access_hal.h // 头文件对外接口声明 ├── door_access_hal.c // 接口实现 └── Android.bp // 编译脚本2. 头文件door_access_hal.h定义所有对外的控制接口覆盖门禁系统的所有硬件操作c运行#ifndef DOOR_ACCESS_HAL_H #define DOOR_ACCESS_HAL_H #ifdef __cplusplus extern C { #endif // 门锁控制 // 开锁1开锁0关锁 int door_lock_set(int enable); // 获取门锁状态 int door_lock_get_status(void); // 蜂鸣器控制 // 蜂鸣器响duration_ms持续时间0一直响 int beeper_play(int duration_ms); // 停止蜂鸣器 int beeper_stop(void); // 按键事件读取 // 初始化按键事件监听 int key_init(void); // 读取按键事件阻塞等待 int key_read_event(int *key_code, int *state); // 释放按键资源 int key_release(void); // RFID读卡 // 初始化RFID模块 int rfid_init(void); // 读取IC卡卡号阻塞等待 int rfid_read_card(unsigned char *card_id, int *id_len); // 释放RFID资源 int rfid_release(void); // 音频播放 // 播放提示音比如“请刷卡”“密码错误” int audio_play_tip(const char *audio_file); // 开始录音 int audio_start_record(const char *record_file); // 停止录音 int audio_stop_record(void); // 系统初始化与释放 // 所有硬件初始化 int door_access_hal_init(void); // 所有资源释放 int door_access_hal_release(void); #ifdef __cplusplus } #endif #endif // DOOR_ACCESS_HAL_H3. 接口实现door_access_hal.c基于我们前面的驱动设备文件实现所有接口核心代码片段如下c运行#include stdio.h #include stdlib.h #include fcntl.h #include unistd.h #include sys/ioctl.h #include pthread.h #include linux/input.h #include door_access_hal.h // 全局设备文件描述符 static int lock_fd -1; static int key_fd -1; static int beeper_fd -1; // 门锁控制实现 int door_lock_set(int enable) { if (lock_fd 0) { lock_fd open(/sys/class/leds/door-lock/brightness, O_RDWR); if (lock_fd 0) { printf(【HAL】打开门锁设备失败\n); return -1; } } if (enable) { write(lock_fd, 1, 1); printf(【HAL】门锁已打开\n); } else { write(lock_fd, 0, 1); printf(【HAL】门锁已关闭\n); } return 0; } int door_lock_get_status(void) { char buf[2] {0}; if (lock_fd 0) return -1; lseek(lock_fd, 0, SEEK_SET); read(lock_fd, buf, 1); return atoi(buf); } // 蜂鸣器控制实现 int beeper_play(int duration_ms) { // 蜂鸣器控制实现通过sysfs节点控制PWM system(echo 2000 /sys/class/leds/beeper/brightness); if (duration_ms 0) { usleep(duration_ms * 1000); beeper_stop(); } return 0; } int beeper_stop(void) { system(echo 0 /sys/class/leds/beeper/brightness); return 0; } // 剩余的按键、RFID、音频接口实现基于前面的单外设驱动知识完成 // 音频部分基于tinyalsa库实现RFID基于SPI设备文件操作4. 编译脚本Android.bpjsoncc_library_shared { name: libdooraccess, srcs: [door_access_hal.c], local_include_dirs: [include], vendor: true, shared_libs: [ libtinyalsa, libcutils, libutils, ], cflags: [ -Wall, -Werror, ], }5. 编译 HAL 层模块bash运行# 进入SDK根目录设置编译环境 source build/envsetup.sh lunch rk3568_r-userdebug # 编译HAL模块 mmm hardware/rockchip/door_access_hal编译完成后会生成libdooraccess.so动态库放到开发板的/vendor/lib64/目录下给 JNI 层调用。四、第三步JNI 封装与安卓门禁 App 开发1. JNI 接口封装在 Android Studio 项目中创建DoorAccessJni.java类声明 native 方法对应 HAL 层的接口java运行package com.heipiao.dooraccess; public class DoorAccessJni { static { System.loadLibrary(dooraccess); System.loadLibrary(door_jni); } public native int halInit(); public native int halRelease(); public native int doorLockSet(int enable); public native int beeperPlay(int durationMs); public native int readKeyEvent(int[] keyInfo); public native int readRfidCard(byte[] cardId); public native int playTipAudio(String audioFile); }然后编写对应的 JNI C 代码调用 HAL 层的接口完成 Java 和 Native 层的桥接。2. 安卓门禁 App 开发基于 JNI 接口开发完整的门禁 App核心功能包括实时预览通过 Camera2 API预览摄像头画面做人脸识别人脸识别集成 RK NPU 的人脸识别 SDK本地完成人脸匹配匹配成功自动开锁密码开锁监听 input 按键事件接收用户输入的密码验证成功开锁刷卡开锁监听 RFID 读卡事件读取卡号验证白名单后开锁事件记录所有开锁、报警事件本地存储到 SQLite 数据库支持查询和导出音视频对讲基于 WebRTC实现门口机和室内机的音视频对讲。App 的核心开锁逻辑代码片段java运行// 人脸识别匹配成功回调 Override public void onFaceMatchSuccess(float similarity) { // 开锁 doorAccessJni.doorLockSet(1); // 播放提示音 doorAccessJni.beeperPlay(500); doorAccessJni.playTipAudio(/sdcard/door_open.mp3); // 记录事件 EventManager.getInstance().addEvent(人脸识别开锁, 匹配度 similarity); // 3秒后关锁 new Handler(Looper.getMainLooper()).postDelayed(() - { doorAccessJni.doorLockSet(0); }, 3000); } // 按键事件监听 new Thread(() - { int[] keyInfo new int[2]; while (isRunning) { int ret doorAccessJni.readKeyEvent(keyInfo); if (ret 0) { int keyCode keyInfo[0]; int state keyInfo[1]; // 处理按键输入密码验证逻辑 runOnUiThread(() - handleKeyInput(keyCode, state)); } } }).start();五、项目优化与落地注意事项系统裁剪与开机优化裁剪安卓系统不必要的服务优化开机速度实现开机自启门禁 App工业级产品要求开机后 10 秒内进入工作状态稳定性优化添加看门狗功能系统异常时自动重启所有硬件操作添加异常处理避免 App 崩溃功耗优化无人操作时关闭屏幕背光降低 CPU 频率进入低功耗模式有人按按键时唤醒安全加固人脸数据、密码、卡号加密存储安卓系统 root 权限关闭SELinux 开启防止恶意破解网络冗余支持有线网和 WiFi 双网冗余断网时本地正常工作联网后自动上报事件。结尾说两句这篇文章我们把前面 17 篇的所有知识点全部整合到了一个完整的智能门禁项目里从硬件方案、驱动适配、HAL 层封装到安卓 App 开发完成了全栈的落地实战。到这里你已经具备了独立完成 RK 平台安卓工业级项目的全流程开发能力再也不是只会写单外设驱动的脚本小子了。下一篇我们进入进阶优化内容驱动性能优化与功耗优化实战教你怎么让你的驱动运行更快、占用资源更少、功耗更低满足工业级产品的严苛要求。我是黒漂技术佬关注我带你零基础入门 RK 安卓驱动开发不踩坑。有任何项目开发的问题评论区留言我都会一一回复。