gpt4 book ai didi

c++ - 状态机问题

转载 作者:行者123 更新时间:2023-11-28 07:32:48 24 4
gpt4 key购买 nike

我在使用状态机设置时遇到问题。我知道这些,所以我遇到了问题。所以这里有些方法可以忽略。主要问题是出于某种原因,它会为接收到的每个字节发送一条消息,但我认为 Serial.read() 会在读取后清除缓冲区。所以这里是大部分代码:

#include "Arduino_Structures.h"
#include <SPI.h>
#include <Ethernet.h>
#include "Time.h"

//GLOBAL DECLARATIONS
enum { STANDBY, SEND, RECEIVE, PROCESS} state = SEND;
enum { STATUS, CONFIG, CURRENT, TIME, VOLTAGE} messageType = STATUS;

char lcv;
char lcv2; //loop control variables

MESSAGE_STRUCT outgoing; //changing outgoing message
MESSAGE_STRUCT incoming; //changing incoming message
OODLES_BLOCK oodles; //oodles of information from the following 5 blocks
STATUS_BLOCK temp_status; //temporary status block
CONFIG_BLOCK temp_config; //temporary config block
CURRENT_BLOCK temp_current; //temporary current block
TIME_BLOCK temp_time; //temporary time block
VOLTAGE_BLOCK temp_voltage; //temporary voltage block


//FUNCATION DECLARATIONS
void sendMsg(MESSAGE_STRUCT* outgoing);
void receiveMsg(MESSAGE_STRUCT* incoming);

//ARDUINO SETUP
void setup()
{
delay(TIMEOUT); //wait for the boards to start up
Serial.begin(BAUD); //set the arduino to be at the Micro-AT baud rate
do
{
lcv = Ethernet.begin(mac); //start etherent board, get IP
}while(!lcv);

}

//ARDUINO LOOP
void loop()
{
switch(state)
{
case STANDBY:
delay(1000);
state = SEND;
break;

case SEND:

switch(messageType)
{
case STATUS:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_STATUS;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

case CONFIG:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_CONFIG;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

case CURRENT:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_CURRENT;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

case TIME:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_TIME;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

case VOLTAGE:
outgoing.start_byte = 0x00;
outgoing.length = 0x00;
outgoing.address_1 = 0xFF;
outgoing.address_2 = 0xFF;
outgoing.code_word = REQUEST_VOLTAGE;
outgoing.checksum = 0;

sendMsg(&outgoing);
state = RECEIVE;
break;

default:
break;
}
break;
case RECEIVE:
if(Serial.available())
{
state = SEND;
receiveMsg(&incoming);
//NEED TO CHECK TO MAKE SURRE START BYTE AND ADDRESS ARE CORRECT
//ALSO THIS IS WHERE I SHOULD CHECK THE CHECKSUM
//ONCE INSIDE SWITCHES NEED TO MAKE SURE THE RESPONSE IS CORRECT
switch(messageType)
{
case STATUS:
//copy information from incoming's data array to the temp_status block so that it retains its structure
memcpy(&temp_status, &incoming.data, sizeof(STATUS_BLOCK));

//these are directly taken from the status block information (Arduino_Structures.h)
oodles.left_source = temp_status.left_source;
oodles.right_source = temp_status.right_source;
oodles.left_overcurrent = temp_status.left_overcurrent;
oodles.right_overcurrent = temp_status.right_overcurrent;
oodles.automatic_transfer = temp_status.ready;
oodles.event_led = temp_status.event;
oodles.bus_type = temp_status.bus_type;
oodles.preferred = temp_status.preferred;
oodles.lockout_installed = temp_status.lockout_installed;
oodles.supervisory_control = temp_status.supervisory_control;

//put the time into the TimeElement then convert it to unix time
TimeElements timeInfo; //will be used (from Time.h library)
timeInfo.Year = temp_status.year;
timeInfo.Month = temp_status.month;
timeInfo.Day = temp_status.day;
timeInfo.Hour = temp_status.hour;
timeInfo.Minute = temp_status.minute;
timeInfo.Second = temp_status.second;
oodles.unix_time = makeTime(timeInfo);

//might want to wipe incoming and outogoing messages to make sure they get correctly rewritten
//messageType = CONFIG;
//state = SEND;
break;

case CONFIG:
break;

case CURRENT:
break;

case TIME:
break;

case VOLTAGE:
break;
}
}
break;

case PROCESS:
break;
}
}

void sendMsg(MESSAGE_STRUCT* message)
{
//brake up integers from MESSAGE_STRUCT to bytes (see intByte in Arduino_Structures.h)

intByte code_word, checksum;

code_word.intValue = message->code_word;
checksum.intValue = message->checksum;

//send byte by byte
Serial.write(message->start_byte);
Serial.write(message->length);
Serial.write(message->address_1);
Serial.write(message->address_2);
Serial.write(code_word.byte1);
Serial.write(code_word.byte2);

for(lcv = 0; lcv < message->length; lcv++)
Serial.write(message->data[lcv]);

Serial.write(checksum.byte1);
Serial.write(checksum.byte2);
}

void receiveMsg(MESSAGE_STRUCT* message)
{
//receive bytes and put them back as integers (see intByte in Arduino_Structures.h)
intByte code_word, checksum;

//receive byte by byte
message->start_byte = Serial.read();
message->length = Serial.read();
message->address_1 = Serial.read();
message->address_2 = Serial.read();
code_word.byte1 = Serial.read();
code_word.byte2 = Serial.read();
message->code_word = code_word.intValue;

for(lcv = 0; lcv < message->length; lcv++)
message->data[lcv] = Serial.read();

checksum.byte1 = Serial.read();
checksum.byte2 = Serial.read();
message->checksum = checksum.intValue;
}

这是显示错误的串行监视器,它应该只响应一次,如果我只发送一个字节它会响应一次。如果我向它发送一个如下所示的 8 字节响应,它会响应 8 次(“Answer”表示 arduino 到笔记本电脑,“request”表示笔记本电脑到 arduino):

Answer: 6/26/2013 4:30:59 PM.56364 (+11.3133 seconds)

00 00 FF FF 00 01 00 00

Request: 6/26/2013 4:31:00 PM.48564 (+0.9219 seconds)

00 00 FF FF 01 01 00 00

Answer: 6/26/2013 4:31:00 PM.51664 (+0.0156 seconds)

00 00 FF FF 00 01 00 00 00 00 FF FF 00 01 00 00
00 00 FF FF 00 01 00 00 00 00 FF FF 00 01 00 00
00 00 FF FF 00 01 00 00 00 00 FF FF 00 01 00 00
00 00 FF FF 00 01 00 00 00 00 FF FF 00 01 00 00

最佳答案

看起来您正在检查 Serial.available() 是否不为零,然后读取了一堆数据。可能是因为您在开始 receiveMsg 函数时还没有接收到数据。你应该:

  1. 检查以确保您需要的字节可用 等待
  2. 它们不可用,但您希望它们很快就会出现

举个例子:

void receiveMsg(MESSAGE_STRUCT* message)
{
// receive bytes and put them back as integers
intByte code_word, checksum;

// receive byte by byte, wait for it if need be
while( Serial.available() < 1 ) {delay(10);}
message->start_byte = Serial.read();
while( Serial.available() < 1 ) {delay(10);}
message->length = Serial.read();

有更好、更稳健的方法来做到这一点,但对于查看输入缓冲区是否未被填满的测试来说,这是非常简单和容易实现的。

关于c++ - 状态机问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17330991/

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