реклама на сайте
подробности

 
 
> Реализация конечного автомата на 8битном контроллере., Около 20 состояний. Хорошие исходники бы посмотреть.
sigmaN
сообщение Jul 9 2017, 10:42
Сообщение #1


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Всем привет!
Сейчас сделано как-то так.
Прекрасно работает, расширяется. Всем доволен, но хотелось бы сравнить с тру 8ми битным подходом. Собственно какую-нибудь хорошую реализацию конечного автомата и хотелось бы где-то посмотреть.
Код
enum DeviceEvents
{
    DEVEV_HEARTBEAT,            //this event occures every ~100ms
    DEVEV_STARTBTN_PRESSED,
    //etc...
    DEVEV_NO_EVENT = 0xff,
}

enum DeviceState_enum
{
    DEVSTATE_OFF,              
    DEVSTATE_LOCKED,
    //etc....
    DEVSTATE_INVALID = 0xff,
}

//state interface class
struct DeviceStateImplementation
{
    virtual void EnterThisStateFrom( const DeviceState_enum &prevState ) = 0;
    //Handles event and returns new device state in response of event
    virtual DeviceState_enum HandleEvent( const DeviceEvents &event ) = 0;
};

//Implementation of DEVSTATE_OFF state
class StateImpl_OFF: public DeviceStateImplementation
{
    timestamp_t MillisecondsCounter;
    uint8_t MinutesCounter;
    bool ReactOnStartBTNRelease;

    void ResetMillisecondsCounter();
public:
    virtual void EnterThisStateFrom( const DeviceState_enum &prevState );
    virtual DeviceState_enum HandleEvent( const DeviceEvents &event );
};

//Implementation of DEVSTATE_OFF state
void StateImpl_OFF::EnterThisStateFrom( const DeviceState_enum &prevState )
{
    TurnOffAllOutputs();
    DisableRPMMeasure();
    G_SettingsStateSelector.ResetPressCounter();
    ReactOnStartBTNRelease = false;
    ResetMillisecondsCounter();
}

void StateImpl_OFF::ResetMillisecondsCounter()
{
    MillisecondsCounter = GetTickCount();
    MinutesCounter = 0;
}

DeviceState_enum StateImpl_OFF::HandleEvent( const DeviceEvents &event )
{
    DeviceState_enum retval = DEVSTATE_OFF;

    switch(event)
    {
    case DEVEV_HEARTBEAT:
        ACC_LEDBlinker.DoTheJob();

        if( G_SettingsStateSelector.GetSelectedState() != DEVSTATE_INVALID )
        {
            ACC_LEDBlinker.StartEndlessBlinkSequence(100, 100);//fast blinking indicating some settings mode was selected
        }
        break;

    case DEVEV_STARTBTN_PRESSED:
        ReactOnStartBTNRelease = true;
        break;

    case DEVEV_STARTBTN_RELEASED:
        //react on release only if press also was made in this state
        if( ReactOnStartBTNRelease )
        {
            ResetMillisecondsCounter();
            if( GlobalVarsRef.BrakePedal.GetButtonState() == GPIOBTNSTATE_PUSHED )
            {
                DeviceState_enum SelectedSettingsModeState = G_SettingsStateSelector.GetSelectedState();
                if( SelectedSettingsModeState != DEVSTATE_INVALID )
                    retval = SelectedSettingsModeState;
                else
                    retval = DEVSTATE_CRANKING;
            }
            else
            {
                retval = DEVSTATE_IGNON;
            }
        }
        break;

    case DEVEV_STARTBTN_LONGPRESS:
        if( GlobalVarsRef.BrakePedal.GetButtonState() == GPIOBTNSTATE_PUSHED )
            retval = DEVSTATE_FORCEDCRANKING;
        else
            retval = DEVSTATE_ACCON;
        break;

    case DEVEV_BREAKPEDAL_PRESSED:
        ResetMillisecondsCounter();
        G_SettingsStateSelector.SelectorWasPressed();

        ACC_LED::Clear();
        ACC_LEDBlinker.StartBlinkSequence(2, 50, 100);
        break;

    case DEVEV_BREAKPEDAL_RELEASED:
        ACC_LED::Clear();
        ACC_LEDBlinker.AbortBlinkSequence();
        break;

    case DEVEV_ENGINE_STARTED:
        retval = DEVSTATE_RUNNING;
        break;

    case DEVEV_ENGINE_STALLED:
        break;
    }

    return retval;
}

