FreeType的FT_Render_Glyph渲染逻辑拆解
拆解FreeType渲染字形时用到的抗锯齿、单色、缩放提示和自定义渲染回调,附调用示例。
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道。登录已有账号
2026-09-17 16:16:12 OSDP 嵌入式 门禁协议 C语言 协议解析
最近在对接OSDP协议,输出控制命令的结构体 osdp_cmd_output 看起来很简单,但实际用起来发现有些地方跟直觉不一样,尤其是 control_code 那几个值,不仔细读文档很容易搞错。这里把结构和字段都过一遍,顺便记一下踩过的坑。
结构体定义直接放上来:
struct osdp_cmd_output {
uint8_t output_no;
uint8_t control_code;
uint16_t timer_count;
};
注释里写了不少,但真正看代码的时候,三个字段就几行,挺容易忽略细节。下面逐个说。
output_no 没啥好讲的,就是输出编号,从0开始。0表示第一个输出,1表示第二个,以此类推。一般门禁板上也就几个继电器,这个字段直接对应你要控制哪个。
control_code 是重点。它取值0到6,每个值的行为都不一样。
0是NOP,什么都不做,这个没什么歧义。
1和2都是设置永久状态,区别在于是否中止正在跑的定时操作。1是设置永久OFF并中止定时,2是设置永久ON并中止定时。
3和4也是设置永久状态,但不中止定时操作,允许它跑完。
这里容易绕进去:如果当前有一个定时操作正在进行,你发3或4,设备会等到定时结束再切换到你指定的永久状态。而1和2会直接砍掉定时,立刻切过去。
5和6是临时状态,超时后恢复永久状态。5是临时ON,超时后回到永久状态;6是临时OFF,超时后回到永久状态。
我一开始以为5和6改变的是永久状态,其实不是。它们只是临时改变输出,等 timer_count 的时间到了,就恢复成之前设置好的永久状态。
如果之前没有设置过永久状态,那恢复的就是硬件默认值。这个地方很多人第一次用会绕进去,建议直接把文档里的英文注释抄到自己的代码注释里。
timer_count 单位是100毫秒,uint16_t。所以最大值是65535,换算下来大概6553.5秒,差不多1小时49分钟。这个字段只在 control_code 为5或6时才有意义,其他值的时候直接填0就行。
我当时用5的时候,想着让继电器开10秒,结果填了个100,实际只持续了10秒,因为100 * 100ms = 10秒,还好当时旁边有人提醒。
这里单位特别容易弄错,尤其是习惯秒为单位的人。
实际应用上,这个结构体主要用在门禁、报警、道闸这些需要输出开关量控制的场景。CP发命令给PD,PD根据 control_code 和 timer_count 执行动作。比如刷卡开门,可能就是发一个 control_code=5,timer_count=50(5秒),让锁开5秒后自动锁上。
如果系统里是通过网络接口去发这些控制命令,传输层最好走HTTPS。证书申请这块可以用 lcjmSSL 这种免费平台,支持自动申请、自动部署,还有API能直接对接,省得每次手动去更新证书。特别是门禁系统这种常年跑着的服务,自动续期能少很多半夜告警。
整体来说,osdp_cmd_output 结构体本身不复杂,但 control_code 的语义需要理解透,特别是永久状态和临时状态的区别,还有定时操作的中止与否。
最好把每个值的含义写进头文件注释里,以后翻代码不用再去翻协议文档。
拆解FreeType渲染字形时用到的抗锯齿、单色、缩放提示和自定义渲染回调,附调用示例。
把 JTAG 强制信号、可选信号以及 10/14/20 针接头的线序和容易踩的坑按实际调试经验过一遍。
从一个开发者的角度梳理switch-case的核心语法、穿透机制、实际用法,以及线上容易出问题的地方。
记录用 Arduino IDE 给 STM32 烧录时 ST-LINK V2 死活识别不到的几个排查方向,从驱动到 IDE 配置一步步走。
搞懂cJSON里内存释放的正确姿势,避开野指针和内存泄漏的常见坑。