Уважаемые знатоки, HELP!!!Arduino+Visual C++2010 Чтение COM-порта непрерывно!!!

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Друзья!!!Имею простенький рабочий код для дальномера на основе HC-SR04 (использую этот вариант для отладки) Ардуино моя подключена на COM2

 

#define Trig 8
#define Echo 9


void setup() 
{  
  pinMode(Trig, OUTPUT); //инициируем как выход 
  pinMode(Echo, INPUT); //инициируем как вход 
  Serial.begin(9600); 
  /* задаем скорость общения. В нашем случае с компьютером */
} 
unsigned int impulseTime=0; 
unsigned int distance_sm=0; 

void loop() 
{  
  digitalWrite(Trig, HIGH); 
  /* Подаем импульс на вход trig дальномера */
  delayMicroseconds(10); // равный 10 микросекундам 
  digitalWrite(Trig, LOW); // Отключаем 
  impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса 
  distance_sm=impulseTime/58; // Пересчитываем в сантиметры 
  Serial.println(distance_sm); // Выводим на порт, далее на VC++2010
  delay(100);
  
  }

Далее простенький код , написанный в Visual Studio C++ 2010 Windows Forms

#pragma once

namespace ultrazvuk {

	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>
	/// Summary for Form1
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			InitializeComponent();
			//
			//TODO: Add the constructor code here
			//
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::Button^  button1;
	protected: 
	private: System::Windows::Forms::Button^  button2;
	private: System::Windows::Forms::Label^  label1;
	private: System::IO::Ports::SerialPort^  serialPort1;
	private: System::Windows::Forms::Button^  button3;
	private: System::ComponentModel::IContainer^  components;

	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>


#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->components = (gcnew System::ComponentModel::Container());
			this->button1 = (gcnew System::Windows::Forms::Button());
			this->button2 = (gcnew System::Windows::Forms::Button());
			this->label1 = (gcnew System::Windows::Forms::Label());
			this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
			this->button3 = (gcnew System::Windows::Forms::Button());
			this->SuspendLayout();
			// 
			// button1
			// 
			this->button1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(204)));
			this->button1->Location = System::Drawing::Point(166, 46);
			this->button1->Name = L"button1";
			this->button1->Size = System::Drawing::Size(100, 49);
			this->button1->TabIndex = 0;
			this->button1->Text = L"Открыть порт";
			this->button1->UseVisualStyleBackColor = true;
			this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
			// 
			// button2
			// 
			this->button2->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(204)));
			this->button2->Location = System::Drawing::Point(166, 116);
			this->button2->Name = L"button2";
			this->button2->Size = System::Drawing::Size(100, 45);
			this->button2->TabIndex = 1;
			this->button2->Text = L"Закрыть порт";
			this->button2->UseVisualStyleBackColor = true;
			this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click);
			// 
			// label1
			// 
			this->label1->AutoSize = true;
			this->label1->Location = System::Drawing::Point(43, 82);
			this->label1->Name = L"label1";
			this->label1->Size = System::Drawing::Size(35, 13);
			this->label1->TabIndex = 2;
			this->label1->Text = L"label1";
			// 
			// button3
			// 
			this->button3->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(204)));
			this->button3->Location = System::Drawing::Point(166, 184);
			this->button3->Name = L"button3";
			this->button3->Size = System::Drawing::Size(100, 42);
			this->button3->TabIndex = 3;
			this->button3->Text = L"Считать данные";
			this->button3->UseVisualStyleBackColor = true;
			this->button3->Click += gcnew System::EventHandler(this, &Form1::button3_Click);
			// 
			// Form1
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(292, 266);
			this->Controls->Add(this->button3);
			this->Controls->Add(this->label1);
			this->Controls->Add(this->button2);
			this->Controls->Add(this->button1);
			this->Name = L"Form1";
			this->Text = L"Form1";
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion
	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
				 if(!this->serialPort1->IsOpen)  //открываем порт
                     { 
                         this->serialPort1->PortName="COM2"; //у меня ардуино подключен к COM2
                         this->serialPort1->BaudRate=Int32::Parse("9600"); //скорость подключения
                          this->serialPort1->Open(); 
                         this->button1->Enabled = false; 
                            this->button2->Enabled = true;
				      } 
			 }
	private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
				         this->serialPort1->Close();  //закрываем порт
                         this->button1->Enabled = true; 
                         this->button2->Enabled = false;
			 }
			 
			 
