问题描述
在边缘计算与机器视觉开发中,多路高清图像采集是常见需求。嘉楠科技 K230 芯片凭借3路 MIPI 接口优势,可轻松支持三路 AHD 传感器输入,搭配 RTOS 系统实现高效图像处理。今天就带大家从硬件适配到软件编译,一步步跑通两路 AHD demo(由于 01Studio CSI2 使用 BTB 接口,无法换成 AHD),解锁 K230 多摄像头开发技能!

什么是AHD?有什么应用场景?
AHD,即 Analog High Definition,意为模拟高清 。在视频领域,我们常把物理分辨率达到 720p 以上的格式称作高清(HD) 。AHD 基于特定协议,通过模拟同轴电缆来传输逐行扫描的高清视频 。它就像是一位 “高清使者”,将高清画质带到了模拟传输的世界。
传统模拟视频传输在清晰度上存在局限,而 AHD 技术的出现,改变了这一局面。它能够在已有的模拟传输线上实现超长距离(500 米)高清视频信号的可靠传输 。采用先进的 Y/C 信号分离和模拟滤波技术,有效减少高频区的色噪声,使图像还原性更好。对比传统模拟高清产品,AHD 的监控图像质量有了质的飞跃和提升,最高清晰度可等同于网络高清 1080p 的全高清级别 。
AHD有广泛的应用场景:安防(监控公共区域、交通、企业家庭)、车载(记录仪、倒车影像、ADAS)、工业质检,还用于医疗内窥镜、无人机航拍、智能家居联动。
一 硬件连接
AHD(模拟高清技术)通过同轴电缆传输高清视频,K230 为 MIPI 接口,我们需借助 XS9950 芯片,将 AHD 信号转为 K230 可识别的 MIPI 信号,再接入 K230 MIPI 接口。
1. 硬件关键注意事项
- 接口对应:两路 AHD 传感器必须分别接入 K230 的 CSI0、CSI1 两个 MIPI 接口,且线序不能接错(参考 K230 芯片 MIPI 引脚图与 AHD 传感器接线图);
- 电压匹配:每路 AHD 传感器的 IIC 电压需与 K230 的 IO 电压一致,否则可能烧毁芯片或导致通信失败;
- 复位与时序:确认传感器的复位(RST)、掉电(PWDn)引脚是否接入 K230,若未接入需保证满足传感器启动时序;
2. 硬件准备
K230 开发板(这里我们使用的是 01Studio 开发板)
XS9950 AHD 转 MIPI 信号板
usb 转 ttl 转接板和杜邦线

硬件连接图:

二、软件
1. 升级SDK
获取最新的 RTOS 系统 SDK,参考:
https://www.kendryte.com/k230_rtos/zh/main/userguide/how_to_build.html
进入 SDK 根目录打开 XS9950 摄像头驱动
aaa@DESKTOP-OSN5BJK:~/canmv_k230_gitee_0908$ make menuconfig

进入 MMP Configuration->Sensor Configuration,选中 Enable XS9950 ,保存退出,然后输入 make 重新编译升级新编译出来的 IMG,升级方法参考:https://mp.weixin.qq.com/s/sQiaXgHr3q3j7HbjhWxSDA
2. 连接串口

