Endlosschleife mit Timer beenden?!



  • Hi zusammen,
    ich hoff ich bin hier in der richtigen Kategorie gelandet...
    Also, ich hab ein Programm geschrieben, mit dem ich Daten über einen COM-Port einlesen kann. Das Gerät, von dem ich die Daten einles, schickt diese nach höchstens 30 sekunden. Ich bin in einer Endlosschleife so lange, bis das Gerät etwas sendet. Wenn es nach 30 Sekunden jedoch noch nichts gesendet hat, soll das Programm aus der Endlosschleife raus und beenden. Ich wollte das Ganze mit einem Timer machen (30000ms), der eine globale Variable hochzählt, die ich dann in meiner Endlosschleife überprüfen will. Der Timer soll auf ButtonClick auslösen, mit dem ich auch die Abfrage starte. Aber irgendwie springt meine Funktion nicht aus der Endlosschleife raus. Ich glaub der Timer kann nicht hochzählen, solange ich in der Endlosschleife bin. Wie könnte man das Problem sonst lösen?
    Hier ist der Quelltext:

    #pragma once
    #include <string>
    #include <sstream>
    #include "c:\Dokumente und Einstellungen\Meinz\Eigene Dateien\BA\Projekte Visual Studio\18 - Aufagabe 4.1\18 - Aufagabe 4.1\CppCLIStringConv.h"
    namespace My1 {
    	int k=0;
    
    	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 std;
    
    	/// <summary>
    	/// Zusammenfassung für Form1
    	///
    	/// Warnung: Wenn Sie den Namen dieser Klasse ändern, müssen Sie auch
    	///          die Ressourcendateiname-Eigenschaft für das Tool zur Kompilierung verwalteter Ressourcen ändern,
    	///          das allen RESX-Dateien zugewiesen ist, von denen diese Klasse abhängt.
    	///          Anderenfalls können die Designer nicht korrekt mit den lokalisierten Ressourcen
    	///          arbeiten, die diesem Formular zugewiesen sind.
    	/// </summary>
    	public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
    		Form1(void)
    		{
    			InitializeComponent();
    			//
    			//TODO: Konstruktorcode hier hinzufügen.
    			//
    		}
    
    	protected:
    		/// <summary>
    		/// Verwendete Ressourcen bereinigen.
    		/// </summary>
    		~Form1()
    		{
    			if (components)
    			{
    				delete components;
    			}
    		}
    	private: System::IO::Ports::SerialPort^  serialPort1;
    	protected: 
    	private: System::Windows::Forms::Timer^  timer1;
    	private: System::Windows::Forms::TextBox^  textBox1;
    	private: System::Windows::Forms::Button^  button1;
    	private: System::Windows::Forms::Button^  button2;
    
    	private: System::ComponentModel::IContainer^  components;
    
    	private:
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    
    #pragma region Windows Form Designer generated code
    		/// <summary>
    		/// Erforderliche Methode für die Designerunterstützung.
    		/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
    		/// </summary>
    		void InitializeComponent(void)
    		{
    			this->components = (gcnew System::ComponentModel::Container());
    			this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
    			this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
    			this->textBox1 = (gcnew System::Windows::Forms::TextBox());
    			this->button1 = (gcnew System::Windows::Forms::Button());
    			this->button2 = (gcnew System::Windows::Forms::Button());
    			this->SuspendLayout();
    			// 
    			// serialPort1
    			// 
    			this->serialPort1->PortName = L"COM7";
    			this->serialPort1->DataReceived += gcnew System::IO::Ports::SerialDataReceivedEventHandler(this, &Form1::serialPort1_DataReceived);
    			// 
    			// timer1
    			// 
    			this->timer1->Enabled = true;
    			this->timer1->Interval = 30000;
    			this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
    			// 
    			// textBox1
    			// 
    			this->textBox1->Location = System::Drawing::Point(12, 12);
    			this->textBox1->Multiline = true;
    			this->textBox1->Name = L"textBox1";
    			this->textBox1->Size = System::Drawing::Size(83, 309);
    			this->textBox1->TabIndex = 0;
    			// 
    			// button1
    			// 
    			this->button1->Location = System::Drawing::Point(660, 325);
    			this->button1->Name = L"button1";
    			this->button1->Size = System::Drawing::Size(75, 23);
    			this->button1->TabIndex = 1;
    			this->button1->Text = L"Ende";
    			this->button1->UseVisualStyleBackColor = true;
    			this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
    			// 
    			// button2
    			// 
    			this->button2->Location = System::Drawing::Point(101, 10);
    			this->button2->Name = L"button2";
    			this->button2->Size = System::Drawing::Size(75, 23);
    			this->button2->TabIndex = 2;
    			this->button2->Text = L"Power-On";
    			this->button2->UseVisualStyleBackColor = true;
    			this->button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click);
    			// 
    			// Form1
    			// 
    			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    			this->ClientSize = System::Drawing::Size(747, 360);
    			this->Controls->Add(this->button2);
    			this->Controls->Add(this->button1);
    			this->Controls->Add(this->textBox1);
    			this->Name = L"Form1";
    			this->Text = L"Form1";
    			this->ResumeLayout(false);
    			this->PerformLayout();
    
    		}
    #pragma endregion
    		const std::string intToHex (int o)											// int-Wert in string mit hex-Wert umwandeln
    		{
    			std::ostringstream oss;
    			oss<<std::hex<<o;
    			return oss.str();
    		}
    	private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
    				 k++;
    			 }
    	private: System::Void serialPort1_DataReceived(System::Object^  sender, System::IO::Ports::SerialDataReceivedEventArgs^  e) {
    			 }
    	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
    				 Close();
    			 }
    private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
    			 	 serialPort1->Open();												//Port öffnen
    				 timer1->Enabled=true;
    				 while(serialPort1->BytesToRead==0 && k<1){}						//hier soller nach 30 sek. raushüpfen, machter aber nich???
    				 while(serialPort1->BytesToRead!=0) 
    				 {
    					 int ein=serialPort1->ReadByte();								//ein Byte einlesen
    					 //std::string textmm="";								          Ausgabe als char
    					 //textmm += ein;
    					 //String^ dext=toString(textmm);
    					 String^ dext=toString(intToHex (ein));							//Ausgabe als hex
    					 textBox1->AppendText(String::Format("{0}\r\n",dext)); 
    				 }
    				 if (k>=1) textBox1->AppendText(String::Format("Kein Ergebnis"));
    				 timer1->Enabled=false;
    				 serialPort1->Close();												//Port schließen
    		 }
    
    };
    }
    


  • while(serialPort1->BytesToRead==0 && k<1){}
    

    Warum lagerst Du den rest der nach der leeren "ich renn mir nen wolf" schleife kommt nicht einfach in den Timer aus ?



  • Ja des ändert ja auch nich wirklich was. Mein Wolf rennt trotzdem munter weiter und der Timer zählt nicht höher...;)



  • Irgendwie is die Funktion nicht so der Hammer. Wenn jemand was besseres einfällt nur her damit;)
    Gruß, Julian



  • Mach k zu nem Member von Form und lass es nicht global in der Landschaft rumhängen!

    Dann schau Dir mal an was Du da machst und schau mal in die Doku:

    SerialPort::ReadTimeout

    TimeoutException
    Der Vorgang konnte nicht vor Ablauf des Timeouts abgeschlossen werden.

    - oder -

    Es wurde kein Byte gelesen.

    Du kannst also die Timeoutgeschichten der Klasse überlassen, diese implementiert das bereits.

    Den Wolf kannst einfach weglassen, der muss sich nich abhetzen 🙂



  • Uuaa, jetzt gehts los. Vielleicht sollte ich noch sagen, dass ich noch nich so die Ahnung hab...(studier E-Technik im 2. Sem., da ham wir bissl was gelernt).
    Wie mach ich denn k zu nem Member bzw. was is n Member?
    Der ReadTimeout steht bei mir grad noch auf -1ms. Muss ich den anders einstellen bzw. was bringt der denn genau?
    Gruß, Julian



  • http://de.wikipedia.org/wiki/Timeout

    http://msdn2.microsoft.com/en-us/library/system.io.ports.serialport.readtimeout.aspx

    http://msdn2.microsoft.com/en-us/library/system.io.ports.serialport.readbyte.aspx

    http://msdn2.microsoft.com/en-us/library/system.serviceprocess.timeoutexception.aspx

    Als Student wird Dir lesen sicherlich nicht fremd sein. Danach kannst Du gerne nochmal fragen.

    Member:

    #include "c:\Dokumente und Einstellungen\Meinz\Eigene Dateien\BA\Projekte Visual Studio\18 - Aufagabe 4.1\18 - Aufagabe 4.1\CppCLIStringConv.h" 
    namespace My1 { 
        int k=0;  <--- Hier wegnehmen
    
    public ref class Form1 : public System::Windows::Forms::Form 
        { 
        int k=0;  <--- Hier eisnetzen
        public:
    


  • Also des mit dem Member geht nich. Wenn ich des k da einfüg krieg ich den Fehler:
    Nur statische Datenmember können innerhalb einer Verweisklasse oder eines Werttyps initialisiert werden.
    Bei dem andern Zeug bin ich mal noch am ausprobieren, meld mich dann wenns klappt oder nicht;)



  • Ok ich brauch den Timer nicht, weil der Port automatisch nach den 30 sek. nen Timeout machen kann. Aber in den 30 sekunden muss ja immer wieder geprüft werden, ob was kommt oder nicht. Bei mir springt er ohne Wolf grad über die Schleife, in der er liest drüber, wenn nicht ankommt. Wie kan ich das machen?



  • Und ich hab noch ein Problem. Ich muss dem Gerät einen String aus Hex-Codes schicken (z.B.: 4E 2D 02 41), weiß aber nicht wie ich das machen kann. Wenn ich serialPort1->Write() benutz, will das Programm, dass ich String^ eingebe. D.h. ich müsste die ganzen Sachen mit ihrem ASCII-Zeichen eingeben. Allerdings gibt es nicht für alle Hex-Zahlen, die ich schicken will ASCII-Zeichen und ich kann sie auch gar nicht eingeben (Smileys usw.). Und wenn ich einfach den Hex-Wert als String^ verschick (z.B. serialPort1->Write("4B")), schickt er erst die 4 raus und dann das B, obwohl ich es als eine Zahl verschicken will. Ich müsste statt dem 4B ein K verschicken, dann wärs richtig.
    Ich hoffe ich hab mein Problem halbwegs verständlich erklärt. Wär schön wenn mir jmd. helfen könnt. Ich bräuchte irgendwie ein Programm HexToAscii aber ich glaub des is nich so einfach in einem Programm zu realisieren.
    Danke. Gruß, Julian


Anmelden zum Antworten