/////main state machine implementation
class MainStateMachine
{
public:
    void EnterStateForced( const DeviceState_enum &state );
    void ProcessEvent( const DeviceEvents &evnt );

private:
    DeviceStateImplementation *CurrentDevStateImplementation; //<----pointer to state interface class
    DeviceState_enum CurrentDevState;

    void SetNewDeviceState( const DeviceState_enum &newDevState );
};

void MainStateMachine::ProcessEvent( const DeviceEvents &evnt )
{
    DeviceState_enum newDevState = CurrentDevStateImplementation->HandleEvent( evnt );
    if( newDevState != CurrentDevState )
        SetNewDeviceState( newDevState );
}

void MainStateMachine::SetNewDeviceState( const DeviceState_enum &newDevState )
{
    switch( newDevState )
    {

    case DEVSTATE_OFF:
        CurrentDevStateImplementation = &OFFState;
        break;
    case DEVSTATE_LOCKED:
        CurrentDevStateImplementation = &LockedState;
        break;
    }
    CurrentDevStateImplementation->EnterThisStateFrom( CurrentDevState );
    CurrentDevState = newDevState;
}


//main loop simplifiyed
int main()
{
    while(1)
    {
        event = DEVEV_HEARTBEAT;
        while( event != DEVEV_NO_EVENT )
        {
            MainStateMachine.ProcessEvent( event );
            event = DetectOneMoreEvents();
        }
    }
}




--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
pokk
сообщение Jul 11 2017, 06:38
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 3-07-11
Пользователь №: 66 028



Dog Pawlowa, можно тоже исходники глянуть? m65535625@gmail.com

А то как не крути вечно такой колхоз получается
(Передача пакета данных по usart)
CODE
void Sendpackage(void){
static uint8_t mode;
static uint16_t counter;
uint8_t* Data;
switch(mode){
case 0:{
//---------------------------------------------
//--------Ожидание команды на отправку---------
//---------------------------------------------
if(TransmitDataStart==Transmit_START){
TransmitDataStart=Transmit_STOP;
Data=&Protocol;
mode=1;
}
break;
}
//-------------------------------------------------
case 1:{
if(counter<sizeof(ProtocolExchange_t)){
if(USART3->SR & USART_SR_TC){
USART3->DR =(uint8_t)Data[counter];
counter++;
}
}else{
mode=0;
}
break;
}
//-------------------------------------------------
}
}

Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jul 11 2017, 20:24
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(pokk @ Jul 11 2017, 09:38) *
А то как не крути вечно такой колхоз получается

Что касается такого колхоза, то этого хватает у каждого.
И вообще это не колхоз, это классика - см ниже! wink.gif
Если речь идет о автоматах, кроющих практически всю функциональность устройства, то тут все становится сложнее, потому что не есть проблема реализовать это все, а проблемой является выбор собственного стиля и подхода, чтобы было все понятно и прозрачно в первую очередь для самого себя.

CODE

#define TRANSPORT_TIMEOUT_SERIAL_SEC 10
#define TRANSPORT_TIMEOUT_TCPIP_SEC 5
#define LONG_RUN_TIMEOUT_SEC 60
#define AUTO_PICKUP_TIME_MS 500
#define NUM_RETRIES 3

// added by me timeouts:
#define RECEIVE_TIMEOUT_MS 1000
#define ANSWER_TIMEOUT_MS 100