可以看到开机 log,表明系统在 CSI0 和 CSI1 检测到 xs9950 设备:
find sensor(xs9950_csi0) on csi0
find sensor(xs9950_csi1) on csi1
Can't find sensor on csi2
3. 编译运行应用程序
demo路径:
~/src/rtsmart/mpp/userapps/sample/sample_ahd_sensor
数据处理全流程(两路通用)
每路 AHD 信号的处理都遵循“采集→格式转换→缩放→旋转→显示”的 Pipeline,以第一路为例
VICAP(采集)→ nonai-2d(格式转换)→ DW(缩放)→ GDMA(旋转)→ VO(显示)
-
VICAP:接收 AHD 传感器的 YUV422 数据,转为 YUV444 存储到 DDR;
-
nonai-2d:将 YUV444 转为 YUV420(用于显示);
-
DW:将 720P(1280×720)图像缩放到 640×360,适配显示需求;
-
GDMA:将 640×360 图像旋转 90°,转为 360×640(因屏幕为 720×1280 竖屏转横屏使用);
-
VO:将处理后的图像输出到屏幕,支持2个视频图层(YUV),两路路分别用2个图层。
由于 demo 显示器为 1280x720,所以屏蔽掉 GDMA 旋转的功能,大家可以根据自己的硬件情况修改 demo。
编译
按照我们的屏幕和输入的 CSI num 修改源码,我们这里 AHD 摄像头接入 CSI0 和 CSI1,所以屏蔽掉 CSI2 初始化部分:
~/src/rtsmart/mpp/userapps/sample/sample_ahd_sensor/ahd_sensor.c :
int main(int argc, char *argv[])
{
。。。
// 根据你的显示器类型修改,注意几路码流拼接出来的宽高不能大于显示器的宽高
sample_vo_init(LT9611_MIPI_4LAN_1920X1080_30FPS);//ST7701_V1_MIPI_2LAN_480X800_30FPS
。。。
// three mcm init
ret = sample_vicap_init(VICAP_DEV_ID_0, XS9950_MIPI_CSI0_1280X720_30FPS_YUV422);
if(ret < 0)
{
printf("vicap VICAP_DEV_ID_0 init failed \n");
goto vicap_init_error;
}
ret = sample_vicap_init(VICAP_DEV_ID_1, XS9950_MIPI_CSI1_1280X720_30FPS_YUV422);
if(ret < 0)
{
printf("vicap VICAP_DEV_ID_1 init failed \n");
goto vicap_init_error;
}
/*ret = sample_vicap_init(VICAP_DEV_ID_2, XS9950_MIPI_CSI2_1280X720_30FPS_YUV422);
if(ret < 0)
{
printf("vicap VICAP_DEV_ID_2 init failed \n");
goto vicap_init_error;
}*/
sample_dw200_init();
sample_vicap_stream(VICAP_DEV_ID_0, K_TRUE);
sample_vicap_stream(VICAP_DEV_ID_1, K_TRUE);
//sample_vicap_stream(VICAP_DEV_ID_2, K_TRUE);
aaa@DESKTOP-OSN5BJK:~/canmv_k230_gitee_0908$ cd src/rtsmart/mpp/userapps/sample/sample_ahd_sensor/
aaa@DESKTOP-OSN5BJK:~/canmv_k230_gitee_0908/src/rtsmart/mpp/userapps/sample/sample_ahd_sensor$ make
[CC] /home/aaa/canmv_k230_gitee_0908/output/k230_canmv_01studio_defconfig/rtsmart/mpp/userapps/sample/sample_ahd_sensor/ahd_sensor.o
[CC] /home/aaa/canmv_k230_gitee_0908/output/k230_canmv_01studio_defconfig/rtsmart/mpp/userapps/sample/sample_ahd_sensor/../sample_vo/vo_test_case.o
[CC] /home/aaa/canmv_k230_gitee_0908/output/k230_canmv_01studio_defconfig/rtsmart/mpp/userapps/sample/sample_ahd_sensor/../sample_vo/vo_bind_test.o
[LD] /home/aaa/canmv_k230_gitee_0908/src/rtsmart/mpp//userapps/sample/elf/sample_ahd_sensor.elf
/home/aaa/k230_toolchains/riscv64-linux-musleabi_for_x86_64-pc-linux-gnu/bin/../lib/gcc/riscv64-unknown-linux-musl/12.0.1/../../../../riscv64-unknown-linux-musl/bin/ld: warning: /home/aaa/canmv_k230_gitee_0908/src/rtsmart/mpp//userapps/sample/elf/sample_ahd_sensor.elf has a LOAD segment with RWX permissions
Make sample sample_ahd_sensor done.
aaa@DESKTOP-OSN5BJK:~/canmv_k230_gitee_0908/src/rtsmart/mpp/userapps/sample/sample_ahd_sensor$ cd ../elf/
aaa@DESKTOP-OSN5BJK:~/canmv_k230_gitee_0908/src/rtsmart/mpp/userapps/sample/elf$ ls
sample_ahd_sensor.elf
- 运行demo
-
将 sample_ahd_sensor.elf 拷贝到 CanMV,这里 copy 到 /data 目录下

-
在串口运行 demo:
msh />cd /data/
sample_vicap.elf
sample_ahd_sensor.elf
msh /data>./sample_ahd_sensor.elf
[D/lt9611] vtotal 1125 vactive 1080 htotal_sys 400
first mode is 3
set output err, set default format ISP_PIX_FMT_YUV420SP
chn_cfg WORK MODE i s 3
chn_cfg.mcm_chn is 0 chn_cfg.buff_num is 10
set output err, set default format ISP_PIX_FMT_YUV420SP
chn_cfg WORK MODE i s 3
chn_cfg.mcm_chn is 1 chn_cfg.buff_num is 10
[dw] enter dev_fds[settings->vdev_id] < 0
[dw] enter ioctl(dev_fds[settings->vdev_id], K_DWVIOC_SETUP, settings)
[dw] split: 0 8191 8191 8191
[dw] LUT: 0x0=0 phy(00000000)
[dw] input: 1280x720@YUV420SP align 0 bit 8
[dw] output[0]: 960x540@YUV420SP align 0 bit 8 crop(0,0,0,0)
[dw] enter dev_fds[settings->vdev_id] < 0
[dw] enter ioctl(dev_fds[settings->vdev_id], K_DWVIOC_SETUP, settings)
[dw] split: 0 8191 8191 8191
[dw] LUT: 0x0=0 phy(00000000)
[dw] input: 1280x720@YUV420SP align 0 bit 8
[dw] output[0]: 960x540@YUV420SP align 0 bit 8 crop(0,0,0,0)
kd_mpi_vicap_start_stream enter 3
vicap_start_mcm is 3
kd_mpi_vicap_start_stream enter 3
vicap_start_mcm is 3
用通过以上步骤,就能轻松在 K230 RTOS 系统上跑通两路 AHD demo,无论是多摄像头监控、机器视觉巡检,还是边缘端图像采集场景,都能基于此框架快速拓展。赶紧拿起 K230 开发板,动手试试吧!
更多细节可参考官方文档:
https://kvftsfijpo.feishu.cn/wiki/I3UcwlAzIiv4iRkFz8vcqtG3nNk#share-U2mVdqK1BowFFvxvd4ncLA4nnig