gpt4 book ai didi

c - 使用初始数据读取串口会导致很多零

转载 作者:太空宇宙 更新时间:2023-11-03 23:49:31 25 4
gpt4 key购买 nike

我正在测试一个串行实现,当我打开一个串行端口时(我有一个 Arduino 吐出罗盘数据行。)有时我一开始会得到一堆零。我还以为这是之前的遗留数据,结果好像不是(flushing IO好像没什么用)

这是一个用 C 编写的编程语言串行实现,我正在 Linux 上测试它,但在 Windows 上得到了类似的结果。

strace 输出在第一次读取时显示:

read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 34815) = 1544
write(1, "== ", 3== ) = 3
write(1, "#{\n00000000000000000000000000000"..., 503#{
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000583A20353333202020593A20313020
20205A3A2033313920202058733A2033393520202059733A203136312020205A
733A20323933202020483A20302E3436202020413A...) = 503

我尝试添加以下行以在端口关闭之前、打开之后以及设置的属性之后清除此数据:

tcflush(ttyfd, TCIOFLUSH); 

但似乎对解决这个问题没有帮助。关于如何清理它的任何想法?

代码来自一个大型项目,我收集了一些相关部分如下,变量声明即使没有显示但应该足够清楚

打开端口:

ttyfd = open(&devpath[0], O_RDWR | O_NOCTTY | O_NONBLOCK); // ttyUSB0 in this case

更改设置:

    if (speeds[n] == 0) speed = B115200; // invalid, use default

cfsetospeed (&attr, speed);
cfsetispeed (&attr, speed);

// C-flags - control modes:
attr.c_cflag |= CREAD | CS8 | CLOCAL;

// L-flags - local modes:
attr.c_lflag = 0; // raw, not ICANON

// I-flags - input modes:
attr.c_iflag |= IGNPAR;

// O-flags - output modes:
attr.c_oflag = 0;

// Control characters:
// device is non-blocking (polled for changes):
attr.c_cc[VMIN] = 0;
attr.c_cc[VTIME] = 0;

// Make sure OS queues are empty:
tcflush(ttyfd, TCIOFLUSH);

// Set new attributes:
if (tcsetattr(ttyfd, TCSANOW, &attr)) return 2;

这是从 OSEPP Compass 模块发送数据的 Arduino 代码

// OSEPP Compass Sensor Example Sketch
// by OSEPP <http://www.osepp.com>
// Modifications by Chris W. to accommodate declination, scaling and origin adjustment 2013-02-13
// This sketch demonstrates interactions with the Compass Sensor

#include <Wire.h>

const uint8_t sensorAddr = 0x1E; // Sensor address (non-configurable)
const float xOffset = 103.0; // Offset required to adjust x coordinate to zero origin
const float yOffset = -165.0; // Offset required to adjust y coordinate to zero origin
const float declination = 70.1; // Enter magnetic declination mrads here (local to your geo area)

// One-time setup
void setup()
{
// Start the serial port for output
Serial.begin(115200);

// Join the I2C bus as master
Wire.begin();

// Configure the compass to default values (see datasheet for details)
WriteByte(sensorAddr, 0x0, 0x70);

WriteByte(sensorAddr, 0x1, 0x20); // +1.3Ga

// Set compass to continuous-measurement mode (default is single shot)
WriteByte(sensorAddr, 0x2, 0x0);
}

// Main program loop
void loop()
{
uint8_t x_msb; // X-axis most significant byte
uint8_t x_lsb; // X-axis least significant byte
uint8_t y_msb; // Y-axis most significant byte
uint8_t y_lsb; // Y-axis least significant byte
uint8_t z_msb; // Z-axis most significant byte
uint8_t z_lsb; // Z-axis least significant byte

int x;
int y;
int z;

// Get the value from the sensor
if ((ReadByte(sensorAddr, 0x3, &x_msb) == 0) &&
(ReadByte(sensorAddr, 0x4, &x_lsb) == 0) &&
(ReadByte(sensorAddr, 0x5, &z_msb) == 0) &&
(ReadByte(sensorAddr, 0x6, &z_lsb) == 0) &&
(ReadByte(sensorAddr, 0x7, &y_msb) == 0) &&
(ReadByte(sensorAddr, 0x8, &y_lsb) == 0))
{
x = x_msb << 8 | x_lsb;
y = y_msb << 8 | y_lsb;
z = z_msb << 8 | z_lsb;

int xs;
int ys;
int zs;

float gScale = .92; // Scale factor for +1.3Ga setting

float adjx = x - xOffset;
float adjy = y - yOffset;

xs = adjx * gScale;
ys = adjy * gScale;
zs = z * gScale;

float heading = atan2(ys, xs);
heading += declination / 1000; // Declination for geo area

if (heading < 0);
heading += 2*PI;

if (heading > 2*PI)
heading -= 2*PI;

float angle = heading * 180/M_PI;

Serial.print("X: ");
Serial.print(x);
Serial.print(" Y: ");
Serial.print(y);
Serial.print(" Z: ");
Serial.print(z);
Serial.print(" Xs: ");
Serial.print(xs);
Serial.print(" Ys: ");
Serial.print(ys);
Serial.print(" Zs: ");
Serial.print(zs);
Serial.print(" H: ");
Serial.print(heading);
Serial.print(" A: ");
Serial.println(angle);
}
else
{
Serial.println("Failed to read from sensor");
}

// Run again in 1 s (1000 ms)
delay(500);
}

// Read a byte on the i2c interface
int ReadByte(uint8_t addr, uint8_t reg, uint8_t *data)
{
// Do an i2c write to set the register that we want to read from
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();

// Read a byte from the device
Wire.requestFrom(addr, (uint8_t)1);
if (Wire.available())
{
*data = Wire.read();
}
else
{
// Read nothing back
return -1;
}

return 0;
}

// Write a byte on the i2c interface
void WriteByte(uint8_t addr, uint8_t reg, byte data)
{
// Begin the write sequence
Wire.beginTransmission(addr);

// First byte is to set the register pointer
Wire.write(reg);

// Write the data byte
Wire.write(data);

// End the write sequence; bytes are actually transmitted now
Wire.endTransmission();
}

我将尝试在 arduino 代码中切换延迟和串行写入的顺序,因为它可能会解决这个问题,但对于类似的 future 场景,该代码将仍然无效。

最佳答案

查看了 IC 的数据表。

参见第 14 页:Link

Continuous-Measurement Mode. In continuous-measurement mode, the device continuously performs measurements and places the result in the data register. RDY goes high when new data is placed in all three registers. After a power-on or a write to the mode or configuration register, the first measurement set is available from all three data output registers after a period of 2/f_DO and subsequent measurements are available at a frequency of f_DO, where f_DO is the frequency of data output

根据 Arduino 文档,Wire 库以 100KHz 运行。 2/100KHz == 20uS。假设您的 Arduino 以 16MHz(1 个周期 == 62.5ns)运行,您可能没有等待足够长的时间来读取寄存器。

为了使您的代码更健壮,我建议在执行任何读取之前检查状态寄存器的 RDY 位。数据可能是正确的,但您必须考虑 IC 所用的启动时间。

如果您这样做并发现同样的问题仍然存在,那么至少您可以进一步隔离问题。


或者:如果您只想快速破解,可以将 500 毫秒的延迟放在顶部主循环的底部。

关于c - 使用初始数据读取串口会导致很多零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24006285/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com