补码左对齐整数转常规二进制及树莓派加速度计读数比较技术问询
嘿,我来帮你搞定这两个问题,刚好做过类似的嵌入式项目,给你一步步捋清楚:
1. 补码左对齐整数转常规二进制
首先明确:你提到的是双字节16位补码(因为加速度计输出两个补码字节),左对齐意味着这两个字节组成完整的16位补码(最高位为符号位)。转换逻辑很清晰:
- 如果是正数(最高位为0):补码和原码完全一致,直接把这16位转换成二进制字符串即可,比如补码
0000110010100101,直接输出这个二进制就是常规二进制。 - 如果是负数(最高位为1):先对整个16位补码按位取反,然后加1得到原码,再输出原码的二进制(符号位保留1)。比如补码
1111001101011011,取反后是0000110010100100,加1得到0000110010100101,原码就是1000110010100101(符号位+数值位)。
给你个C++小函数实现,直接把16位补码转成二进制字符串:
#include <bitset> #include <string> std::string twosComplementToBinary(int16_t complement) { // 转成bitset直接输出二进制 std::bitset<16> bits(complement); std::string binary = bits.to_string(); // 负数可选标注原码,方便查看 if (complement < 0) { int16_t original = (~complement) + 1; std::bitset<16> original_bits(original); binary += " (原码: 1" + original_bits.to_string().substr(1) + ")"; } return binary; }
2. C++/Qt + wiringPi 处理I2C加速度计,实现机械臂角度往返控制
我之前用wiringPi做过I2C传感器项目,结合Qt做UI和逻辑控制,给你一套可行的落地方案:
第一步:读取I2C加速度计的补码数据
先确保wiringPi初始化完成,并且打开I2C设备(替换成你的加速度计I2C地址):
#include <wiringPiI2C.h> #include <cstdint> int fd = wiringPiI2CSetup(0x1D); // 替换为你的加速度计I2C地址 if (fd == -1) { // 处理初始化失败,比如Qt里弹出错误提示 return; }
然后读取目标轴的两个补码字节(替换成你的加速度计数据寄存器地址):
// 读取高字节和低字节(示例为X轴数据寄存器) uint8_t high_byte = wiringPiI2CReadReg8(fd, 0x32); uint8_t low_byte = wiringPiI2CReadReg8(fd, 0x33); // 组合成16位补码,直接转有符号整数(C++的int16_t自动处理补码转换) int16_t current_reading = (static_cast<int16_t>(high_byte) << 8) | low_byte;
这里int16_t是关键,它会自动把双字节补码转换成对应十进制数值,不用手动做补码转原码的操作,省了很多事。
第二步:比较读数,实现机械臂往返逻辑
先预设目标值(对应机械臂需要停留的角度的加速度计读数),再通过状态变量控制往返方向:
// 可作为类成员或全局变量 int16_t target_value = 1234; // 替换为你的预设值 bool moving_to_target = true; const int threshold = 5; // 误差阈值,避免频繁切换方向 // 每次读取读数后执行的逻辑 if (moving_to_target) { if (current_reading >= target_value - threshold) { // 到达目标附近,切换方向 moving_to_target = false; controlArmReverse(); // 自定义函数:控制机械臂往回走 } else { controlArmForward(); // 自定义函数:控制机械臂往目标方向走 } } else { if (current_reading <= target_value + threshold) { // 回到目标附近,切换方向 moving_to_target = true; controlArmForward(); } else { controlArmReverse(); } }
controlArmForward()和controlArmReverse()需要你根据硬件实现,比如通过GPIO输出PWM控制舵机,或者发送指令给机械臂驱动板。
第三步:Qt定时读取逻辑
在Qt里用QTimer定时读取加速度计数据,保证逻辑实时性:
QTimer *readTimer = new QTimer(this); connect(readTimer, &QTimer::timeout, this, [this]() { readAccelerometer(); // 封装好的读取加速度计函数 controlArm(); // 封装好的机械臂控制逻辑 }); readTimer->start(100); // 每隔100ms读取一次,可根据需求调整
这样就能实现机械臂在预设角度附近往返的功能了,注意加速度计的安装方向要和机械臂角度对应,可能需要先校准初始值。
内容的提问来源于stack exchange,提问作者MarqTwine
相关产品推荐
相关产品推荐

