在this post之后,我找到了一种使用sscanf
解析串行输入CSV格式数据的简洁方法:
volatile byte state = LOW;
volatile byte state_ = state;
long val1 = 100;
long val1_ = val1; // buffer
long val2 = 500;
long val2_ = val2; // buffer
String inpuSerialBufferString = "";
volatile byte control = LOW;
volatile byte control_ = control;
void reportSerial() {
Serial.println(String(millis()) + ", " + String(control) + ", " +
String(state) + ", " + String(val1) + ", " + String(val2));
}
void setup() {
Serial.begin(9600);
}
void loop() {
if(Serial.available() > 0)
{
inpuSerialBufferString = Serial.readStringUntil('\n');
sscanf(inpuSerialBufferString.c_str(), "%d,%d,%d,%d", &control, &state, &val1, &val2);
}
if (val1 != val1_ || val2 != val2_ || state != state_ || control != control_) {
reportSerial();
val1_ = val1;
val2_ = val2;
state_ = state;
control_ = control;
}
}
例如,在Arduino IDE的串行监视器发送中,我放置了以下值:
1,0,300,200
0,1,400,100
0,1,600,200
我得到
十一六二八、一、零、三百、二百
22260、0、1、741343632、741408868
41760、0、1、741343832、741408968
或者有时它不返回任何东西。如果您能帮助我了解问题所在以及如何修复它,我将不胜感激。代码中的优先级应该是
1.安全性:系统应具有可预测的行为
1.业绩受到赞赏
1.代码最好是简洁易读
- P.S.**我没有在Arduino StackExchange发帖,因为我在那里找不到任何标签
csv
,scanf
或parsing
。
- P.S.**我没有在Arduino StackExchange发帖,因为我在那里找不到任何标签
2条答案
按热度按时间r8xiu3jd1#
我想我已经解决了这个问题。从this post使用
strtok
标记化C字符串和atoi
进行C字符串到整数的转换,到目前为止我得到了可靠的结果。到
有一个小问题,我得到以下警告:
在函数“void loop()”中:
警告:从“const char*”到“char*”的转换无效[-fpermissive]
char* 输入序列缓冲区字符串=输入序列缓冲区字符串.c_str();
附言感谢@datafiddler替换
与
**P.S.2.**CSV中的最后一位数字应该是
4
位数,不能少,不能多。所以如果你想放50
,你需要发送0050
。我不知道为什么!bn31dyow2#
sscanf依赖于格式字符串来指定目标变量的大小。
特别是,状态和控制是字节。您需要使用“hh”修饰符(C99)来读取字符长度变量,并使用%hhd。或者,您需要使用临时int变量来阅读%d,然后将赋值转换为字节变量。
您还为val 1和val 2使用了%d,但它们是long int,因此格式字符串需要“l”修饰符-- %ld。
当sscanf将int值写入char变量时,它将写入int范围的值(16位或32位,具体取决于平台),结果不可预测。
如果变量在堆栈中,则会损坏堆栈,这很可能导致崩溃。