Обмен данными через serial port

Обмен данными через serial port

Сообщение Userpc1010 » 06 ноя 2017, 20:58

Возникла необходимость продевать данные с компьютера на atmega 2560 и обратно на компьютер в 1м случае данные должны иметь адрес устройства и числовые данные для сервоприводов, принимать на ПК нужно только числовые данные от mems датчиков однако проблемы возникли при реализации части на ПК а именно при приёме любого пакета выскакивают исключения якобы о том что данных в перемененных нет или они равны 0 хотя в мониторе порта Atmega все сообщения отображаются нормально за исключением 1го но байта длины передаваемых данных он не отображается и очень вероятно что записан не правильно или отсутствует код для atmeg'и я использовал из этой статьи поэтому приводить его не буду там он очень подробно разобран. Я постарался сделать ответную часть на основе примера из этой статьи с использованием класса SerialPort если получится её сделать выкину в комментарии под ней может пригодится т.к. рабочего примера протокола обмена данными между ПО VisualStudio и Atmega2560 пока не нашёл. Надеюсь форум ещё не полностью заброшен и кто нибудь поможет разобраться с примером.



Код: Выделить всё
#pragma once
#include <Windows.h>
#include <cstring>
#include <string.h>


namespace Проект2 {

   using namespace System;
   using namespace System::ComponentModel;
   using namespace System::Collections;
   using namespace System::Windows::Forms;
   using namespace System::Data;
   using namespace System::Drawing;
   using namespace System::IO::Ports;