private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e) {
			  this->label1->Text=this->serialPort1->ReadLine();  //читаем данные ультразвукового датчика и выводим их на метку
		 }
};
}
 Проблема собственно в непрерывном чтении COM-порта в виндовс программе. Работает только по нажатию кнопки (по событию если быть точным), выводятся данные датчика от ардуино в метку. А мне оооооооочень нужно считывать данные непрерывно в реальном времени.

Проблем с управлением например соленоидами подачи воды и прочей периферией с виндовс программы через ардуино не возникает, а вот с чтением ком порта просто тупик. Перелопатил кучу форумов,в том числе и англоязычных, но способ реализовать задачу так и не нашел(возможно в силу своей неопытности). Поэтому прошу помочь умельцев (как последнюю инстанцию) объяснить как считывать порт в реальном времени.

 

maksim
Offline
Зарегистрирован: 12.02.2012

Вам не кажется что вы ошиблись форумом?

       string DataRecived = null;

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            DataRecived = serialPort1.ReadLine();
            this.Invoke(new EventHandler(TextOut));
        }

        private void TextOut(object sender, EventArgs e)
        {
            textBox1.Text = DataRecived;
        }

 

Клапауций
Offline
Зарегистрирован: 10.02.2013

maksim пишет:

Вам не кажется что вы ошиблись форумом?

Это уже как минимум второй сумасшедший программист, который без проблем читает показания датчиков из дуино в винду, но не может прочитаь компорт.

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Форумом безусловно ошибся!!!Но ошибся сознательно!!!Как показывает практика, когда требуется связать Arduino и Visual C++ именно здешние спецы компетентны и оказывают хорошую помощь (за что ИМ огромное спасибо!!!).

