尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用AT7456E给模拟监控叠加时间戳和Logo的完整方案

用AT7456E给模拟监控叠加时间戳和Logo的完整方案 前阵子改一批老式模拟监控甲方要求画面右下角必须有实时时间戳还得把单位Logo叠到左上角。摄像头本身不自带OSD菜单或者自带的只能显示时间不能传Logo市面上能买到的成品时间叠加器又不便宜要能自己定义内容就得加钱。那段时间我试了好几套方案最后盯上了FPV圈子常用的AT7456E也就是MAX7456的国产兼容型号。这芯片天生就是干视频字符叠加的把摄像头CVBS信号从它过一遍MCU通过SPI把字库和显示位置写进去画面就能带上时间水印和Logo成本十几块钱逻辑也不复杂。这篇文章就把我实际跑通的5个步骤写出来给同样想做视频OSD叠加的朋友做个参考。1. 为什么是AT7456E这颗芯片到底解决什么问题1.1 从监控画面缺时间戳说起模拟监控系统里时间水印是个绕不开的需求。很多老式模拟摄像头出厂时自带简单的OSD菜单能显示时间但时间格式固定没法加自定义文字更不用说叠加单位Logo。数字网络摄像头虽然本身支持OSD但那是ISP芯片内部完成的而且通常只能加在编码前的数字流里想往模拟视频链路里塞内容基本没门。AT7456E这类视频字符叠加芯片解决的就是“往模拟视频信号里叠加自定义内容”这个需求。它的本质是一个硬件字符发生器内部带有字符点阵RAM通过SPI接口接收MCU写入的字模和显示布局再把字符逐行“替换”到视频信号的对应位置。使用者不需要关心视频时序细节芯片把同步分离、场同步、消隐期判段这些脏活全包了。在FPV无人机图传领域AT7456E几乎是标配用来叠加电池电压、飞行时间、经纬度、卫星数量这些信息。我之前在飞控上用过它的同类芯片所以第一反应就是把这套思路搬到监控改造里来。结果发现效果出奇地好字符无闪烁、无拖尾叠加内容几乎零延迟而且摄像头、显示器、录像机都不需要改动只要把视频线从芯片中穿过去就行了。1.2 外置OSD芯片的适用边界说清楚一个问题AT7456E只能处理CVBS模拟视频信号也就是常说的AV信号、莲花头信号、BNC信号不能直接插在HDMI或者网络摄像头的网口上。现代IPC监控如果只走网络需要叠加信息应该在摄像头配置文件里设置或者用流媒体服务器在编码后进行文字叠加那是另一套方案。AT7456E真正适合的场景是这样的摄像头有模拟输出口或者链路中能拿到CVBS信号。比如老式模拟摄像机、DVR的模拟输入前端、车载监控的AV输出、无人机图传的模拟信号以及很多4G/工业摄像机上保留的CVBS调试口。把AT7456E串接在摄像头和显示器/采集卡/录像机之间就能实现视频透传加OSD叠加。选型上AT7456E相比其他方案的优势非常明显。用单片机纯软件生成字符叠加几乎不可行因为视频时序要求极高中断稍微抖动字符就飘了用FPGA做叠加成本高、开发周期长成品时间叠加器动辄几百块而且不能自定义Logo。AT7456E的模块价格十几块钱外围电路只需要晶振、电阻电容和视频接口MCU部分用STM32或Arduino都能驱动这个性价比在DIY圈子里很难找到替代品。2. 动手前的硬件准备与接线2.1 最小系统需要的元器件清单先把材料备齐再动手避免焊到一半发现缺东西。我这里按最常用的一套组合来说也是实测跑通的配置。AT7456E模块一个建议买带视频输入输出口的成品模块省去自己画板焊接芯片的麻烦。如果手头只有芯片需要按数据手册搭最小系统包括无源晶振具体频率看模块设计常见范围在4~24MHz之间、去耦电容、视频输入端的75欧端接电阻等。控制板一块STM32F103最小系统板或者Arduino Nano都行主要用SPI接口和几个GPIO。摄像头必须有CVBS输出。如果是网络摄像头确认是否有模拟输出口这个很重要别等接完了才发现信号进不去。视频线、BNC转接头或者AV莲花头配合模块接口类型使用。3.3V稳压模块AT7456E工作电压3.3V电流不大几十毫安量级从5V电源用AMS1117-3.3转一下就行。杜邦线若干面包板或者洞洞板都行方便前期调试。元器件清单看着多实际上都是常见物料电子市场或者网上模块店基本能一次买齐。如果只是快速验证直接买现成的AT7456E模块加一块Arduino半小时就能跑通基础demo。2.2 接线与供电注意事项AT7456E的引脚定义在不同模块上略有差异但核心引脚就那么几个。我这次的接线方式如下供参考。AT7456E模块引脚接MCU/系统说明VIN摄像头CVBS输出视频输入标准幅度约1VppVOUT显示器/录像机/采集卡叠加后的视频输出GND公共地视频地与电源地尽量单点连接SCKSPI SCK时钟实测1MHz稳定CS任意GPIO片选信号低电平有效MOSISPI MOSI数据输入MISOSPI MISO可读状态寄存器用RSTGPIO或RC复位低电平复位VCC3.3V模块供电GND电源负极与视频地共地接线有一个关键点容易踩坑视频信号的地线处理。模拟视频对地环路非常敏感如果摄像头电源地和AT7456E电源地之间存在较大电位差画面上就会出横杠干扰甚至滚动条纹。实际接法建议先共地再把视频线的屏蔽层在模块输入端单点接地不要形成多点环路。供电方面AT7456E虽然功耗不大但对电源纹波有要求。模块的VCC引脚和地之间最好并一颗10uF和一颗0.1uF陶瓷电容靠近芯片引脚放置。RST引脚接一个10k上拉电阻到3.3V再并一个0.1uF电容到地防止上电瞬间误复位。视频输入端如果能加一个串联电阻或ESD保护管在室外改造场景会耐用很多不过前期调试可以省略。3. 五步实操时间水印和Logo叠加3.1 第1步准备字模和Logo素材AT7456E屏幕上显示的字符不是ASCII码而是点阵字模。芯片内置一个字符索引表MCU写入的每个显示字符对应一个索引这个索引指向芯片RAM里存储的点阵数据。所以第一步要做的就是把时间字符数字、横杠、冒号、字母和Logo图片转换为AT7456E能识别的字模。字模工具我用的还是老牌的PCtoLCD2002虽然界面旧但功能稳定。取模时需要把字体大小设定为12像素宽、18像素高每个字符生成的点阵数据就是12×18的点阵。至于数据组织方式不同驱动有不同的处理逻辑常见的做法是每行存储两个或三个字节低有效位对应像素位置。具体字节数需要和你准备移植的驱动保持一致。如果你的驱动是从Betaflight或者minimOSD工程里抄来的那直接用它们配套的字体文件最省事每个字符按54字节处理256个字符打包成一个字体数组。把数字、大写字母、横杠、冒号、点号这些常用符号的位置记好就行。Logo的话先用画图软件把单位标志缩放到12×18的倍率比如想要一个大一点的Logo就拆成2×2共4个字符格每个格对应12×18像素分别生成字模后放到不同的字符索引位置。这一步看着繁琐但做完一次就能重复使用。我把常用字符字模和Logo字模合并成一个头文件之后所有项目直接include不用反复做取模。3.2 第2步初始化AT7456E初始化主要是配置SPI接口和设置芯片的视频模式。AT7456E上电后默认状态不显示OSD必须由MCU写寄存器把显示功能打开同时指定输入视频制式PAL还是NTSC。先看SPI配置。我实测1MHz时钟完全够用即使上传整个字库也就一两秒。MCU作为主机AT7456E作为从机写寄存器时CS拉低发寄存器地址和数值结束后拉高CS。读状态寄存器时控制字节最高位置1后续时钟周期就能把寄存器值读回来。初始化代码的核心部分是设置VM0、VM1寄存器。VM0决定了视频制式和字符格式PAL和NTSC的设置值不同接错制式会出现字符上下跳动或者位置不对。VM1控制屏幕显示开关初始建议设置为关闭显示状态等字库上传完再打开避免中间过程出现花屏。#define AT7456E_VM0 0x00 #define AT7456E_VM1 0x01 #define AT7456E_HOS 0x02 #define AT7456E_VOS 0x03 #define AT7456E_DMM 0x04 #define AT7456E_DMAH 0x05 #define AT7456E_DMAL 0x06 #define AT7456E_DMDI 0x07 #define AT7456E_CMM 0x08 #define AT7456E_CMAH 0x09 #define AT7456E_CMAL 0x0A #define AT7456E_CMDI 0x0B #define AT7456E_STAT 0xA0 void osd_init(void) { spi_master_init(); // 先复位等芯片稳定 cs_high(); delay_ms(50); // 设置为PAL制式关闭OSD显示 spi_write_reg(AT7456E_VM0, 0x02); // 实际值以手册为准 spi_write_reg(AT7456E_VM1, 0x00); // 水平垂直偏移清零 spi_write_reg(AT7456E_HOS, 0x00); spi_write_reg(AT7456E_VOS, 0x00); }补充说明一下HOS和VOS寄存器这两个是水平偏移和垂直偏移调节用来微调OSD字符在屏幕上的位置。如果字符压边或者偏离预期不需要重新布局直接改这两个寄存器的值就行后文排查部分还会提到。3.3 第3步上传字库初始化完成后字模还只是躺在MCU的Flash里需要把每个字符的点阵数据写入AT7456E的字符RAM。这一步就是字库上传也是整个流程里最容易出问题的地方。上传字库的流程是先设置字符存储控制寄存器CMM把芯片切换到字符RAM写入模式然后通过CMAH和CMAL两个寄存器指定当前要写哪个字符的起始地址最后逐个写入该字符的点阵字节。写完一个字符后地址会自动累加也可以重新设置地址来覆盖某个特定字符。为什么上传速度慢会出问题芯片内部在写入字符RAM时需要稳定的时钟和电压如果SPI中断频繁被打断或者电源纹波大写入的数据可能错位。我遇到过一次写完字库后数字和字母显示全乱的情况排查半天发现是MCU在传字库过程中被定时器中断抢占导致CS片选时序被打断。解决办法就是上传字库期间关闭无关中断用一个循环一口气传完。void osd_upload_font(const uint8_t *font) { // 设置字符RAM写入模式 spi_write_reg(AT7456E_CMM, 0x20); // 读手册确认模式值 // 256个字符逐个写入 for (int i 0; i 256; i) { uint16_t addr i * 54; spi_write_reg(AT7456E_CMAH, (addr 8) 0xFF); spi_write_reg(AT7456E_CMAL, addr 0xFF); for (int j 0; j 54; j) { // 等待芯片内部忙标志释放 while (spi_read_reg(AT7456E_STAT) 0x01); spi_write_reg(AT7456E_CMDI, font[i * 54 j]); } } }这里把单个字符的字节数按54字节处理这和Betaflight、minimOSD里的字体文件格式一致。如果你的字模工具有不同的输出格式需要按照驱动实际要求调整循环次数和地址步进。3.4 第4步配置字符布局并显示时间字库上传完毕接下来就是“排兵布阵”决定时间戳显示在屏幕的哪个位置。AT7456E的显示区域以字符格为单位屏幕上一行能放几十个字符格纵向也有十几行具体行列数和叠加的字符大小、视频制式有关。我的布局方案是时间水印放在右下角也就是第1行第20列左右格式“YYYY-MM-DD HH:MM:SS”一共19个字符Logo固定放在左上角第0行第0列必要时占多个相邻格。确定坐标后通过显示RAM写入接口把每个字符的索引值送到指定位置。这里需要理解显示RAM的地址计算。AT7456E内部有一个显示缓冲区每个显示位置对应一个地址。计算方式是“页面×每页字节数行号×每行字符数列号”。我给一个简化版的写入函数把行列坐标和字符索引传进去内部自动计算地址并触发DMA方式写入。void osd_set_char(uint8_t row, uint8_t col, uint8_t ch) { uint16_t addr row * 30 col; // 按一屏30列设计 spi_write_reg(AT7456E_DMM, 0x02); // 显示RAM写入模式 spi_write_reg(AT7456E_DMAH, (addr 8) 0xFF); spi_write_reg(AT7456E_DMAL, addr 0xFF); spi_write_reg(AT7456E_DMDI, ch); } void osd_show_string(uint8_t row, uint8_t col, const char *str) { while (*str) { osd_set_char(row, col, char_index(*str)); str; } }注意char_index函数是把ASCII字符映射到AT7456E字库的索引。上传字库时字符索引顺序需要自己约定比如把ASCII码0x30数字0的字符存到索引0那么显示时就先把ASCII码转换成对应索引。这一步不处理好就会出现“明明传的是数字0屏幕上却显示一个花屏符号”的情况。3.5 第5步动态刷新与Logo固定叠加静态显示时间没有意义真正实用的是每秒自动刷新的时间水印。这一步的关键在于不要每秒全屏重写只更新变化的那几个字符。否则屏幕会闪SPI总线也被无效传输占用。我用一个RTC模块提供时间源每秒读取一次时分秒和日期拼成字符串然后和上一秒的内容比较。如果内容没变就不动显示如果变了只把变化的字符逐个写入对应位置。char time_buf[20]; char prev_buf[20]; while (1) { rtc_get_time(time_buf, sizeof(time_buf)); if (memcmp(time_buf, prev_buf, 19) ! 0) { for (int i 0; i 19; i) { osd_set_char(1, 20 i, char_index(time_buf[i])); } memcpy(prev_buf, time_buf, 19); } delay_ms(1000); }Logo叠加和动态时间刷新不冲突。Logo字模在上传字库阶段已经作为某个字符索引存进芯片了现在只需要在初始化阶段调用一次osd_set_char把Logo的索引放到对应位置。以后不管时间怎么变Logo不受影响因为赛道里的字符内容独立存储。如果要叠加一个比单个字符更大的Logo比如两倍宽度就把Logo拆成左右两个字符分别放到相邻的列例如第0列放左半部分第1列放右半部分。这样做出来的效果无缝连接只要字模像素设计时保持边缘对齐。4. 进阶玩法GIS坐标、状态提示与画质联动4.1 移动监控叠加GPS/GIS信息提到移动监控摄像头带GIS信息AT7456E其实是最省钱的实现路径之一。车载监控、无人机巡检、执法记录仪只要有模拟视频输出再加上一个GPS/北斗模块就能把经纬度、速度、航向实时叠到画面上事后回放视频相当于带着一张移动轨迹地图。实现思路不复杂GPS模块通过串口以NMEA协议输出数据MCU解析出$GPRMC语句里的纬度、经度、地面速度、日期时间然后把它们格式化成字符串通过前面写的osd_show_string函数显示到屏幕上。解析NMEA的代码网上很多核心就是按逗号分隔字段。我当时的做法是写了一个轻量级的解析函数只提取RMC语句其他语句直接丢弃。拿到经纬度后格式化成“N31.2305 E121.4736”这样的文本放在屏幕底部一行不遮挡主要画面。这里有一个值得一提的细节时间水印可以直接从GPS的UTC时间取省掉一颗RTC芯片。GPS信号包含精确到秒的时间只要冷启动成功就能提供可靠时间源非常适合户外无人值守的监控场景。如果现场搜星困难再退回到RTC方案两条路可以做成自动切换。4.2 夜间全彩模式灵敏度问题里OSD能做什么网上经常看到有人问“海康威视4G监控摄像头晚上开全彩模式下灵敏度低下画面噪点大暗部细节看不清”。这个问题本质是sensor和ISP层面的曝光、增益、降噪策略问题光靠叠加字符肯定解决不了。AT7456E只负责显示不接触视频原始数据更动不了ISP参数。但OSD可以辅助定位问题。我调试这类摄像头时会把当前工作模式、曝光状态、增益提示通过AT7456E叠加在监控画面上比如“Mode: FullColor Gain: 24dB”。这样现场调整补光灯策略或者切换日夜模式时回看录像就能清楚知道当时设备处于什么状态排查到底是算法触发了全彩模式导致灵敏度下降还是硬件补光不足。这种“状态可视化”在远程调试场景很实用值班人员看着画面就能汇报设备状态不用每次打电话问后台。如果你确实想提升全彩模式下的夜间灵敏度要在摄像头自身的配置工具里调参数而不是在叠加层上想办法。把时钟灵敏度调低、开启超低照度模式、调整降噪等级、限制最大曝光时间这些动作才会真正影响画面亮度。OSD叠加的“Mode/Gain”提示更多是辅助判断这些调整是否生效。4.3 与摄像头参数调整工具的协同监控摄像头的画质参数调整离不开配套软件工具。厂家会提供调试工具或者开放SDK用来修改分辨率、码率、日夜切换阈值、增益上限等参数。这些工具通常支持导出配置文件或者通过网络/串口把参数下发到设备。在DIY场景里我习惯做一个“联动提示”MCU通过串口或网络接口读取摄像头当前配置的关键状态然后把状态同步到AT7456E的OSD显示区域。比如工具里把增益上限从12dB调到18dBOSD上立刻显示“GainLimit:18dB”把日夜模式设为“自动”OSD就显示“Mode:Auto”。这样在视频图像上直接能看到当前配置文件生效情况不用来回切换屏幕。具体的联动方式要看你用的设备与工具。有些厂家工具支持HTTP API查询状态有些是私有串口协议。如果都没办法直接对接还有一个土办法用脚本解析工具导出的配置文件把关键参数生成一个文本标签通过串口发给MCU更新OSD。虽然时效性差一些但作为记录存证、回放分析完全够用。5. 常见问题与排查记录5.1 黑屏、无OSD输出黑屏是刚上电最常遇到的问题表现为屏幕完全没画面或者有视频但看不到任何OSD字符。有视频但没OSD字符多半是VM1寄存器里显示开关是关闭状态或者字库上传失败导致所有字符索引都是空白。先确认视频信号有没有真正进入芯片。用万用表量模块VIN端直流电压CVBS信号大约0.3V左右用示波器看波形最直接有同步头的复合视频波形一目了然。有信号但还是黑屏检查VM0寄存器制式设置是不是PAL/NTSC选反了。制式不匹配时常见现象是画面很暗或者滚动条纹。如果视频直通正常但OSD不显示下一步读STAT寄存器确认芯片是否处于忙碌状态。如果忙标志一直不释放说明芯片可能没完成初始化或者处于异常模式。把CS引脚拉高断电重启等50ms再重新执行初始化流程多数情况能恢复。5.2 字符乱码、闪烁、错位字符乱码几乎都是字模数据和驱动不匹配引起的。比如驱动按54字节格式处理而字模工具输出的是36字节这样从第2个字符开始全部错位屏幕上看到的自然是一堆乱码。解决方法是统一格式直接用Betaflight的字体文件或者把你自己的取模方式调整到和驱动一致。闪烁问题通常和刷新方式有关。如果每秒都重写整屏字符会出现肉眼可见的闪烁尤其在SPI速率不高的情况下。按前文说的差分更新策略只改时间变化位闪烁基本消失。硬件端也可能有原因供电纹波大或者晶振频率不准都会导致字符边缘跳动建议用低ESR电容给模块供电并检查晶振负载电容是否匹配。错位的问题先检查HOS/VOS寄存器的值这两个偏移寄存器专门用来调位置遇到字符整体偏左偏右直接改它们就行。如果是单个字符横向错乱那就回到显示RAM地址计算确认每行字符数和地址步进和芯片实际配置一致。5.3 时间刷新卡顿与SPI占用时间每秒刷新一次看起来频率不高但如果你把大量其他功能挂在同一个SPI总线上比如SPI Flash、SD卡、传感器它们共用总线时就会互相干扰。我在一个项目里把SD卡和AT7456E挂在同一条SPI每次SD卡写入时OSD会卡一下字符更新明显变慢。解决办法有三个方向。一是降低时间刷新频率改成5秒刷新一次对监控场景完全够用二是在SPI访问上做互斥确保读写SD卡时不打断OSD传输三是如果用STM32可以把OSD刷新放到DMA传输里MCU只要准备数据后续搬运交给DMACPU占用率大幅降低。注意用DMA时CS引脚的拉低和拉高要放在DMA传输前后手动控制不然片选时序会和DMA传输脱节。5.4 排查问题速查表把常见问题和对应解法整理成表格方便现场调试时快速定位。现象可能原因快速排查操作视频直通但无OSDVM1未开启显示写VM1打开OSD显示开关画面全黑VM0制式设错/无信号输入用示波器查VIN确认PAL/NTSC字符乱码字模格式与驱动不匹配统一用54字节字库或Betaflight字体字符闪烁全屏重写/电源纹波差分更新加强去耦电容字符整体偏移HOS/VOS未校准调整水平/垂直偏移寄存器某个字符显示为空白字模未上传或索引错误重新上传该字符检查索引映射SPI通信异常CS时序被中断/接线过长上传期间关中断缩短杜邦线上电后字库丢失芯片RAM易失需每次上电上传在初始化流程里自动加载字库最后再分享一个我实际踩过的坑AT7456E的字库是易失性的断电就丢上电后必须重新上传。一开始我把字库放在SD卡里每次开机从文件系统读取速度慢不说还经常因为文件系统挂载失败导致OSD白屏。后来直接把整个字库数组编译进MCU的Flash上电几百毫秒就传完稳定省事。如果你也给摄像头做类似改造建议从一开始就把字库固化成代码数组少走弯路。另外视频地线不干净会导致字符边缘毛刺我在模块电源引脚并了一颗100uF低ESR电容之后问题基本消失这个小细节当时调了好几天写出来算是给后来人省点时间。
返回列表