You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:27:20