По поводу "второй сумасшедший программист" повеселило)))))))))Ситуация действительно глупая!!!Да получается через ком порт посылать команды на Ардуино ,а ею управлять всевозможными  КИПовскими примочками,но вот читать непрерывно порт не выходит!( Так как сам не программист,а КИПовец,но нынешняя задача требует от меня связать это воедино!

maksim ,огромное спасибо Вам за помощь!!! Но в силу малых знаний в данной сфере все утро сегодня пытаюсь связать свой код с Вашим комментарием!Делаю кучу ошибок( Если Вас не затруднит, опишите подробнее как мне скомпоновать мой кодик с Вашим!!!Пока мониторил интернет по данной проблеме, находил посты ребят с такой же проблемой,а благодаря Вам здесь многие смогут найти ответ!!!

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

Вы просто некомпетентны в программировании вообще. Читать компорт можно как по таймеру так и по событию наличия данных. А вы даже в гугле набрать "Visual c++ serial port recive data event" поленились. http://msdn.microsoft.com/ru-ru/library/system.io.ports.serialport.datareceived.aspx

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

NeiroN, по поводу некомпетентности , меня это не обижает, так так и есть!А по поводу лени позвольте!!!!!!!!!!!!!!!!!Знаю что ком порт нужно читать отдельным потоком(и именно в нем читать порт), а главный поток должен заниматься всем остальным!Иначе прога попросту зависает(это и неудивительно)так как программа занимается помимо порта еще и прорисовкой и событиями обьектов и так далее!!!!!!!!Пробовал и таймер и цикл while и через BackgroundWorker!!!Поэтому за некомпетентность + ,а за лень -!!!!!!

Но эта полемика проблему не отменяет,а посему если можете растолковать что к чему, будуочень благодарен!!!

maksim
Offline
Зарегистрирован: 12.02.2012

Так в чем проблема то ??? Что не получается??? 

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Если я правильно понял, то я должен читать ком порт только по событию!Событием является поступление данных(если что то пришло то только тогда читать данные и прога не будет виснуть) А вот прописать в своем коде правильно обработку этого события не удаетсяне удается.

У меня был написан такой бред, когда нажимаем кнопку button3 то считываем данные с порта 

private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e) {
	              this->label1->Text=this->serialPort1->ReadLine();  //читаем данные ультразвукового датчика и выводим их на метку
	         }
	

А как прописать через DataReceived ?

leshak
Offline
Зарегистрирован: 29.09.2011

DeN-iZ пишет:

 

А как прописать через DataReceived ?

Ну дык вам же ссылочку выше дали, вы ее смотрели? Вы не поверите но там пример именно на DataReceived.

Да вообщем-то и код Максима тоже через DataReceived. Только не на C++, а на C#. Но смысл у них все равно идентичный. Только синтаксис подправить под C++.

DeN-iZ
Offline
Зарегистрирован: 04.04.2013
#pragma once

namespace ultrazvuk {

	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>
	/// Summary for Form1
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			InitializeComponent();
			//
			//TODO: Add the constructor code here
			//
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::Button^  button1;
	protected: 
	private: System::Windows::Forms::Button^  button2;
	private: System::Windows::Forms::Label^  label1;
	private: System::IO::Ports::SerialPort^  serialPort1;
	private: System::Windows::Forms::Button^  button3;
	private: System::Windows::Forms::TextBox^  textBox1;
	private: System::ComponentModel::IContainer^  components;

	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>


#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->components = (gcnew System::ComponentModel::Container());
			this->button1 = (gcnew System::Windows::Forms::Button());
			this->button2 = (gcnew System::Windows::Forms::Button());
			this->label1 = (gcnew System::Windows::Forms::Label());
			this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
			this->button3 = (gcnew System::Windows::Forms::Button());
			this->textBox1 = (gcnew System::Windows::Forms::TextBox());
			this->SuspendLayout();
			// 
			// button1
			// 
			this->button1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(204)));
			this->button1->Location = System::Drawing::Point(166, 46);
			this->button1->Name = L"button1";
			this->button1->Size = System::Drawing::Size(100, 49);
			this->button1->TabIndex = 0;
			this->button1->Text = L"Открыть порт";
			this->button1->UseVisualStyleBackColor = true;
			this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
			// 
			// button2
			// 
			this->button2->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(204)));
			this->button2->Location = System::Drawing::Point(166, 116);
			this->button2->Name = L"button2";
			this->button2->Size = System::Drawing::Size(100, 45);
			this->button2->TabIndex = 1;
			this->button2->Text = L"Закрыть порт";
			this->button2->UseVisualStyleBackColor = true;
			this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click);
			// 
			// label1
			// 
			this->label1->AutoSize = true;
			this->label1->Location = System::Drawing::Point(43, 82);
			this->label1->Name = L"label1";
			this->label1->Size = System::Drawing::Size(35, 13);
			this->label1->TabIndex = 2;
			this->label1->Text = L"label1";
			// 
			// serialPort1
			// 
			this->serialPort1->DataReceived += gcnew System::IO::Ports::SerialDataReceivedEventHandler(this, &Form1::serialPort1_DataReceived);
			// 
			// button3
			// 
			this->button3->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 8.25F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(204)));
			this->button3->Location = System::Drawing::Point(166, 184);
			this->button3->Name = L"button3";
			this->button3->Size = System::Drawing::Size(100, 42);
			this->button3->TabIndex = 3;
			this->button3->Text = L"Считать данные";
			this->button3->UseVisualStyleBackColor = true;
			this->button3->Click += gcnew System::EventHandler(this, &Form1::button3_Click);
			// 
			// textBox1
			// 
			this->textBox1->Location = System::Drawing::Point(46, 184);
			this->textBox1->Name = L"textBox1";
			this->textBox1->Size = System::Drawing::Size(100, 20);
			this->textBox1->TabIndex = 4;
			// 
			// Form1
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(292, 266);
			this->Controls->Add(this->textBox1);
			this->Controls->Add(this->button3);
			this->Controls->Add(this->label1);
			this->Controls->Add(this->button2);
			this->Controls->Add(this->button1);
			this->Name = L"Form1";
			this->Text = L"Form1";
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion
	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
				 if(!this->serialPort1->IsOpen)  //открываем порт
                     { 
                         this->serialPort1->PortName="COM2"; //у меня ардуино подключен к COM2
                         this->serialPort1->BaudRate=Int32::Parse("9600"); //скорость подключения
                          this->serialPort1->Open(); 
                         this->button1->Enabled = false; 
                            this->button2->Enabled = true;
				      } 
			 }
	private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
				         this->serialPort1->Close();  //закрываем порт
                         this->button1->Enabled = true; 
                         this->button2->Enabled = false;
			 }
			 
	 string DataRecived = null;

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


 {
     DataRecived = serialPort1.ReadLine();
     this.Invoke(new EventHandler(TextOut));
 }

 private void TextOut(object sender, EventArgs e)
 {
     textBox1.Text = DataRecived;
 }
		 }
};
}