   /// <summary>
   /// Сводка для MyForm
   /// </summary>
   public ref class MyForm : public System::Windows::Forms::Form
   {

      String^ Port;
      int line;
      String^ line2;
      int counter;


      String^ sp_startMarker;           // Переменная, содержащая маркер начала пакета
      String^ sp_stopMarker;             // Переменная, содержащая маркер конца пакета
      String^ sp_dataString;             // Здесь будут храниться принимаемые данные
      int sp_startMarkerStatus;    // Флаг состояния маркера начала пакета
      int sp_stopMarkerStatus;    // Флаг состояния маркера конца пакета
      int sp_dataLength;       // Флаг состояния принимаемых данных
      boolean sp_packetAvailable;    // Флаг завершения приема пакета
      String^ data;
      int bufferChar;





   public:

   private: System::Windows::Forms::Button^  button2;
   private: System::Windows::Forms::Button^  button4;
   private: System::Windows::Forms::ListBox^  listBox1;


   private: System::Windows::Forms::Button^  button3;
   public:



      MyForm(void)
      {
         InitializeComponent();
         //
         //TODO: добавьте код конструктора
         //
      }

   protected:
      /// <summary>
      /// Освободить все используемые ресурсы.
      /// </summary>
      ~MyForm()
      {
         if (components)
         {
            delete components;
         }
      }
   public: System::IO::Ports::SerialPort^  serialPort1;
   private: System::Windows::Forms::TextBox^  textBox1;
   private: System::Windows::Forms::Button^  button1;
   public:
   protected:

   protected:
   private: System::ComponentModel::IContainer^  components;

   private:
      /// <summary>
      /// Требуется переменная конструктора.
      /// </summary>
#pragma region Windows Form Designer generated code
      /// <summary>
      /// Обязательный метод для поддержки конструктора - не изменяйте
      /// содержимое данного метода при помощи редактора кода.
      /// </summary>
      void InitializeComponent(void)
      {
         this->components = (gcnew System::ComponentModel::Container());
         this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
         this->textBox1 = (gcnew System::Windows::Forms::TextBox());
         this->button1 = (gcnew System::Windows::Forms::Button());
         this->button2 = (gcnew System::Windows::Forms::Button());
         this->button3 = (gcnew System::Windows::Forms::Button());
         this->button4 = (gcnew System::Windows::Forms::Button());
         this->listBox1 = (gcnew System::Windows::Forms::ListBox());
         this->SuspendLayout();
         //
         // serialPort1
         //
         this->serialPort1->BaudRate = 115200;
         this->serialPort1->Parity = System::IO::Ports::Parity::Odd;
         this->serialPort1->PortName = L"COM3";
         this->serialPort1->ReadTimeout = 150;
         this->serialPort1->WriteTimeout = 150;
         this->serialPort1->DataReceived += gcnew System::IO::Ports::SerialDataReceivedEventHandler(this, &MyForm::serialPort1_DataReceived);
         //
         // textBox1
         //
         this->textBox1->Location = System::Drawing::Point(2, 9);
         this->textBox1->Name = L"textBox1";
         this->textBox1->Size = System::Drawing::Size(202, 20);
         this->textBox1->TabIndex = 0;
         this->textBox1->Text = L"Номер порта Atmega2560 прим: COM1 ";
         this->textBox1->TextChanged += gcnew System::EventHandler(this, &MyForm::textBox1_TextChanged);
         //
         // button1
         //
         this->button1->Location = System::Drawing::Point(210, 6);
         this->button1->Name = L"button1";
         this->button1->Size = System::Drawing::Size(75, 23);
         this->button1->TabIndex = 1;
         this->button1->Text = L"Определить";
         this->button1->UseVisualStyleBackColor = true;
         this->button1->Click += gcnew System::EventHandler(this, &MyForm::button1_Click);
         //
         // button2
         //
         this->button2->Location = System::Drawing::Point(183, 230);
         this->button2->Name = L"button2";
         this->button2->Size = System::Drawing::Size(98, 23);
         this->button2->TabIndex = 3;
         this->button2->Text = L"Clean";
         this->button2->UseVisualStyleBackColor = true;
         this->button2->Click += gcnew System::EventHandler(this, &MyForm::button2_Click);
         //
         // button3
         //
         this->button3->Location = System::Drawing::Point(2, 230);
         this->button3->Name = L"button3";
         this->button3->Size = System::Drawing::Size(96, 23);
         this->button3->TabIndex = 4;
         this->button3->Text = L"Start";
         this->button3->UseVisualStyleBackColor = true;
         this->button3->Click += gcnew System::EventHandler(this, &MyForm::button3_Click);
         //
         // button4
         //
         this->button4->Location = System::Drawing::Point(104, 230);
         this->button4->Name = L"button4";
         this->button4->Size = System::Drawing::Size(75, 23);
         this->button4->TabIndex = 5;
         this->button4->Text = L"Stop";
         this->button4->UseVisualStyleBackColor = true;
         this->button4->Click += gcnew System::EventHandler(this, &MyForm::button4_Click);
         //
         // listBox1
         //
         this->listBox1->FormattingEnabled = true;
         this->listBox1->Location = System::Drawing::Point(2, 31);
         this->listBox1->Name = L"listBox1";
         this->listBox1->ScrollAlwaysVisible = true;
         this->listBox1->Size = System::Drawing::Size(279, 199);
         this->listBox1->TabIndex = 6;
         this->listBox1->SelectedIndexChanged += gcnew System::EventHandler(this, &MyForm::listBox1_SelectedIndexChanged);
         //
         // MyForm
         //
         this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
         this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
         this->ClientSize = System::Drawing::Size(284, 262);
         this->Controls->Add(this->listBox1);
         this->Controls->Add(this->button4);
         this->Controls->Add(this->button3);
         this->Controls->Add(this->button2);
         this->Controls->Add(this->button1);
         this->Controls->Add(this->textBox1);
         this->Name = L"MyForm";
         this->Text = L"Поключение к плате";
         this->ResumeLayout(false);
         this->PerformLayout();

      }
#pragma endregion
   private: System::Void textBox1_TextChanged(System::Object^  sender, System::EventArgs^  e) {
   }
   private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {

             Port = textBox1->Text;
             MessageBox::Show("Теперь используется: " + Port);


   }
   private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {

             listBox1->Items->Clear();


   }
   private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e) {

             this->serialPort1->Open();
            
             //data = "Start"; //Инициализация
            
            
             //sp_Send(data); //Передача







             //this->serialPort1->Write("77777");  // In the future,  you'll expand on this
             // to write your custom data to the board
             //this->serialPort1->ReadByte();
             //serialPort1->DataReceived;
             //Sleep(100);
             //for ( counter;counter < 10; counter++){


             //line = serialPort1->ReadByte();
             //richTextBox1->Text = "\n" + line.ToString();
             //line = serialPort1->ReadByte();
             //richTextBox1->Text = line.ToString();
             //}

   }
   private: System::Void button4_Click(System::Object^  sender, System::EventArgs^  e) {

             //this->serialPort1->Write("00");
             this->serialPort1->Close();
             counter = 0;
   }
   

         




          void sp_Reset()
          {
             sp_startMarkerStatus = 0;   // Сброс флага маркера начала пакета
             sp_stopMarkerStatus = 0;   // Сброс флага маркера конца пакета
             sp_dataLength = 0;      // Сброс флага принимаемых данных
             sp_packetAvailable = false;   // Сброс флага завершения приема пакета
          }



          void sp_ResetAll()
          {
             this->serialPort1->DiscardInBuffer();      // Обнуляем буфер приема данных
             sp_Reset();         // Частичный сброс протокола
          }

