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

使用PIC16+CCS C通过I2C读取ADXL343数据异常求助

问题排查:PIC16通过I2C读取ADXL343始终返回65535

问题背景

使用PIC16微控制器、CCS C编译器,通过I2C协议读取ADXL343加速度计的X/Y/Z轴数据,Arduino测试可正常获取数值,但自制C代码始终输出X=65535、Y=65535、Z=65535。

相关代码片段

adxl343.h

enum {
  adxl343_IIC_ADDR1 = 0x53 , /* Normal Address */
  adxl343_I2C_WRITE = 0xa6,
  adxl343_I2C_READ  = 0xa7,
};

main.c(原代码标注为main.h,应为笔误)

iic_power_enable();
delay_ms(1000);
adxl343_write_reg(adxl343_IIC_ADDR1,adxl343_REG_POWER_CTL,0x08);
delay_ms(2000);

errorReadData=0;
adxl343_t xyz;
int i = 0;
int8 lsb = 0;
int8 msb = 0;
int ack = 0;
i2c_custom_start();
ack = i2c_custom_write(iic_addr | adxl343_I2C_WRITE);
errorReadData+=i2c_ACK != ack;
assert(i2c_ACK == ack);
ack = i2c_custom_write(adxl343_OUT_X_MSB);
errorReadData+=i2c_ACK != ack;
assert(i2c_ACK == ack);
i2c_custom_start();
ack = i2c_custom_write(iic_addr | adxl343_I2C_READ);
errorReadData+=i2c_ACK != ack;
assert(i2c_ACK == ack);

msb = i2c_custom_read(TRUE);
lsb = i2c_custom_read(TRUE);
xyz.x = make16(lsb, msb);
msb = i2c_custom_read(TRUE);
lsb = i2c_custom_read(TRUE);
xyz.y = make16(lsb, msb);
msb = i2c_custom_read(TRUE);
lsb = i2c_custom_read(FALSE); /* End register reading. */
xyz.z = make16(lsb, msb);
i2c_custom_stop();

TRACE1("\r\nZ=%Lu", xyz.z);
TRACE1("\r\nX=%Lu", xyz.x);
TRACE1("\r\nY=%Lu", xyz.y);

i2c_custom.h

int i2c_custom_read(int ack) {return i2c_read(ack);}
int i2c_custom_write(int8 data) {return i2c_write(data);}
void i2c_custom_stop() {i2c_stop();}

核心问题排查

  • I2C地址拼接错误:
    代码中用iic_addr | adxl343_I2C_WRITE拼接写地址,但adxl343_I2C_WRITE本身已是完整的I2C写地址(0x53左移1位得到0xa6),按位或操作会破坏正确地址。比如若iic_addr为0x53,0x53 | 0xa6 = 0xf7,完全偏离ADXL343的真实地址,导致通信失败,读取到默认的0xFF字节,组合后就是65535。应直接使用adxl343_I2C_WRITE或adxl343_IIC_ADDR1 << 1,而非按位或。

  • 数据字节顺序错误:
    ADXL343的OUT_X_MSB是16位数据的高字节,OUT_X_LSB是低字节,正确的16位数值组合应为make16(msb, lsb),但代码中用了make16(lsb, msb),会导致字节反转。不过当前返回全0xFF,说明通信问题是主因,此错误为次要问题。

  • iic_addr变量未明确定义:
    代码中使用了iic_addr但未给出定义,若该变量不是0x53,会进一步加剧地址拼接错误,直接导致I2C通信无法建立。

  • 初始化配置缺失(次要):
    仅设置POWER_CTL为测量模式(0x08),未配置DATA_FORMAT寄存器(如量程、数据对齐),但Arduino能正常读取说明硬件本身无问题,此配置缺失并非当前返回全65535的直接原因。

修复建议

  1. 修正I2C地址写法,将:

    ack = i2c_custom_write(iic_addr | adxl343_I2C_WRITE);
    // ...
    ack = i2c_custom_write(iic_addr | adxl343_I2C_READ);
    

    改为:

    ack = i2c_custom_write(adxl343_I2C_WRITE);
    // ...
    ack = i2c_custom_write(adxl343_I2C_READ);
    
  2. 修正字节顺序,将make16(lsb, msb)改为make16(msb, lsb)。

  3. 若保留iic_addr变量,应使用(iic_addr << 1)作为写地址,(iic_addr << 1) | 1作为读地址,而非直接按位或预定义的adxl343_I2C_WRITE/adxl343_I2C_READ。

内容的提问来源于stack exchange,提问作者Aizaz Afridi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:20:39