CODESYS V3与Raspberry Pi SL:I2C总线传感器读写技术咨询
在CODESYS Development System V3 + Raspberry Pi SL中通过I2C读取Si705x/VCNL传感器的实操方案
我之前在项目里刚好折腾过CODESYS+树莓派的I2C传感器,给你捋一套实打实的操作步骤,不用啃那些晦涩的数据手册也能快速上手。
第一步:先搞定硬件和CODESYS的I2C基础配置
- 先在树莓派上启用I2C:通过终端输入
raspi-config,进入Interfacing Options选择I2C开启,重启树莓派后,输入i2cdetect -y 1(树莓派3及以后的型号默认用总线1),确认传感器的I2C地址(比如Si705x默认是0x48,VCNL4040默认是0x60),这一步必须做,先确保硬件连接没问题。 - 在CODESYS项目里添加I2C驱动:打开你的项目,在设备树里找到Raspberry Pi的节点,右键选择添加设备,找到
CODESYS Control I2C Master添加进去,然后配置总线号(和树莓派的一致,比如1),波特率默认100k即可,大部分传感器都支持。
第二步:读取Si705x温度传感器的实操代码
Si705x的操作很简单,不用复杂的寄存器配置,发个测量命令就能读数据:
在CODESYS里新建一个ST(结构化文本)程序块,定义变量和逻辑:
// 全局/块级变量定义 bReadTempTrigger: BOOL; // 触发读取的开关 bySi705xAddr: BYTE := 16#48; // 传感器I2C地址,和i2cdetect结果一致 byMeasureCmd: BYTE := 16#E3; // Si705x单次温度测量命令 arrTempData: ARRAY[0..1] OF BYTE; // 存储读取的2字节数据 rRealTemp: REAL; // 转换后的实际温度(摄氏度) // 主逻辑 IF bReadTempTrigger THEN // 发送测量命令 I2CMaster_Write( xEnable := TRUE, bySlaveAddress := bySi705xAddr, pbyData := ADR(byMeasureCmd), uiLength := 1, xBusy => , xError => , uiErrorID => ); // 等待传感器完成测量(Si705x大概需要10ms,留余量) DELAY(10); // 读取测量结果 I2CMaster_Read( xEnable := TRUE, bySlaveAddress := bySi705xAddr, pbyData := ADR(arrTempData), uiLength := 2, xBusy => , xError => , uiErrorID => ); // 转换为实际温度(公式来自数据手册简化版,直接用就行) rRealTemp := (REAL((arrTempData[0] SHL 8) OR arrTempData[1]) * 175.72) / 65536.0 - 46.85; bReadTempTrigger := FALSE; // 重置触发开关 END_IF
解释一下:16#E3是Si705x的单次测量命令,读完的两个字节组合成16位数据,代入公式直接得到摄氏度温度,不用纠结数据手册里的时序细节,这个逻辑直接能用。
第三步:VCNL系列传感器的读写操作(以VCNL4040为例)
VCNL需要先指定寄存器地址再读写,比如读环境光强、接近值,或者修改配置位:
同样在ST块里定义变量和逻辑:
读取环境光强
// 变量定义 byVCNLAddr: BYTE := 16#60; // VCNL4040默认I2C地址 byALSRegAddr: BYTE := 16#04; // 环境光强数据寄存器地址 arrALSData: ARRAY[0..1] OF BYTE; rRealALS: REAL; // 转换后的光强(单位:lux) // 读取逻辑 // 先发送要读取的寄存器地址 I2CMaster_Write( xEnable := TRUE, bySlaveAddress := byVCNLAddr, pbyData := ADR(byALSRegAddr), uiLength := 1, xBusy => , xError => , uiErrorID => ); DELAY(2); // 短延时确保寄存器地址写入完成 // 读取2字节光强数据 I2CMaster_Read( xEnable := TRUE, bySlaveAddress := byVCNLAddr, pbyData := ADR(arrALSData), uiLength := 2, xBusy => , xError => , uiErrorID => ); // 转换为lux值(VCNL4040的转换系数是0.01) rRealALS := REAL((arrALSData[1] SHL 8) OR arrALSData[0]) * 0.01;
写入特定位的示例(开启接近传感器自动模式)
如果要修改传感器的配置寄存器特定位,比如开启自动模式:
// 变量复用上面的byVCNLAddr,新增配置寄存器地址 byConfigRegAddr: BYTE := 16#00; // VCNL4040的配置寄存器地址 arrConfigData: ARRAY[0..1] OF BYTE; // 读写逻辑 // 先读取当前配置寄存器的值 I2CMaster_Write( xEnable := TRUE, bySlaveAddress := byVCNLAddr, pbyData := ADR(byConfigRegAddr), uiLength := 1, xBusy => , xError => , uiErrorID => ); DELAY(2); I2CMaster_Read( xEnable := TRUE, bySlaveAddress := byVCNLAddr, pbyData := ADR(arrConfigData), uiLength := 2, xBusy => , xError => , uiErrorID => ); // 修改第3位(自动模式位)为1,其他位保持不变 arrConfigData[0] := arrConfigData[0] OR 16#08; // 写回配置寄存器(注意长度是3:寄存器地址+2字节配置数据) I2CMaster_Write( xEnable := TRUE, bySlaveAddress := byVCNLAddr, pbyData := ADR(byConfigRegAddr), uiLength := 3, xBusy => , xError => , uiErrorID => );
注意:VCNL的寄存器是16位的,读写都是2字节,而且字节顺序是低字节在前,所以转换的时候要把高字节左移8位再和低字节合并。
常见坑点提醒
- 树莓派的I2C总线是3.3V电平,绝对不能接5V的传感器,否则会烧坏树莓派或传感器。
- 如果CODESYS里I2C通信报错,先查
i2cdetect能不能找到传感器,再核对CODESYS里的地址是不是和检测到的一致,波特率不要设太高(超过400k可能会不稳定)。 - 数据手册里的时序要求,用
DELAY加几毫秒延时就足够,CODESYS的实时性完全能应付这些低速传感器。
内容的提问来源于stack exchange,提问作者jdoe
相关产品推荐
相关产品推荐

