непонятно что в com порте

Тема в разделе "Микроконтроллеры AVR", создана пользователем rewan871, 19 окт 2017.

  1. rewan871

    rewan871 Нерд

    Если я правильно понимаю, то чтение в массив по идентификатору ce fa будет происходить так:
    Код (C++):
    char buffer[385];
    for(int i=0;i<385;i++){
       buffer[i]= Serial.read();
       if (i == 1) {
              if(buffer[0]!='ce' && buffer[1]!='fa')
    {
      break;
    }
    }
    }
     
  2. DIYMan

    DIYMan Guest

    Нет, понимаешь неправильно, этот код даже не скомпилируется. Если надо сравнивать байты на 0xCE и 0xFA, то так:
    Код (C++):
    uint8_t buffer[385] = {0};

    int readed = 0;
    bool goodPacket = true;

    while(readed < 385)
    {
        if(!Serial.available())
            continue;
     
        buffer[readed++] = Serial.read();
     
        if(readed == 2 && !(buffer[0] == 0xCE && buffer[1] == 0xFA ) )
        {
            goodPacket = false;
            break;
        }
    }

    if(goodPacket)
    {
        // первые два байта из прочитанных 385 - имеют значение 0xCE 0xFA
    }
     
  3. rewan871

    rewan871 Нерд

    Спасибо большое!

    Я правильно понимаю, что этот код будет принимать данные, записывать их в массив и без изменений передавать на другой com порт?
    Код (C++):
    uint8_t buffer[385] = {0};
    int readed = 0;
    bool goodPacket = true;

    void setup() {
      Serial.begin(115200);
      Serial1.begin(115200);
    }

    void loop() {
    while(readed < 385)
    {
        if(!Serial.available())
            continue;
     
        buffer[readed++] = Serial.read();
     
        if(readed == 2 && !(buffer[0] == 0xCE && buffer[1] == 0xFA ) )
        {
            goodPacket = false;
            readed = 0;
            break;
        }
    }

    if(goodPacket == true && readed == 385)
    {
    Serial1.write(buffer, sizeof ( buffer));
    }

    }
     
  4. DIYMan

    DIYMan Guest

    Чуть-чуть не так - вы не обнуляете readed и не сбрасываете флаг. Так:
    Код (C++):
    uint8_t buffer[385] = {0};
    int readed = 0;
    bool goodPacket = true;

    void setup()
    {
      Serial.begin(115200);
      Serial1.begin(115200);
    }

    void loop()
    {
        while(readed < 385)
        {
            if(!Serial.available())
                continue;

            buffer[readed++] = Serial.read();

            if(readed == 2 && !(buffer[0] == 0xCE && buffer[1] == 0xFA ) )
            {
                goodPacket = false;
                readed = 0;
                break;
            }
        }

        if(!goodPacket)
        {
            return;
        }

        Serial1.write(buffer, sizeof (buffer));
        goodPacket = true;
        readed = 0;

    }
    Если задача просто передавать 385 байт из одного порта в другой, с проверкой, что первые два байта определённые - можно проще, без большого промежуточного буфера:
    Код (C++):
    byte header[2] = {0};
    byte writeCounter = 0;

    typedef enum {
        waitHeader,
        retransmitPacket
    } MachineState;

    MachineState state = waitHeader;

    void setup()
    {
      Serial.begin(115200);
      Serial1.begin(115200);
    }

    void loop()
    {
        if(Serial.available())
        {
            byte b = Serial.read();
         
            switch(state)
            {
                case waitHeader:
                {
                    header[writeCounter++] = b;
                    if(writeCounter == 2)
                    {
                        if(header[0] == 0xCE && header[1] == 0xFA)
                        {
                            Serial1.write(header, sizeof (header));
                            state = retransmitPacket;
                        }
                        else
                        {
                            writeCounter = 0;
                        }
                    }
                }
                break;
             
                case retransmitPacket:
                {
                    Serial1.write(b);
                    writeCounter++;
                 
                    if(writeCounter == 385)
                    {
                        state = waitHeader;
                    }
                }
                break;
            }
        }
    }
    Приведённый код будет читать по 2 байта, пока не прочтёт заголовок, и выпулит его и следующие 383 байта в другой Serial. Навскидку писал, но принцип понятен, надеюсь.
     
    Последнее редактирование модератором: 24 окт 2017
  5. rewan871

    rewan871 Нерд

    Спасибо большое!

    Подскажи пожалуйста еще как делать изменения данных в массиве, например я беру с 3 по 6 байт в массиве, собираю из них long прибавляю единицу, получившийся результат заношу обратно в массив.

    a[2]
    a[3]
    a[4]
    a[5]
     
    Последнее редактирование: 24 окт 2017
  6. brokly

    brokly Гик

    Код который показал DIYMan, может "прозевать" заголовок, я конечно могу ошибаться, ибо глубоко не вникал, но читать заголовок парами - ошибка. Что будет если первый байт заголовка придет в этот конечный автомат вторым ? ;)

    Может так :
    Код (C++):
    void loop() {
        if(Serial.available()) {
            byte b = Serial.read();
            static uint16_t arrow=0; //;)
            if ((arrow==0) && (b==0xCE)) arrow=1;
            else if ((arrow==1) && (b==0xFA)) arrow=2;
            else if (arrow==2) {
               Serial1.write(0xCE);
               Serial1.write(0xFA);
               Serial1.write(b);
               arrow=3;
            } else if (arrow<385) {
               Serial1.write(b);
               arrow++;
            } else arrow=0;
        }
    }
     
    Последнее редактирование: 24 окт 2017
  7. brokly

    brokly Гик

    Дык в первом примере же показано как загнать массив байт в структуру и как обращаться к элементам структуры.
    Код (C++):
        TConvert temp;
     
        //....

        temp.data[i++]=Serial.read(); // грузим массив из ком порта
     
        //....

        temp.Packet2.Body.Param.GGAR.HEIGHT++; //увеличиваем показатель GGA высота на 1 метр
     
    Только если ты потом попытаешься этот пакет передать наружу в том же формате, не забудь пересчитать контрольную сумму, алгоритм в том мануале, в котором описаны структуры данных.

    И да, вам не помешало бы понять, что такое union :)
     
  8. DIYMan

    DIYMan Guest

    Не, не ошибаешься, более того - я знаю об этом ;) Но не буду же я всё-всё за автора доделывать? Там надо, если прочитали 2 байта и заголовок не сходится - декрементить кол-во прочитанных, переносить второй байт на место первого в буфер - и тогда всё будет алё ;) Но было - лень :), в ТЗ таких нюансов не написано, про поиск заголовка в потоке :)

    Если поправить, как описал выше - то код будет ждать следующего пакета.
     
  9. b707

    b707 Гуру

    Для того чтобы прибавить к лонгу единицу, совершенно необязательно брать из массива все 4 байта и "собирать" лонг, достаточно прибавить единицу к младшему байту...
     
  10. brokly

    brokly Гик

    А если в младшем байте 0xFF , ничего не потеряется ?
    Кстати по большому счету никакой "сборки" лонга нет, просто идет обращение к четырем ячейкам памяти как к лонгу. Да и в моем премере не лонг совсем ;) Тут в данных лонг только для даты, так что к нему просто единицу не прибавишь :)
     
    Последнее редактирование: 25 окт 2017
  11. b707

    b707 Гуру

    верятность этого невелика, всего полпроцента :)
     
  12. brokly

    brokly Гик

    Хыыыыы...... Ракета промахнулась на пол процента :) Кстати, а как это подсчитать ? 100/256 вроде получается 0.4 :)
     
  13. b707

    b707 Гуру

    да так и считать... я просто округлил.
     
  14. rewan871

    rewan871 Нерд

    Искал искал про контрольную в гугле контрольную сумму Xor16 (так написано в техническом описании устройства), ничего найти не могу. :(

    Но я думаю она собирается так же, суммой всех байтов.

    считается функцией Array.Sum()?
     
    Последнее редактирование: 25 окт 2017
  15. b707

    b707 Гуру

    Из названия XOR16 очевидно, что используется не простая сумма, а побитное XOR суммирование, и не по байтам (8 бит) - а по словам (16 бит).
    Что такое XOR и как оно считается - полно ссылок в гугле, не знаю, как вы искали.
     
  16. brokly

    brokly Гик

    Ну что же вы так...

    Код (C++):
    typedef struct {
    float UTC;
    float LAT;
    float LAT2;
    float LNG;
    float LNG2;
    float SPEED;
    float COURSE;
    long int DATE;
    float DECLIN;
    } RMC;
    typedef struct {
    float UTC;
    float LAT,LAT2,LNG,LNG2;
    short int QUAL,SNUM;
    float HDOP;
    short int HEIGHT,HDIFF;
    } GGA;

    typedef struct {
    short int CALCMOD;
    short int ID[12];
    float PDOP,HDOP,VDOP;
    } GSA;

    typedef struct {
    short int ID,ELEV,AZIM,SN;
    } INF;

    typedef struct {
    short int VIEW;
    INF AINF[12];
    } GSV;
    typedef struct TParamet{
    unsigned short int Header; //0xFACE
    long int Index;
    short int Flag1;
    long int RawData[19];
    short int Reserved1;
    short int GNSSPacketID;
    long Reserved2;
    RMC RMCR;
    GGA GGAR;
    GSA GSAR;
    GSV GSVR;
    unsigned char VALID_RMC, AUTO_GSA;
    unsigned short Flag2;
    float Pitch;
    float Roll;
    float Heading;
    float MagHeading;
    float LAT;
    float LNG;
    float SPEED;
    float Hout;
    float firm_version;
    float V_up;
    float Hbar;
    float LAT2;
    float LNG2;
    long int NavTime;
    };

    typedef union{
    TParamet Param;
    unsigned short int Data[sizeof(TParamet)/2];
    unsigned char DataB[sizeof(TParamet)];
    } TBody;

    typedef struct{
    TBody Body;
    unsigned short int CheckSum; //16bit XOR
    } TPacket2;

    typedef union{
      TPacket2 Packet2;
      unsigned char Data[sizeof(TPacket2)];
    } TConvert;


    unsigned char test[]={
      0xce , 0xfa , 0x14 , 0xeb , 0x01 , 0x00 , 0x58, 0x02,
      0x08, 0xed, 0x40, 0x00, 0xc7, 0x89, 0x44, 0x00, 0x9c, 0xf3, 0x44, 0x00, 0xc7, 0x4d, 0x0e, 0x00,
      0xb6, 0x05, 0x3f, 0x00, 0x45, 0xd3, 0x3c, 0x00, 0xc7, 0x4d, 0x0e, 0x00, 0x1d, 0x25, 0x67, 0x00,
      0x01, 0x52, 0x40, 0x00, 0x89, 0x1e, 0x3d, 0x00, 0xc7, 0x4d, 0x0e, 0x00, 0x4e, 0x30, 0x05, 0x00,
      0xa5, 0x90, 0x3e, 0x00, 0x6c, 0xc1, 0x3e, 0x00, 0x7b, 0xb0, 0x3e, 0x00, 0xc7, 0x4d, 0x0e, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x46, 0x00, 0x00, 0x6c, 0x42, 0x70, 0x77, 0x0a, 0x3f,
      0x00, 0x00, 0xf0, 0x41, 0xaf, 0x4a, 0xaf, 0x3d, 0xff, 0x6b, 0x93, 0x3d, 0xcd, 0x0c, 0x8e, 0x43,
      0x29, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x46, 0x00, 0x00, 0x6c, 0x42,
      0x70, 0x77, 0x0a, 0x3f, 0x00, 0x00, 0xf0, 0x41, 0xaf, 0x4a, 0xaf, 0x3d, 0x01, 0x00, 0x08, 0x00,
      0x9a, 0x99, 0xd9, 0x3f, 0x5b, 0x00, 0x12, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x1b, 0x00, 0x08, 0x00,
      0x15, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x33, 0x33, 0x53, 0x40, 0x9a, 0x99, 0xd9, 0x3f, 0x33, 0x33, 0x33, 0x40, 0x0d, 0x00,
      0x08, 0x00, 0x38, 0x00, 0x16, 0x01, 0x28, 0x00, 0x0a, 0x00, 0x48, 0x00, 0x95, 0x00, 0x27, 0x00,
      0x12, 0x00, 0x35, 0x00, 0x50, 0x00, 0x22, 0x00, 0x15, 0x00, 0x17, 0x00, 0x67, 0x00, 0x1c, 0x00,
      0x1b, 0x00, 0x3c, 0x00, 0xc7, 0x00, 0x2b, 0x00, 0x45, 0x00, 0x3b, 0x00, 0x40, 0x00, 0x19, 0x00,
      0x46, 0x00, 0x2e, 0x00, 0xb5, 0x00, 0x1c, 0x00, 0x4d, 0x00, 0x15, 0x00, 0x60, 0x01, 0x00, 0x00,
      0x54, 0x00, 0x23, 0x00, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x57, 0x00, 0x0f, 0x01, 0x1f, 0x00,
      0x56, 0x00, 0x1d, 0x00, 0x33, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x01, 0x00, 0x06, 0x01, 0xf1, 0x9c, 0xa6, 0x3f, 0xe4, 0xa2, 0x40, 0xbf, 0x52, 0xc2, 0x8c, 0x43,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x42, 0x4e, 0x7d, 0x0a, 0x3f, 0x00, 0x00, 0xf0, 0x41,
      0xe0, 0x29, 0xaf, 0x3d, 0xfe, 0xff, 0xcf, 0x37, 0xb1, 0x0e, 0xc1, 0x42, 0xa1, 0x4e, 0x02, 0x00,
      0x86, 0xd7, 0x93, 0x3c, 0x24, 0xeb, 0x9f, 0x42, 0xab, 0xea, 0x01, 0x00,
      0x07, 0x10, // <- CS
      0xd1, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xaf,
      0x06, 0x3e, 0x89, 0x73, 0x64, 0x3e, 0xd4, 0x58, 0x1c, 0x41, 0x0c, 0x68
    };

    uint16_t csXor16(uint16_t* buff, uint16_t size){
      uint16_t cs=0;
      for(uint16_t i=0;i<size;i++) cs^=buff[i];
      return cs;
    }

    void setup() {
      Serial.begin(19200);
      TPacket2* pack2= (TPacket2*) test;
      Serial.print("Read CS: ");
      Serial.println(pack2->CheckSum,HEX);
      Serial.print("Calc CS: ");
      Serial.println(csXor16((uint16_t*) &(pack2->Body), sizeof(pack2->Body)/2),HEX);
    }

    void loop() {
    }
     
    Последнее редактирование: 26 окт 2017
  17. rewan871

    rewan871 Нерд

    Таким образом считается?)
    Код (C++):
    uint8_t test[]={ 0xce , 0xfa , 0x14 , 0xeb , 0x01 , 0x00 }


    uint16_t sum1 = ((uint16_t)test[1] << 8) | test[0];
    uint16_t sum2 = ((uint16_t)test[3] << 8) | test[4];
    uint16_t sum3 = ((uint16_t)test[6] << 8) | test[5];

    uint16_t XOR16 = sum1+sum2+sum3;
     
  18. brokly

    brokly Гик

    В принципе гланды можно и через анус автогеном удалить, у вас это получилось :) Только вместо + поставьте вот такую крышечку ^
    Я же вам прям готовый , проверенный пример дал, а вы все пытаетесь себе жизнь усложнить.
     
  19. rewan871

    rewan871 Нерд

    Спасибо! то есть это будет работать?)
    Код (C++):
    uint8_t test[]={ 0xce , 0xfa , 0x14 , 0xeb , 0x01 , 0x00 }


    uint16_t sum1 = ((uint16_t)test[1] << 8) | test[0];
    uint16_t sum2 = ((uint16_t)test[3] << 8) | test[4];
    uint16_t sum3 = ((uint16_t)test[6] << 8) | test[5];

    uint16_t XOR16 = sum1^sum2^sum3;
    мне в начале главное принцип понять, потом все адаптирую)
     
  20. brokly

    brokly Гик