Пробую вот так и конечно ничего не выходит!В примере инициализация ком порта выполнена в теле static void Main(), а у меня по нажатию кнопки Button 1. Вообщем запутался в край!!!Еще там используют #using <System.dll> Мне тоже использовать эту длл-ку?

DeN-iZ
Offline
Зарегистрирован: 04.04.2013
                 {
	     DataRecived = serialPort1.ReadLine();
	     this.Invoke(new EventHandler(TextOut));
	 }
	 
	 private void TextOut(object sender, EventArgs e)
	 {
	     textBox1.Text = DataRecived;
	 }
	       

Ага одна из ошибок моих!Эта часть наC# ,а я её втулил в таком же виде в C++!!!!!!!!

Переписал так 

      {
	     DataRecived = serialPort1->ReadLine();
	     this->Invoke(new EventHandler(TextOut));
	 }
	 
	 private void TextOut(object sender, EventArgs e)
	 {
	     textBox1->Text = DataRecived;
	 }

Тоже не катит(

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Да и убрал обработку третьей кнопки ,да и вообще её убрал

leshak
Offline
Зарегистрирован: 29.09.2011

>В примере инициализация ком порта выполнена в теле static void Main()

Вот и вы начните с этого примера. Обычная консольная аппликуха. Вначале в ней научитесь читать порт по событию, а не из основного потока.

А то вы сразу схватились за приложение на WinForms. Там, извините, порог вхождения намного больше чем в ардуино. Ардуино - намного проще того что нынче требуется для того что-бы написать приличное windows-приложение. Пользователи - они балованные стали. Потом разберетесь с жизненным циклом Form. Какие события происходят при загрузке формы, при старте приложения. При закрытии (освобождать порт тоже нужно не забывать). Научитесь апдейтить UI не из главного потока.

Вот тогда и формочка напишется. Если "серьезно и красиво" хотите, а не поделку "три кнопки, два поля". То лучше, наверное перейти на C#/WPF. Но там и с XAML прийдется разбиратся, учится строить правильную архитектуру. Познакомится с MVC и хреновой тучей его реализаций.....

По поводу вашей попытки.

Ну во первых нужно пнуть за "тоже не катит". Очень информативно. Не компилируется, не ловит, зависает? Что вам тут ответить?  Ну значит "где-то лажа".

Во вторых, вы явно не поняли сути события. Оно срабатывает когда в сериал пришли данные. Но вам никто не гарантировал что "они пришли целиком". Может только пол строки к этому моменту успело попасть в буффер. Поэтому ReadLine - немного не уместно. Вам нужно "прочитать что пришло". Если вы собираетесь "сразу выводить" - можете вывести и кусочек, если хотите что-бы выводило построчно, значит нужно "куда-то запомнить". Пока не прийдется следующая порция данных. Когда пришла очередная, ищете в ней символ \n (символ конца строки), когда пришло - вот тогда уже выводите что вы там из кусочков "насобирали". Все это "натренироватся" можно в консольном приложении.

В третьих: вас не смущает что вы попытались слепить два примера написанных на разных языках?   Один на C++ второй на C# .  Я вроде даже указал что пример Максима на C# написан и нужно править синтаксис.

Тут кстати, если новичок, то не очень понятен изначальный выбор C++ в качестве языка написания. C# оно как-бы меньше способов выстрелить себе в ногу, не нужно с указателями быть на "Вась-Вась" и т.п.. Да и у Visual Studio это все-таки "основной язык". Расплата за это, конечно - необходимость иметь на машине .net framework, что автоматом означает что работать будет только под windows. Но если прога пришется "для себя", то не такая уж и большая плата за удобство. К тому же, даже если вы на C++ напишите с использованием WinForms - не уверен что но где-то кроме винды запустится.

 

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Приложение пишу для себя и использовать буду только под виндовс. Нужно это по работе. Для управления проливной установкой для уровнемеров. Нужно из программы управлять подачей воды и сливом воды (нажатием кнопок в программе). Эта часть получилась без проблем, открываю порт и шлю комады в ардуино, все работает!!!А считывать ком порт необходимо так как хочу внизу установки поместить датчик избыточного давления (отградуированного в ммВодяного столба) а по его показаниям определять уровень воды в установке. Показания датчика хочу выводить в любое место программы, хоть в lable хоть в textBox не принципиально!Вот все что нужно!!!!!!Только чтоб данные выводились в реальном времени!!!Как это исполнить?

leshak
Offline
Зарегистрирован: 29.09.2011

>Как это исполнить?

Ну видимо - никак. Ответы вам уже дали, но вам они ничего не говорят. Что тут дальше можно? Два варианта, либо повторить все еще раз, либо садится и писать за вас код.

Вы хотя-бы пример из ссылки взяли, запустили его?

 

 

Клапауций
Offline
Зарегистрирован: 10.02.2013

DeN-iZ пишет:

Только чтоб данные выводились в реальном времени!!!Как это исполнить?

Я запретил виндузятникам читать компорт в реальном времени, поэтому - только командная строка.

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

К чему пост ??????????????????????????????

 

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Господа,благодарю адекватных людей за помощь, если говорите что по вышесказанному можно реализовать задачу, значит разберусь, по окончанию выложу код здесь. Чтобы люди могли пользоваться. В любом случае сделаем с Вами полезное дело!!!

Клапауций
Offline
Зарегистрирован: 10.02.2013

DeN-iZ пишет:

Господа,благодарю адекватных людей за помощь, если говорите что по вышесказанному можно реализовать задачу, значит разберусь, по окончанию выложу код здесь. Чтобы люди могли пользоваться. В любом случае сделаем с Вами полезное дело!!!

это правильно - неадекватных благодарить не нужно.

Trouyan
Offline
Зарегистрирован: 05.01.2014

Добрый день. Тоже вожусь с COM портом. В принципе давно всё работает. Но сейчас у меня задача отправлять очень большой поток данных, и к сожалению установленная скорость в 115200бит/сек не достигается.

С учетом стартовых и стоповых битов скорость должна быть около 11520байт/сек, но в реале наблюдаю раз в десять меньше. Полагаю что это из-за ОС Windows. Т.е. информация дошла вовремя, но вот получение ее заторможена сторонними событиями. (т.к. Windows не есть RTOS).

Решил обойти эту неловкую ситуацию следующим образом:

1.) Получаю первай байт -  он будет сигнализировать о начале передачи большого пакета (8000байт). 