          void sp_SetUp()
          {
             sp_startMarker = "<bspm>";    // Так будет выглядеть маркер начала пакета
             sp_stopMarker = "<espm>";    // Так будет выглядеть маркер конца пакета
             //sp_dataString->reserve(64);    // Резервируем место под прием строки данных
             sp_ResetAll();       // Полный сброс протокола
          }


             public: System::Void serialPort1_DataReceived(System::Object^  sender, System::IO::Ports::SerialDataReceivedEventArgs^  e) {

                       sp_Read();                         // Вызов «читалки» принятых данных
                       //String^ line = serialPort1->ReadLine();
                       //listBox1->Items->Add(line);
                       if (sp_packetAvailable)             // Если после вызова «читалки» пакет полностью принят
                       {
                          ParseCommand();                   // Обрабатываем принятую информацию
                          sp_ResetAll();                    // Полный сброс протокола.
                       }
                      
             }




                    void sp_Read()
                    {

                       for (boolean read = serialPort1->BytesToRead; read;)
                       {
                         
                          bufferChar = serialPort1->ReadByte();                           // Читаем очередной байт из буфера
                         
                          if (sp_startMarkerStatus < sp_startMarker->Length)        // Если стартовый маркер не сформирован (его длинна меньше той, которая должна быть)
                          {
                             if (sp_startMarker[sp_startMarkerStatus] == bufferChar)   // Если очередной байт из буфера совпадает с очередным байтом в маркере
                             {
                                sp_startMarkerStatus++;                                // Увеличиваем счетчик совпавших байт маркера
                             }
                             else
                             {
                                sp_ResetAll();                                         // Если байты не совпали, то это не маркер. Нас нае****, расходимся.
                             }
                          }
                          else
                          {
                             // Стартовый маркер прочитан полностью
                             if (sp_dataLength <= 0)                                 // Если длинна пакета на установлена
                             {
                                sp_dataLength = bufferChar;                          // Значит этот байт содержит длину пакета данных
                             }
                             else                                                    // Если прочитанная из буфера длинна пакета больше нуля
                             {
                                if (sp_dataLength > sp_dataString->Length)            // Если длинна пакета данных меньше той, которая должна быть
                                {
                                   sp_dataString += (char)bufferChar;                  // прибавляем полученный байт к строке пакета
                                }
                                else                                                  // Если с длинной пакета данных все нормально
                                {
                                   if (sp_stopMarkerStatus < sp_stopMarker->Length)    // Если принятая длинна маркера конца пакета меньше фактической
                                   {
                                      if (sp_stopMarker[sp_stopMarkerStatus] == bufferChar)  // Если очередной байт из буфера совпадает с очередным байтом маркера
                                      {
                                         sp_stopMarkerStatus++;                              // Увеличиваем счетчик удачно найденных байт маркера
                                         if (sp_stopMarkerStatus == sp_stopMarker->Length)
                                         {
                                            // Если после прочтения очередного байта маркера, длинна маркера совпала, то сбрасываем все флаги (готовимся к приему нового пакета)
                                            sp_Reset();
                                            sp_packetAvailable = true;                        // и устанавливаем флаг готовности пакета
                                         }
                                      }
                                      else
                                      {
                                         sp_ResetAll();                                      // Иначе это не маркер, а х.з. что. Полный ресет.
                                      }
                                   }
                                   //
                                }
                             }
                          }




                       }

                    }



                    void sp_Send(String^ data)
                    {
                       serialPort1->Write(sp_startMarker);      // Отправляем маркер начала пакета
                       serialPort1->Write(data->Length.ToString());      // Отправляем длину передаваемых данных
                       serialPort1->Write(data);         // Отправляем сами данные
                       serialPort1->Write(sp_stopMarker);      // Отправляем маркер конца пакета
                    }


                    void ParseCommand()
                    {
                       if (sp_dataString == "ver?")    // Если была принята строка «ver?»
                       {

                          String^ versionString;
                          versionString = "Version of serial protocol ";

                          sp_Send(versionString);    // Отправляем на PC содержимое строки «versionString»
                       }

                       if (sp_dataString == "ready")
                       {
                         
                         
                          listBox1->Items->Add(sp_dataString);
                       }



                    }
         
         











private: System::Void listBox1_SelectedIndexChanged(System::Object^  sender, System::EventArgs^  e) {

         


          listBox1->Items->Add(bufferChar);
}
};

}
Userpc1010
 
Сообщения: 5
Зарегистрирован: 01 авг 2017, 19:53

Вернуться в Коммуникации

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron
© 2009-2017 |  О проекте  |  Политика Конфиденциальности  |