enum {
errNO=0,
errMESSAGE_SIZE,
errOP_CODE,
errRECORDS_QTY,
errINDEX1,
errINDEX2,
errINDEX3,
errNOT_SUPPORTED,
errREAD_ONLY,
errWRONG_SIZE,
errWRITE_ONLY,
errWRONG_OPCODE,
errSIZE,
};


#define RECEIVED_MESSAGE_LENGTH ((int)com1.rx_buf[1]+((int)com1.rx_buf[2])<<8)
#define RECEIVED_TYPE (com1.rx_buf[3])
#define RECEIVED_SEQUENCE (com1.rx_buf[4])
#define ctrlRECEIVED (com1.rx_buf[5])
#define ctrlACK ('A')
#define ctrlNAK ('N')
#define ctrlEND ('E')
#define ctrlWAIT ('W')
#define ctrlPICKUP ('P')
#define ctrlDROP ('D')
#define XML_PTR_FIRST (char*)(com1.rx_buf+5)
#define XML_PTR_LAST (com1.rx_buf+RECEIVED_MESSAGE_LENGTH-4)
#define ETX_INDEX (RECEIVED_MESSAGE_LENGTH-3)

/*
Control message
1 byte STX StartMessage
2 byte Unsigned Binary Length Length of the entire message; including StartMessage and EndMessage but excluding CRC bytes
1 byte ASCII Type 'C'
1 byte Unsigned Binary Sequence 0x00 is invalid value
1 byte ASCII ControlFunction 'A' ACK
'N' NAK
'E' End Sequence
'W' Wait
'P' Pickup
'D' Drop Link
1 byte ETX EndMessage
2 byte Binary CRC See CRC Calculation


Payload message
1 byte STX StartMessage
2 byte UnsignedBinary Length Length of the entire message; including StartMessage and EndMessage but excluding CRC bytes
1 byte ASCII Type 'P'
1 byte Unsigned Binary Sequence 0x00 is invalid value
Variable Unsigned Binary Payload The transported application protocol message
1 byte ETX EndMessage
2 byte Unsigned Binary CRC See CRC Calculation

*/

#define XML_START_OFFSET 5
#define XML_END_OFFSET 2

char payload_sent_wait_control;
char payload_sent_time;
char payload_sent_qty;





void PrepareTransportPayloadHeader(void)
{ com1.tx_head=com1.tx_buf;
*com1.tx_head++=STX;
com1.tx_head+=2; // pass length
*com1.tx_head++='P'; // payload type
*com1.tx_head++=RECEIVED_SEQUENCE;
}

void PrepareTransportControlMessage(char com)
{
int my_checksum;

com1.tx_head=com1.tx_buf;
*com1.tx_head++=STX;
*com1.tx_head++=7; // length = 7
*com1.tx_head++=0;
*com1.tx_head++='C'; // control type
*com1.tx_head++=RECEIVED_SEQUENCE;
*com1.tx_head++=com;
*com1.tx_head++=ETX;
my_checksum=crc16_ccitt(com1.tx_buf, 7);
*com1.tx_head++=(char)(my_checksum&0x00ff);
*com1.tx_head++=(char)(my_checksum>>8);
}

void PrepareTransportTrailer(void)
{
int my_size;
int my_checksum;

*com1.tx_head++=ETX;
my_size=com1.tx_head- com1.tx_buf;
com1.tx_buf[1]=(char)(my_size&0x00ff);
com1.tx_buf[2]=(char)(my_size>>8);
my_checksum=crc16_ccitt(com1.tx_buf, my_size);
*com1.tx_head++=(char)(my_checksum&0x00ff);
*com1.tx_head++=(char)(my_checksum>>8);

}




enum { UNCONFIGURED,
RESTART_RX,
WAITING_STX,
WAITING_ETX,
WAITING_BCC1,
WAITING_BCC2,
ANALYSE_MESSAGE,
PREPARE_MESSAGE,
START_SEND_MESSAGE,
WAITING_START_TRANSMIT,
WAITING_END_TRANSMIT,
FINAL,
PREPARE_NAK,
PREPARE_DROP,
PREPARE_END };

