第一讲:课程导学与环境搭建
各位同学,大家好。我是你们这门课的老司机。说实话,每次开新课前,我最怕的就是环境搭建这一趴。为啥?因为太多人卡在这一步,后面全白搭。今天咱们就把这事儿捋清楚。
嵌入式Linux摄像头开发,说白了就是让一块开发板能接上摄像头,把图像数据抓出来,再拿去处理或显示。听起来简单,但坑不少。我当年第一次调摄像头驱动,折腾了整整三天,最后发现是电源没给够——嗯,这种糗事后面慢慢跟你们聊。
1.1 开发板选型:别盲目跟风
选开发板这事儿,我个人的建议是:看需求,别只看参数。
市面上常见的板子,我列个表给你们参考:
| 开发板 | 处理器 | 摄像头接口 | 适合场景 |
|---|---|---|---|
| 树莓派4B | BCM2711 | CSI-2 | 入门学习、原型验证 |
| i.MX6ULL | Cortex-A7 | 并行DVP | 工业应用、低功耗 |
| RK3399 | Cortex-A72+A53 | MIPI CSI | AI视觉、高清视频 |
| 全志V3s | Cortex-A7 | DVP/MIPI | 低成本方案 |
我个人习惯用树莓派做教学演示,因为社区资源多,遇到问题好查。但如果你要做产品,i.MX6ULL或RK3399更靠谱。我在项目中遇到过用树莓派做产品,结果供货不稳定,差点翻车。
1.2 虚拟机与交叉编译链安装
好,板子选好了,接下来是开发环境。你想想看,在PC上写代码,编译完要跑到ARM板子上跑,这就得用交叉编译链。
我推荐用Ubuntu 20.04 LTS作为宿主机系统。为啥?因为大部分芯片厂商的SDK都是基于这个版本测试的。你非要用最新的Ubuntu 24.04,也行,但可能会遇到一些库版本不兼容的问题——我踩过这个坑。
安装步骤(以树莓派为例)
- 安装虚拟机:VMware Workstation或VirtualBox都行。我个人偏爱VMware,稳定。
- 安装Ubuntu:下载镜像,一路下一步。记得给虚拟机分配至少4GB内存,40GB硬盘。
- 安装交叉编译链:
# 下载树莓派官方交叉编译工具
git clone https://github.com/raspberrypi/tools.git
# 设置环境变量
export PATH=$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
# 验证安装
arm-linux-gnueabihf-gcc --version
这里要注意:交叉编译链的版本一定要和板子上的系统匹配。我曾经用了一个太新的gcc版本,编译出来的程序在板子上跑不起来,报了一堆段错误。后来发现是glibc版本不兼容。
1.3 V4L2框架初探
V4L2,全称Video for Linux 2。说白了,它就是Linux内核里给视频设备提供的一套标准接口。你写应用程序时,不用管底层是USB摄像头还是CSI摄像头,统一用open、ioctl、mmap这些系统调用就行。
我刚开始学V4L2时,觉得它好复杂。后来发现,其实核心就几个步骤:
- 打开设备:open("/dev/video0")
- 查询能力:ioctl(VIDIOC_QUERYCAP)
- 设置格式:ioctl(VIDIOC_S_FMT)
- 申请缓冲区:ioctl(VIDIOC_REQBUFS)
- 开始采集:ioctl(VIDIOC_STREAMON)
- 读取数据:ioctl(VIDIOC_DQBUF) + mmap
嗯,是不是感觉有点像流水线?没错,V4L2就是这么设计的。
核心概念:V4L2把摄像头抽象成一个文件。你读写这个文件,就是在和摄像头交互。这种设计思想在Linux里随处可见——一切皆文件。
一个最简单的V4L2示例
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
int main() {
int fd = open("/dev/video0", O_RDWR);
if (fd < 0) {
perror("open");
return -1;
}
struct v4l2_capability cap;
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
perror("VIDIOC_QUERYCAP");
close(fd);
return -1;
}
printf("驱动: %s\n", cap.driver);
printf("设备: %s\n", cap.card);
printf("总线: %s\n", cap.bus_info);
close(fd);
return 0;
}
这段代码很简单,就是打开摄像头设备,查询它的能力,然后打印出来。你编译运行后,应该能看到类似这样的输出:
驱动: uvcvideo
设备: USB Camera
总线: usb-0000:00:14.0-1
如果报错"Permission denied",记得加sudo。或者把你的用户加到video组里:
sudo usermod -a -G video $USER
然后重新登录一下。
v4l2-ctl --list-devices
v4l2-ctl -d /dev/video0 --all
这个工具在v4l-utils包里,sudo apt install v4l-utils就能装。
1.4 本章小结
好,咱们第一讲就到这儿。你想想看,今天咱们干了啥?
- 选了开发板——别盲目,看需求
- 搭了环境——虚拟机+交叉编译链,版本要匹配
- 初探了V4L2——其实就是open、ioctl、mmap那套
下一讲,咱们要深入V4L2的核心——缓冲区管理。到时候我会手把手教你写一个完整的摄像头采集程序。嗯,那个程序我当年写了五版才跑通,你们可以少走很多弯路。
课后作业:在你的板子上运行上面的示例代码,把摄像头信息打印出来。如果遇到问题,先自己查查,实在搞不定,咱们下节课讨论。
公众号:蓝海资料掘金营,微信deep3321