我正在编写一些代码,通过SPI记录来自多个传感器的电压测量结果。我将所有数据保存在自定义数据结构中,然后在发生太多事件或用户请求数据时将数据结构打印到终端。我发现的问题是,当我调用DataDump函数时,每个事件中的最后一个数据值是完全错误的。如果我尝试在记录数据后立即打印,它是正确的。我已经将我认为重要的代码片段放在下面,但是这里有一个指向整个程序http://pastebin.com/Y7kcntu3的链接。
我唯一想知道的是,当我为200个事件分配内存时,结构的范围并没有扩展到dumpData函数。但这并不是真正有意义的,因为所有其他数据都是存在和正确的。我的另一个想法是,当从char->二进制->十进制进行转换时会出现anderror,但同样只有单个值是错误的。
第一个代码块是我为处理来自多个传感器的数据而创建的数据结构。这些数据仅仅是来自ADC的8位SPI数据,所以我使用了无符号字符来最小化所使用的内存量。我还为200个事件分配了足够的内存。
typedef struct //event structure, containts a timestamp element and an array of 18 data points
{
unsigned long int timeStamp;
unsigned char data[SENSORS];
} Event;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Event eventLog[MAX_DATA]; //an array of structures representing 200 events, once the 200 events have been filled the data will be printed在主“循环()”中,当一个引脚很高时,就会有一个数据收集过程。当偶数发生时,第一个事件数据结构将记录一个时间戳,然后是启动模拟到数字转换并将数据存储在当前事件的数据数组中的过程。
eventLog[i].timeStamp = micros();
for (j=0; j<=SENSORS; ++j) {
lockAndPop(); //lock digital value and reset conversion
selector = inputSelector(selector); //increment the selector pin
PORTA = selector;
digitalWrite(RD, LOW); //Start new conversion
digitalWrite(CLK_INH, LOW); //Start the data transfer
eventLog[i].data[j] = SPI.transfer(0); //read a single byte from the SPI line
digitalWrite(CLK_INH, HIGH); //Inhibit clock
digitalWrite(LD, LOW);
while(digitalRead(INT1)){} //wait for previous conversion to end
}
i++;数据转储函数在两种情况下被调用,第一种情况是发生200个事件时,第二种情况是外部按钮被取消时。此函数将创建一个打印缓冲区,可以对事件数据进行格式化并以十进制值显示。数据值从二进制转换为十进制,而不是ASCII。
void dataDump (){
char buf[100], *pos = buf; //create a buffer of 100 charaters, anda pointer to the begining of that buffer
char *base = buf; //create a base address to reset the buffer
unsigned char eventCount = i; //how many events occured before dump command was called
unsigned char localCount;
unsigned char localData;
Serial.begin(115200);
for (localCount = 0; localCount<=eventCount; ++localCount){
pos += sprintf(pos, "%lu", eventLog[localCount].timeStamp); //sprintf will append the data to the pointer "pos", and return the number of byte append.
for (localData = 0; localData<=SENSORS; ++localData){
pos += sprintf(pos, " %d", (unsigned int)(eventLog[localCount].data[localData]));
}
Serial.println(buf);
pos = base;
}
i=0;
j=0;
Serial.end();
return;我面临的问题是,当调用数据转储函数时,除了数组中的最后一个数据值外,所有内容都打印得很好。以下是打印内容的示例
539580840 171 149 120 152
539581080 170 149 119 216
539581912 170 149 120 196
539582148 170 149 120 180
539582388 170 149 120 168
539582632 170 149 119 148
539582868 170 148 119 128
539583104 170 149 119 216
539583704 170 149 120 196
539583940 170 149 120 176
539584176 170 149 120 160
539584416 170 149 120 148
539584660 170 149 120 128
539584896 170 149 120 112
539585136 170 149 120 92
539585372 170 149 119 80
539585616 170 149 120 60
539585852 170 149 119 59当ADC读取参考电压时,最后的值应该和它前面的三个值一样是常数。这些数据在打印时是完全有效的。
Serial.println(eventLog[i].data[3])主要的“循环()”代码。我尝试过从数据转储函数中运行相同的代码,但是我仍然得到了垃圾。此外,我使用逻辑分析器监视SPI行,并且在数据线上看到了我应该看到的数据。
**我唯一想到的是,当我为200个事件分配内存时,结构的范围并没有扩展到dumpData函数。但这并没有什么意义,因为所有其他的数据都已经存在了。**
发布于 2016-06-17 20:45:46
一开始我没有意识到这一点,但一旦你回答了我的问题,它就像一个疼痛的大拇指一样突出。
如果SENSORS等于3,那么unsigned char data[SENSORS];是一个由三个元素组成的数组。不是你所期望的四个。
数组与基于零的索引(0,1,2,3,.)一起使用然而,当您声明它们时,需要将所需元素的实际计数。
要解决这个问题,我会让SENSORS等于4,然后调整循环,使其从零变为小于SENSORS (不小于或等于)。MAX_DATA也是如此。您的循环使用的元素比实际拥有的多一个。
除非需要索引,否则C++11有一个防止超出数组的功能。这是一个远程循环。
您现在使用的循环:
for (localCount = 0; localCount<=eventCount; ++localCount){
pos += sprintf(pos, "%lu", eventLog[localCount].timeStamp); //sprintf will append the data to the pointer "pos", and return the number of byte append.
for (localData = 0; localData<=SENSORS; ++localData){
pos += sprintf(pos, " %d", (unsigned int)(eventLog[localCount].data[localData]));
}
Serial.println(buf);
pos = base;
}会变成这样:
for( auto &entry : eventLog ){
pos += sprintf(pos, "%lu", entry.timeStamp);
for( char reading : entry.data ){
pos += sprintf(pos, " %d", (unsigned int)reading);
}
Serial.println(buf);
pos = base;
}由于不涉及索引,所以您将始终使用元素的实际数量。远程循环一开始可能会很混乱,但非常有用。
而修复SENSORS和MAX_DATA的使用可能并不能解决所有的问题,不管如何解决,如果您的问题仍然存在,那么我们可以查看其余的问题。如果有更多的问题,请在下面的评论中留下一些信息,我会更新我的答案。
https://stackoverflow.com/questions/37873546
复制相似问题