char transport_error;

#define USE_TIMEOUT 1

u16 TimeoutRunning(void)
{
#ifdef USE_TIMEOUT
return com1.timeout;
#else
return 1;
#endif
}


void fRnt(void)
{

static u16 my_checksum;
static u16 message_checksum;


switch (pstate)
{ case UNCONFIGURED:
Com1Init();
pstate++;
break;

case RESTART_RX:
Com1SetReceive(COM1_WAIT_STX);
prot_error=errNO;
pstate++;
OFF_LED5();
OFF_LED4();

break;

case WAITING_STX:
if ( payload_sent_wait_control )
{ if (payload_sent_qty<2)
{ if (event==evSec)
{ if (payload_sent_time<10)
payload_sent_time++;
else
{ pstate=START_SEND_MESSAGE;
payload_sent_qty++;
payload_sent_time=0;
}
}
}
else // all attempts done
payload_sent_wait_control=0;
}
else
{ payload_sent_qty=0;
payload_sent_time=0;
}


switch (com1.rx_status)
{ case COM1_RECEIVED:
pstate=RESTART_RX; // buffer is over
break;

case COM1_RECEIVING_:
pstate=WAITING_ETX;
com1.timeout=RECEIVE_TIMEOUT_MS;
break;
}
break;

case WAITING_ETX:
ON_LED4(); // recieving starts
if (TimeoutRunning())
{ if (com1.rx_head>com1.rx_tail)
{ switch (*com1.rx_tail)
{
case ETX:
// case EOT:
com1.rx_tail++;
if (com1.rx_tail>com1.rx_buf+5)
pstate++;
break;

default:
com1.rx_tail++;
break;
}
}
}
else
pstate=RESTART_RX;
break;

case WAITING_BCC1:
if (TimeoutRunning())
{ if (com1.rx_head>com1.rx_tail)
{ com1.rx_tail++;
pstate++;
}
}
else
pstate=RESTART_RX;
break;

case WAITING_BCC2:

if (TimeoutRunning())
{ if (com1.rx_head>com1.rx_tail)
{ com1.rx_tail++;
pstate++;
Com1SetReceive(COM1_PASSIVE);
}
}
else
pstate=RESTART_RX;
break;


case ANALYSE_MESSAGE:
OFF_LED4();
if (com1.rx_head<com1.rx_buf+8) // too short message
{ pstate=RESTART_RX;
break;
}
my_checksum=crc16_ccitt(com1.rx_buf, com1.rx_tail-com1.rx_buf-2);
message_checksum= ( ((unsigned int)*(com1.rx_head-2)) ) |
( ((unsigned int)*(com1.rx_head-1))<<8 );

#if (defined IGNORE_CHECKSUM)

#elif (defined USE_CHECKSUM)
if ( (my_checksum!=message_checksum) || // wrong checksum
(*(com1.rx_head-3) !=ETX) //not ETX
)
{ pstate=RESTART_RX;
break;
}
#else
#error "What to do with checksum?"
#endif



switch (RECEIVED_TYPE)
{ case 'C': // control message
switch (ctrlRECEIVED)
{ case ctrlEND:
pstate=PREPARE_END;
break;
case ctrlDROP:
pstate=PREPARE_DROP;
break;

default:
pstate=RESTART_RX;
break;
}
break;

case 'P': //
if (!AnalyseXmlOk(XML_PTR_FIRST,(char*)com1.rx_head-4))
pstate=PREPARE_NAK;
else
pstate=PREPARE_MESSAGE;
break;

}
break;

case PREPARE_MESSAGE:
ON_LED5(); // answering started
com1.tx_head=com1.tx_buf;
PrepareTransportPayloadHeader();
PrepareXml();
PrepareTransportTrailer();
pstate++;
payload_sent_wait_control=1;
payload_sent_time=0;
break;

case START_SEND_MESSAGE:
SET_TRANSMIT(); // for driver
pstate++;
com1.timeout=ANSWER_TIMEOUT_MS;
break;


case WAITING_START_TRANSMIT:
if (!com1.timeout)
{ Com1SetTransmit(COM1_TRANSMITTING);
pstate++;
}
break;

case WAITING_END_TRANSMIT:
if (com1.tx_status==COM1_TRANSMITTED)
if (TRANSMIT_OVER())
{ com1.timeout=0;
pstate++;
}
break;

case FINAL:
OFF_LED5();
pstate=RESTART_RX;
break;


case PREPARE_NAK:
pstate = UNCONFIGURED;
break;

case PREPARE_DROP: //0207004300440389AC
ON_LED5();
PrepareTransportControlMessage('D');
com1.timeout=ANSWER_TIMEOUT_MS;
SET_TRANSMIT();
pstate=WAITING_START_TRANSMIT;
break;

case PREPARE_END:
ON_LED5();
PrepareTransportControlMessage('E');
com1.timeout=ANSWER_TIMEOUT_MS;
SET_TRANSMIT();
pstate=WAITING_START_TRANSMIT;
payload_sent_wait_control=0;
break;

default:
pstate = UNCONFIGURED;
break;
}
}


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- sigmaN   Реализация конечного автомата на 8битном контроллере.   Jul 9 2017, 10:42
- - iosifk   Цитата(sigmaN @ Jul 9 2017, 13:42) Всем д...   Jul 9 2017, 12:50
- - sigmaN   iosifk, спасибо, кажется нашел пдфку с которой сто...   Jul 9 2017, 16:33
|- - iosifk   Цитата(sigmaN @ Jul 9 2017, 19:33) iosifk...   Jul 9 2017, 18:59
|- - XVR   Цитата(sigmaN @ Jul 9 2017, 19:33) iosifk...   Jul 10 2017, 10:30
|- - Dog Pawlowa   Цитата(XVR @ Jul 10 2017, 13:30) либо в в...   Jul 10 2017, 12:37
- - Dog Pawlowa   Цитата(sigmaN @ Jul 9 2017, 13:42) Всем д...   Jul 10 2017, 07:37
- - sigmaN   Биты при том, что при моей нынешней реализации(кот...   Jul 10 2017, 07:53
|- - Dog Pawlowa   Цитата(sigmaN @ Jul 10 2017, 10:53) Биты ...   Jul 10 2017, 09:09
- - sigmaN   Спасибо, будет интересно посмотреть! altersoft...   Jul 10 2017, 09:21
- - sigmaN   ЦитатаЧто касается автоматов на МК с минимумум рес...   Jul 10 2017, 10:56
- - sigmaN   Вот дойдут как-нибудь руки до сравнений и будет ин...   Jul 10 2017, 23:02
|- - k155la3   Цитата(sigmaN @ Jul 11 2017, 02:02) . . ....   Jul 11 2017, 06:33
- - sigmaN   ЦитатаСмотря как компилятором реализуется работа v...   Jul 11 2017, 10:02
|- - jcxz   Цитата(sigmaN @ Jul 11 2017, 13:02) Error...   Jul 11 2017, 10:46
|- - k155la3   Цитата(sigmaN @ Jul 11 2017, 13:02) Error...   Jul 11 2017, 10:52
|- - jcxz   Цитата(k155la3 @ Jul 11 2017, 13:52) Есть...   Jul 11 2017, 11:08
- - sigmaN   С этим разобрались, осталось провести эксперименты...   Jul 11 2017, 11:47
|- - Lerk   Цитата(sigmaN @ Jul 11 2017, 14:47) Честн...   Jul 11 2017, 12:40
- - sigmaN   Видел. Там даже мой лайк имеется под этим видео ))...   Jul 11 2017, 13:15
- - 501-q   https://www.state-machine.com/ https://state-machi...   Jul 25 2017, 05:57


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 3rd August 2025 - 08:30
Рейтинг@Mail.ru


Страница сгенерированна за 0.01436 секунд с 7
ELECTRONIX ©2004-2016