PCA9685寄存器配置与I2C通信实战(一)

张开发
2026/5/4 12:16:22 15 分钟阅读
PCA9685寄存器配置与I2C通信实战(一)
1. PCA9685模块基础认知第一次拿到PCA9685模块时我以为是块普通的PWM扩展板直到真正用起来才发现这玩意儿简直就是舵机和LED控制的瑞士军刀。这个指甲盖大小的芯片能同时驱动16路PWM信号每路分辨率高达12位4096级最妙的是所有通道共享同一个基准时钟完全避免了树莓派硬件PWM的通道间抖动问题。记得去年做智能花盆项目时我需要同时控制12个舵机模拟向日葵追光。当时傻乎乎地用树莓派GPIO模拟PWM结果CPU占用率直接飙到80%舵机还抖得像得了帕金森。换成PCA9685后不仅解决了这些问题还能通过I2C轻松实现级联——理论上最多62块板子协同工作总共992路PWM输出模块背面那个蓝色电位器特别有意思它其实是用来调节输出驱动能力的。实测发现顺时针拧到底时5V供电下能输出约25mA的拉电流足够直接驱动小型舵机。不过建议还是外接逻辑电平转换器特别是当控制电压超过5V时否则容易烧毁I2C接口。2. 寄存器配置核心逻辑2.1 寄存器地图精要翻遍16页的英文datasheet后我总结出这张速查表寄存器名地址位宽功能说明MODE10x008bit时钟源选择/低功耗模式控制MODE20x018bit输出极性/驱动模式配置LED0_ON_L0x068bit通道0开启时间低字节LED0_ON_H0x078bit通道0开启时间高字节LED0_OFF_L0x088bit通道0关闭时间低字节LED0_OFF_H0x098bit通道0关闭时间高字节PRE_SCALE0xFE8bitPWM频率预分频系数特别提醒所有LEDn_OFF_H寄存器的第4位bit4都是强制关闭位。有次调试时不小心设置了这个位舵机直接罢工排查了两小时才发现是这个隐藏功能在作怪。2.2 时钟配置的坑设置PWM频率时有个大坑——必须在休眠状态下修改PRE_SCALE寄存器具体操作流程应该是读取当前MODE1值设置SLEEP1进入休眠等待至少500us写入新的PRE_SCALE值清除SLEEP位唤醒芯片再等待500us让时钟稳定用i2cset实现就是# 进入休眠 i2cset -y 1 0x40 0x00 0x10 usleep 500 # 设置50Hz频率24MHz时钟源时 i2cset -y 1 0x40 0xFE 0x79 # 唤醒芯片 i2cset -y 1 0x40 0x00 0x80 usleep 5003. PWM输出实战技巧3.1 占空比计算秘籍PWM周期被分成4096个tickLEDn_ON和LEDn_OFF的值就是基于这个刻度设置的。举个例子要设置通道3输出25%占空比开启时刻设为0LED3_ON 0关闭时刻 4096×25% 1024转换为十六进制1024 0x0400拆分高低字节HIGH0x04, LOW0x00对应的i2cset命令i2cset -y 1 0x40 0x12 0x00 # LED3_ON_L i2cset -y 1 0x40 0x13 0x00 # LED3_ON_H i2cset -y 1 0x40 0x14 0x00 # LED3_OFF_L i2cset -y 1 0x40 0x15 0x04 # LED3_OFF_H3.2 相位调节黑科技通过错开各通道的LEDn_ON值可以实现相位差控制。比如要让通道4比通道5滞后90度# 通道4在25%周期点开启 i2cset -y 1 0x40 0x18 0x00 # LED4_ON_L0 i2cset -y 1 0x40 0x19 0x04 # LED4_ON_H1024 i2cset -y 1 0x40 0x1A 0x00 # LED4_OFF_L0 i2cset -y 1 0x40 0x1B 0x08 # LED4_OFF_H2048 # 通道5在0点开启 i2cset -y 1 0x40 0x1C 0x00 # LED5_ON_L0 i2cset -y 1 0x40 0x1D 0x00 # LED5_ON_H0 i2cset -y 1 0x40 0x1E 0x00 # LED5_OFF_L0 i2cset -y 1 0x40 0x1F 0x04 # LED5_OFF_H1024这个技巧在控制多关节机械臂时特别有用能有效降低电源的瞬时电流需求。4. 高级功能挖掘4.1 批量写入技巧开启MODE1的AIAuto-Increment位后可以连续写入多个寄存器。比如要同时设置通道0-3的PWM# 启用地址自增 i2cset -y 1 0x40 0x00 0xA0 # 批量写入6个通道配置每个通道4个寄存器 i2cset -y 1 0x40 0x06 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 i注意最后加个i参数表示多字节写入。实测这个操作比单字节写入快6倍以上特别适合需要快速更新所有通道的场景。4.2 应急停止方案所有通道的紧急关闭有两种方式快速方案设置ALL_LED_OFF_H的bit4i2cset -y 1 0x40 0xFD 0x10优雅方案逐个通道设置LEDn_OFF_H的bit4for i in {6..69}; do i2cset -y 1 0x40 $i 0x10 done第一种会丢失所有寄存器设置第二种能保留当前配置。去年展会演示时有个熊孩子乱按开关就是靠这个应急方案避免了舵机暴走。

更多文章