2.) отключаю событие по приему данных через последовательный порт  (здесь проблема.... не пойму как это сделать)

3.) Выжидаю 1 сек ( при скорости11520байт/с этого должно быть более чем достаточно) 

4.) Читаю все полученные 8000байт

 

Уважаемые форумчанене, имеет ли такой план право на жизнь ? Если да то как быть со вторым пунктом  (пишу на с++ в Windows Form).

Заранее благодарю.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Могу посоветовать только это

http://www.hiasm.com/sdk.html

DarkDaemon
Offline
Зарегистрирован: 31.10.2015

Долго мучался с C++, для C# полно примеров, а для VC++ их нет. Пример из MSDN'a неудобный - он не позволяет выводить текст из COM-порта в элементы формы. Спустя 3 часа мучений наклепал правильный код:

//В самом начале кода формы объявляем делегат
public delegate void updateDelegate(String^ message);

//Затем в конструкторе формы добавляем к объекту SerialPort (у меня имя serialPort1) событие DataReceived
//После добавления в коде конструктора формы появится такая строчка
this->serialPort1->DataReceived += gcnew System::IO::Ports::SerialDataReceivedEventHandler(this, &Form1::serialPort1_DataReceived);

//И процедура serialPort1_DataReceived. В нее пишем такой код
private: System::Void serialPort1_DataReceived(System::Object^  sender, System::IO::Ports::SerialDataReceivedEventArgs^  e) {
	SerialPort^ sp = (SerialPort^)sender;
	String^ message = sp->ReadLine();
	this->BeginInvoke(gcnew updateDelegate(this, &Form1::DataReceivedDelegate), message);
}

private: System::Void DataReceivedDelegate(String^ message)	{
	if (message->IndexOf("arduino") > -1)	{ //У меня кодовое слово - "arduino" )))
		//Тут можно сделать любые нужные вам манипуляции с сообщением из COM-порта
		textBox1->Text = message; //Выводим сообщение в текстовое поле.
	}  else {
		textBox1->Text = "Пришел некорректный ответ";
	}
	serialPort1->Close();
}

Если есть вопросы - задавайте

91832547
Offline
Зарегистрирован: 11.03.2017

Помогите. Arduino UNO. Посылает две строки со значениями.
{
Serial.print("T");
Serial.println(analogRead(A0));
delay(1);
Serial.print("H");
Serial.println(analogRead(A1));
delay(1);

}
Как этот массив принять в textBoxы я могу его принять полностью он состоит из двух строк
Как эти строки разложить в разные textBox1 и textBox2 и убрать первые символы "H" , "T" потому что
должны остаться циферные значения для преобразования в int тип. СПАСИБО БОЛЬШОЕ. Пишу на Visual Studio C++

Evgeni61
Offline
Зарегистрирован: 13.06.2020

Здравствуйте. Если вам не сложно можете помочь мне.

Нужно отправить массив значений в COM порт.

У меня есть массив DataDiscrete

не получается отправить

 

Evgeni61
Offline
Зарегистрирован: 13.06.2020
#pragma once
unsigned __int8 DataDiscrete[8] = {1,1,1,1,1,1,1,1}; // Массив который нужно отправить


namespace My {


	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;

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

						 this->serialPort1->Close();  //закрываем порт
                         this->button1->Enabled = true;
                         this->button2->Enabled = false;
						 this->PortText->Text = "ЗАКРЫТ";
		 }
private: System::Void but4_Click(System::Object^  sender, System::EventArgs^  e) {
					DataDiscrete[2] = 1;
		 }

private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
			//if(this->but1->IsClick) {DataDiscrete |= 1;} else {DataDiscrete &= ~1;}
//-------------------- ДАЛЕЕ МНОГО КОДА--------------------//			
			
// ЗДЕСЬ ОБРАБОТЧИК ТАЙМЕРА

			if(this->serialPort1->IsOpen)
			{
			    this->serialPort1->Write(DataDiscrete,0,7); //В этой строчке ошибка !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			}
// Конец обработчика


private: System::Void but2_Click(System::Object^  sender, System::EventArgs^  e) {
			DataDiscrete[1] = 1;
		 }
private: System::Void but3_Click(System::Object^  sender, System::EventArgs^  e) {
			DataDiscrete[1] = 0; DataDiscrete[2] = 0;
		 }
private: System::Void but5_Click(System::Object^  sender, System::EventArgs^  e) {
			 DataDiscrete[3] = 1;
		 }
private: System::Void but7_Click(System::Object^  sender, System::EventArgs^  e) {
			 DataDiscrete[4] = 1;
		 }
private: System::Void but6_Click(System::Object^  sender, System::EventArgs^  e) {
			DataDiscrete[3] = 0;  DataDiscrete[4] = 0;
		 }
private: System::Void but8_Click(System::Object^  sender, System::EventArgs^  e) {
			 DataDiscrete[5] = 1;
		 }
private: System::Void but10_Click(System::Object^  sender, System::EventArgs^  e) {
			 DataDiscrete[6] = 1;
		 }
private: System::Void but9_Click(System::Object^  sender, System::EventArgs^  e) {
		 DataDiscrete[5] = 0;  DataDiscrete[6] = 0;
		 }
};
}