{"id":502,"date":"2016-04-17T19:01:45","date_gmt":"2016-04-17T17:01:45","guid":{"rendered":"http:\/\/www.daniel.slask.pl\/?p=502"},"modified":"2021-02-12T21:08:53","modified_gmt":"2021-02-12T20:08:53","slug":"visual-studio-2015-obsluga-komponentu-serialport-tworzymy-prosty-terminal-dla-portu-szeregowego","status":"publish","type":"post","link":"https:\/\/daniel.slask.pl\/m\/visual-studio-2015-obsluga-komponentu-serialport-tworzymy-prosty-terminal-dla-portu-szeregowego\/","title":{"rendered":"[Visual Studio 2015] Obs\u0142uga komponentu serialPort &#8211; tworzymy prosty terminal dla portu szeregowego"},"content":{"rendered":"\n<p>Witam.<\/p>\n\n\n\n<p>W pewnym momencie dla hobbysty elektronika przychodzi taki moment w kt\u00f3rym potrzebne jest, aby wykonane urz\u0105dzenie skomunikowa\u0142o si\u0119 z komputerem &#8211; np. aby wys\u0142a\u0107 warto\u015bci zmierzonej temperatury. Dodatkowo chcemy aby odbieraniem i interpretacj\u0105 danych zajmowa\u0142 si\u0119 dedykowany program, najlepiej jakby by\u0142 napisany przez nas. Aby tego dokona\u0107, w programie<strong> Visual Studio<\/strong> w j\u0119zyku<strong> C#<\/strong> wykorzystuje si\u0119 komponent <em>serialPort<\/em>, kt\u00f3ry w do\u015b\u0107 \u0142atwy spos\u00f3b umo\u017cliwia nam odbieranie i wysy\u0142anie danych.<\/p>\n\n\n\n<p>W tym wpisie chcia\u0142bym przedstawi\u0107 spos\u00f3b konfiguracji tego komponentu na przyk\u0142adzie prostego terminala. Mo\u017cliwa b\u0119dzie zmiana portu szeregowego, oraz wyb\u00f3r pr\u0119dko\u015bci <em>baudrate<\/em>. Postaram si\u0119 r\u00f3wnie\u017c w jak najlepszy, oraz w prosty i zrozumia\u0142y spos\u00f3b opisa\u0107 kod, kt\u00f3ry zostanie wykorzystany. W tym momencie r\u00f3wnie\u017c chcia\u0142bym przeprosi\u0107 za ewentualne b\u0142\u0119dy, oraz prosi\u0107 o sugestie dot. lepszego opisania danego fragmentu programu.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>Zak\u0142adam, \u017ce tworzenie nowego projektu jak i wstawianie nowych komponent\u00f3w do formatki jest znana.<\/p>\n\n\n\n<p>Przyk\u0142ad terminala, realizowany jest w programie <strong>Visual Studio 2015 Community<\/strong> w j\u0119zyku<strong> C#<\/strong>.<\/p>\n\n\n\n<p>Wi\u0119kszo\u015b\u0107 kodu (cz\u0119\u015b\u0107 \u0142atwiejsza) zostanie opisana w komentarzach. Pozosta\u0142e fragmenty kodu wymagaj\u0105ce wi\u0119kszej uwagi zostan\u0105 dodatkowo opisane.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>W programie zostan\u0119 u\u017cyte nast\u0119puj\u0105ce kontrolki:<\/p>\n\n\n\n<ul><li><em>label<\/em> &#8211; 3 sztuki &#8211; zastosowane do opisu innych kontrolek<\/li><li><em>button<\/em> &#8211; 3 sztuki &#8211; przyciski po\u0142\u0105cz, roz\u0142\u0105cz wy\u015blij<\/li><li><em>comboBox<\/em> &#8211; 2 sztuki &#8211; wyb\u00f3r portu, oraz pr\u0119dko\u015bci transmisji<\/li><li><em>checkBox<\/em> &#8211; 2 sztuki &#8211; wyb\u00f3r, czy wysy\u0142any tekst ma na ko\u0144cu zawiera\u0107 znak ko\u0144ca linii i\/lub powrotu karetki<\/li><li><em>richTextBox<\/em> &#8211; 1 sztuka &#8211; okienko w kt\u00f3rej b\u0119d\u0105 pojawia\u0107 si\u0119 odebrane znaki<\/li><li><em>textBox<\/em> &#8211; 1 sztuka &#8211; okienko do kt\u00f3rego b\u0119d\u0105 wpisywane znaki, kt\u00f3re maj\u0105 zosta\u0107 wys\u0142ane<\/li><li><em>serialPort<\/em> &#8211; 1 sztuka &#8211; komponent potrzebny do obs\u0142ugi komunikacji szeregowej<\/li><\/ul>\n\n\n\n<p>Ustawienie komponent\u00f3w jest dowolne. W moim przyk\u0142adzie wygl\u0105da to nast\u0119puj\u0105co:<\/p>\n\n\n\n<figure class=\"wp-block-image alignnone\"><a href=\"http:\/\/www.daniel.slask.pl\/m\/wp-content\/uploads\/2016\/04\/Wyglad_formatki.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"http:\/\/www.daniel.slask.pl\/m\/wp-content\/uploads\/2016\/04\/Wyglad_formatki-150x150.jpg\" alt=\"U\u0142o\u017cenie komponent\u00f3w\" class=\"wp-image-505\"\/><\/a><figcaption>U\u0142o\u017cenie komponent\u00f3w<\/figcaption><\/figure>\n\n\n\n<p>Tak jak ju\u017c wspomnia\u0142em we wst\u0119pie, program b\u0119dzie umo\u017cliwia\u0142 wybranie pr\u0119dko\u015bci <em>baudrate<\/em>, oraz portu do kt\u00f3rego pod\u0142\u0105czone b\u0119dzie nasze urz\u0105dzenie. Aby mo\u017cliwy by\u0142 wyb\u00f3r pr\u0119dko\u015bci nale\u017cy do kontrolki z rozwijanym menu wpisa\u0107 \u017c\u0105dane pr\u0119dko\u015bci &#8211; dokonuje si\u0119 tego poprzez wskazanie rozwijanej listy <em>(comboBox)<\/em> i odnalezieniu we w\u0142a\u015bciwo\u015bciach (okienko w\u0142a\u015bciwo\u015bci domy\u015blnie znajduje si\u0119 na dole po prawej stronie) do tej kontroli parametru <em>Items.<\/em> Wybranie tego parametru powoduje otwarcie nowego okna, gdzie w ka\u017cdej nowej linii, mo\u017cna umie\u015bci\u0107 w tym przypadku \u017c\u0105dane pr\u0119dko\u015bci. Wygl\u0105da to w ten spos\u00f3b:<\/p>\n\n\n\n<figure class=\"wp-block-image alignnone\"><a href=\"http:\/\/www.daniel.slask.pl\/m\/wp-content\/uploads\/2016\/04\/Ustalenie_kolekcji_predkosci.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"http:\/\/www.daniel.slask.pl\/m\/wp-content\/uploads\/2016\/04\/Ustalenie_kolekcji_predkosci-150x150.jpg\" alt=\"Wpisanie dost\u0119pnych pr\u0119dko\u015bci do rozwijanej listy.\" class=\"wp-image-506\"\/><\/a><figcaption>Wpisanie dost\u0119pnych pr\u0119dko\u015bci do rozwijanej listy.<\/figcaption><\/figure>\n\n\n\n<p>Natomiast dost\u0119pne porty, uzupe\u0142niane b\u0119d\u0105 automatycznie podczas \u0142adowania\/uruchamiania si\u0119 naszego programu. Tego dokonamy pisz\u0105c odpowiedni kod w zdarzeniu wywo\u0142ywanym podczas \u0142adowania naszego formularza. W tym celu nale\u017cy wybra\u0107 formularz i w oknie w\u0142a\u015bciwo\u015bci zmieni\u0107 wy\u015bwietlany tryb na zdarzenia, a nast\u0119pnie dwa razy klikn\u0105\u0107 obok zdarzenia <em>LOAD:<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image alignnone\"><a href=\"http:\/\/www.daniel.slask.pl\/m\/wp-content\/uploads\/2016\/04\/Zdarzenia.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"http:\/\/www.daniel.slask.pl\/m\/wp-content\/uploads\/2016\/04\/Zdarzenia-150x150.jpg\" alt=\"Zdarzenia formatki\" class=\"wp-image-507\"\/><\/a><figcaption>Zdarzenia formatki<\/figcaption><\/figure>\n\n\n\n<p>Otworzy nam si\u0119 plik programu z rozszerzeniem <em>*.cs,<\/em> a znak kursora b\u0119dzie ustawiony na zawarto\u015b\u0107 metody uruchamianej po za\u0142adowaniu formatki. Cia\u0142o tej zostanie uzupe\u0142nione nast\u0119puj\u0105cym kodem:<\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">\/\/za\u0142adowanie FORM\nprivate void Form1_Load(object sender, EventArgs e)\n{\n         \/\/odczytanie dost\u0119pnych port\u00f3w wraz z wpisanie ich do rozwijanej listy\n            comboBox1.Items.AddRange(SerialPort.GetPortNames());\n\n          \/\/sortowanie wyswietlanych nazw dost\u0119pnych port\u00f3w\n          comboBox1.Sorted = true;   \/\/true oznacza, \u017ce zawarto\u015b\u0107 tego komponenty ma by\u0107 posortowana\n\n          \/\/przypisanie wartosci domyslnych w rozwijanych listach wyboru\n          comboBox1.SelectedIndex = 0;   \/\/pierwszy dost\u0119pny port\n          comboBox2.SelectedIndex = 6;   \/\/pr\u0119dko\u015b\u0107 19200 - jest 6 z kolei - liczymy od 0\n\n          \/\/aktywacja i deaktywacja odpowiednich kontrolek\n          comboBox1.Enabled = true;   \/\/lista z portami\n          comboBox2.Enabled = true;   \/\/lista z pr\u0119dko\u015bci\u0105\n          button1.Enabled = false;    \/\/przycisk wy\u015blij\n          button2.Enabled = true;     \/\/przycisk po\u0142\u0105cz\n          button3.Enabled = false;    \/\/przycisk roz\u0142\u0105cz\n          textBox1.Enabled = false;   \/\/edit box dla wy\u015blij\n}<\/code><\/pre>\n\n\n\n<p>W ostatniej cz\u0119\u015bci tego kodu aktywujemy, b\u0105d\u017a dezaktywujemy niekt\u00f3re kontrolki &#8211; w zale\u017cno\u015bci od tego czy po za\u0142adowaniu programu maj\u0105 one by\u0107 dost\u0119pne dla u\u017cytkownika.<\/p>\n\n\n\n<p>Nale\u017cy doda\u0107 jeszcze jedn\u0105 przestrze\u0144 nazw (zbi\u00f3r dost\u0119pnych klas &#8211; biblioteki), kt\u00f3ra b\u0119dzie nam potrzebna do odczytania dost\u0119pnych port\u00f3w. Dodajemy j\u0105 na samej g\u00f3rze za domy\u015blnie dodanymi przestrzeniami nazw, a przed cia\u0142em naszej klasy. Jest to przestrze\u0144:<\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp\">using System.IO.Ports;                  \/\/Dodanie nowej przestrzeni nazw zwi\u0105zanej z obs\u0142ug\u0105 wej\u015b\u0107\/wyj\u015b\u0107 dla port\u00f3w<\/code><\/pre>\n\n\n\n<p>W nast\u0119pnym kroku ustanowimy po\u0142\u0105czenie programu z wybranym portem, poprzez wci\u015bni\u0119cie przycisku &#8211; <em>Po\u0142\u0105cz<\/em>. Aby napisa\u0107 kod dla przycisku, nale\u017cy przej\u015b\u0107 do widoku projektanta formularza i dwa razy klikn\u0105\u0107 na przycisk kt\u00f3ry ma powodowa\u0107 po\u0142\u0105czenie z danym portem. Kod dla tego przycisku wygl\u0105da nast\u0119puj\u0105co:<\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">\/\/po\u0142\u0105cz\n     private void button2_Click(object sender, EventArgs e)\n     {\n\n         \/\/zabezpieczenie przed wyst\u0105pieniem wyj\u0105tku\/problemu z otwarciem portu\n         try\n         {\n            \/\/ustawiany jest port, kt\u00f3ry zosta\u0142 wybrany z rozwijanej listy\n             serialPort1.PortName = comboBox1.Text;\n             \/\/konwersja i ustawienie pr\u0119dko\u015bci transmisji (kt\u00f3ra zosta\u0142a wybrana z rozwijanej listy)\n             serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);\n\n             \/\/otwarcie wybranego portu\n             serialPort1.Open();\n\n             \/\/wpisanie do \"odebrane\"\n             richTextBox1.Text += \"Po\u0142\u0105czono dla Port \" + serialPort1.PortName + \" \" + serialPort1.BaudRate.ToString() + \"bps \\n\\r\";\n\n                \/\/aktywacja i deaktywacja odpowiednich kontrolek\n             comboBox1.Enabled = false;      \/\/lista z portami\n             comboBox2.Enabled = false;      \/\/lista z pr\u0119dko\u015bci\u0105\n             button1.Enabled = true;         \/\/przycisk wy\u015blij\n             button2.Enabled = false;        \/\/przycisk po\u0142\u0105cz\n             button3.Enabled = true;         \/\/przycisk roz\u0142\u0105cz\n             textBox1.Enabled = true;        \/\/edit box dla wy\u015blij\n         }\n         catch\n         {\n             \/\/je\u017celi wyst\u0105pi b\u0142\u0105d\n             richTextBox1.Text += \"B\u0142\u0105d po\u0142\u0105czenia\\n\\r\";\n         }\n\n}<\/code><\/pre>\n\n\n\n<p>W obs\u0142udze tego przycisku zosta\u0142a umieszczona instrukcja<em> try, catch<\/em>. Powoduje ona przechwycenie wyj\u0105tku\/b\u0142\u0119du kt\u00f3ry wyst\u0105pi w kt\u00f3rej\u015b cz\u0119\u015bci programu kt\u00f3ry si\u0119 w niej znajduje. Je\u017celi taki b\u0142\u0105d zostanie przechwycony, wykonywanie reszty kodu w instrukcji <em>try<\/em> zostanie przerwane i nast\u0105pi wykonanie kodu w instrukcji <em>catch.<\/em> W przypadku braku wyst\u0105pieniu jakiego\u015b b\u0142\u0119du, kod w instrukcji <em>catch<\/em> nie zostanie w og\u00f3le wykonany.<\/p>\n\n\n\n<p>W podobny spos\u00f3b post\u0119pujemy z przyciskiem <em>roz\u0142\u0105cz:<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">       \/\/roz\u0142\u0105cz\n        private void button3_Click(object sender, EventArgs e)\n        {\n\n            \/\/zabezpieczenie przed wyst\u0105pieniem wyj\u0105tku\/problemu z zamkni\u0119ciem portu\n            try\n            {\n                \/\/zamkni\u0119ciu portu - od\u0142\u0105czenie\n                serialPort1.Close();\n\n                \/\/wpisanie do \"odebrane\"\n                richTextBox1.Text += \"Roz\u0142\u0105czono\\n\\r\";\n\n                \/\/aktywacja i deaktywacja odpowiednich kontrolerk\n                comboBox1.Enabled = true;   \/\/lista z portami\n                comboBox2.Enabled = true;   \/\/lista z pr\u0119dko\u015bci\u0105\n                button1.Enabled = false;    \/\/przycisk wy\u015blij\n                button2.Enabled = true;     \/\/przycisk po\u0142\u0105cz\n                button3.Enabled = false;    \/\/przycisk roz\u0142\u0105cz\n                textBox1.Enabled = false;   \/\/edit box dla wy\u015blij\n            }\n            catch\n            {\n                \/\/je\u017celi wyst\u0105pi b\u0142\u0105d\n                richTextBox1.Text += \"B\u0142\u0105d z roz\u0142\u0105czeniem\\n\\r\";\n            }\n\n        }<\/code><\/pre>\n\n\n\n<p>oraz <em>wy\u015blij<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">        \/\/przycisk wy\u015blij\n        private void button1_Click(object sender, EventArgs e)\n        {\n            \/\/wsy\u0142anie danych z kontroli textbox przez port szeregowy\n            serialPort1.Write(textBox1.Text.ToString());\n\n            \/\/czy ma wysy\u0142a\u0107 polecenie powrotu karetki\n            if (checkBox1.Checked)\n            {\n                \/\/wys\u0142anie polecenia powrotu\n                serialPort1.Write(\"\\r\");\n            }\n\n            \/\/czy ma wysy\u0142a\u0107 polecenie nowej lini\n            if (checkBox2.Checked)\n            {\n                \/\/wys\u0142anie polecenia nowej linii\n                serialPort1.Write(\"\\n\");\n            }\n\n        }<\/code><\/pre>\n\n\n\n<p>Aby terminal odbiera\u0142 dane nale\u017cy napisa\u0107 kod reaguj\u0105cy na to zdarzenie (odbioru danych). \u017beby tego dokona\u0107, nale\u017cy przej\u015b\u0107 od okna projektanta, wybra\u0107 kontrolk\u0105<em> serialport1<\/em> z formularza, w w\u0142a\u015bciwo\u015bciach zmieni\u0107 widok na zdarzenia i dwa razy klikn\u0105\u0107 na zdarzenie <em>DataReceived:<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image alignnone\"><a href=\"http:\/\/www.daniel.slask.pl\/m\/wp-content\/uploads\/2016\/04\/Zdarzenie_odbioru.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"http:\/\/www.daniel.slask.pl\/m\/wp-content\/uploads\/2016\/04\/Zdarzenie_odbioru-150x150.jpg\" alt=\"Zdarzenie odbioru z serialPort\" class=\"wp-image-508\"\/><\/a><figcaption>Zdarzenie odbioru z serialPort<\/figcaption><\/figure>\n\n\n\n<p>Po przej\u015bciu do pliku z kodem \u017ar\u00f3d\u0142owym, wn\u0119trze metody obs\u0142uguj\u0105cej zdarzenie odbioru danych wype\u0142nimy nast\u0119puj\u0105co:<\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">        \/\/zdarzenie odbioru danych\n        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)\n        {\n            \/\/sprawdzenie czy komponent gdzie wypisywane s\u0105 odebrane jest w tym samym w\u0105tku co odbi\u00f3r danych\n            if (richTextBox1.InvokeRequired)\n            {\n                \/\/utworzenie delegata (wska\u017anika do mikro funkcji) metody do wpisywania danych w komponencie z bufora odbioru danych\n                \/\/ () =&gt; oznacza lambd\u0119\n                Action act = () =&gt; richTextBox1.Text += serialPort1.ReadExisting();\n\n                \/\/wykonanie delegata dla w\u0105tku g\u0142\u00f3wnego\n                Invoke(act);   \/\/wywo\u0142anie delegata\n            }\n            else\n            {\/\/je\u017celi jest w tym samym w\u0105tku przepisz normalnie dane z bufora do komponentu\n                richTextBox1.Text += serialPort1.ReadExisting();\n            }\n\n        }<\/code><\/pre>\n\n\n\n<p>I tutaj znajduje si\u0119 cz\u0119\u015b\u0107 kodu kt\u00f3ra ma\u0142o gdzie by\u0142a opisana (dlatego postanowi\u0142em opisa\u0107 to). Co tu si\u0119 dzieje &#8211; wi\u0119c tak (prostymi s\u0142owami, jak ja to rozumiem):<br>Zdarzenie obs\u0142uguj\u0105ce odbi\u00f3r danych wykonuje si\u0119 w osobnym w\u0105tku (w tedy gdy nadlec\u0105 nowe dane &#8211; mo\u017ce ono by\u0107 w osobnym w\u0105tku, ale nie musi, dlatego jest warunek<em> if,else<\/em> i sprawdzane czy dana kontrolka jest w innym w\u0105tku, czy nie). Aby mo\u017cliwe by\u0142o wpisanie danych do tej kontrolki, w tym przypadku jest to <em>richtext,<\/em> nale\u017cy odnie\u015b\u0107 si\u0119 do w\u0105tku w kt\u00f3rym ta kontrolka si\u0119 znajduje. Do tego celu nale\u017cy utworzy\u0107 funkcj\u0119, kt\u00f3ra b\u0119dzie powodowa\u0142a wpisanie danych do <em>richtext.<\/em><br>Aby to osi\u0105gn\u0105\u0107 zostanie u\u017cyty wbudowany delegat <em>Action<\/em>. Delegat jest to najpro\u015bciej m\u00f3wi\u0105c wska\u017anik do metody. Wbudowany delegat <em>Action<\/em> jest u\u017cywany gdy chcemy u\u017cy\u0107 metody kt\u00f3ra nie b\u0119dzie zwraca\u0142a nic (typ <em>void<\/em>).<br>Aby zapisa\u0107 definicj\u0119 funkcji w jednej linijce (dla wygody) zostanie u\u017cyte wyra\u017cenie <em>lambda<\/em> w postaci<strong> () =&gt;<\/strong> , dzi\u0119ki temu nie trzeba deklarowa\u0107 nazwy tej metody w klasie.<\/p>\n\n\n\n<p>Mo\u017cna r\u00f3wnie\u017c zrobi\u0107 nie u\u017cywaj\u0105c wyra\u017cenia <em>lambda<\/em> (troch\u0119 wi\u0119cej roboty):<br>&#8211; na pocz\u0105tku klasy utworzy\u0107 metod\u0119:<\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp\">private void writeText()\n{\n     richTextBox1.Text += serialPort1.ReadExisting();\n}<\/code><\/pre>\n\n\n\n<p>&#8211; w obs\u0142udze zdarzenia warunek <em>if<\/em> mia\u0142by posta\u0107:<\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp\">\/\/utworzenie delegata\nAction act;\nact = writeText;      \/\/przypisanie naszej metody do delegata\n\/\/wykonanie delegata dla komponentu\nInvoke(act);      \/\/wywo\u0142anie delegata<\/code><\/pre>\n\n\n\n<p>Nast\u0119pnie poprzez metod\u0119 <em>Invoke<\/em> (s\u0142u\u017cy ona do wywo\u0142ania kontrolki z w\u0105tku w kt\u00f3rym zosta\u0142a ta kontrolka utworzona) zostanie wykonana nasza instrukcja przepisuj\u0105ca odebrane dane do kontrolki &#8211; czyli przej\u015bcie do w\u0105tku g\u0142\u00f3wnego i tam wykonanie tej instrukcji.<\/p>\n\n\n\n<p>W obs\u0142udze zdarzenia od odbioru jest jeszcze bezpo\u015brednie wpisanie danych do kontrolki, gdyby obs\u0142uga zdarzenia odbioru danych, jednak by\u0142a w tym samym w\u0105tku co nasza kontrolka (obs\u0142uga <em>else)<\/em><\/p>\n\n\n\n<p>Dodamy jeszcze kr\u00f3tki, kod kt\u00f3ry b\u0119dzie si\u0119 wykonywa\u0142 po zamkni\u0119ciu aplikacji &#8211; aby tak si\u0119 sta\u0142o, nale\u017cy wybra\u0107 zdarzenie <em>Closed<\/em> dla naszego formularza (z w\u0142a\u015bciwo\u015bci zdarzenia). Kod wygl\u0105da nast\u0119puj\u0105co:<\/p>\n\n\n\n<pre class=\"wp-block-code lang:c# decode:true\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">\/\/po zamkni\u0119ciu aplikacji\/formularza\nprivate void Form1_FormClosed(object sender, FormClosedEventArgs e)\n{\n\n      \/\/je\u017celi dla komponentu serialport1 jest otwarty port nale\u017cy do zamkn\u0105\u0107\n      if (serialPort1.IsOpen)\n      {\n          serialPort1.Close();\n      }\n}<\/code><\/pre>\n\n\n\n<p>Powoduje on zamkni\u0119ciu portu, w przypadku gdy nie zosta\u0142 on od\u0142\u0105czony przed wykonaniem zamkni\u0119cia aplikacji.<\/p>\n\n\n\n<p>Mam nadziej\u0119, \u017ce pomog\u0142em w zrozumieniu obs\u0142ugi tego zdarzenia, oraz \u017ce za du\u017co b\u0142\u0119d\u00f3w merytorycznych nie pope\u0142ni\u0142em &#8211; opisywa\u0142em to w\u0142asnymi s\u0142owami tak jak Ja (pocz\u0105tkuj\u0105cy) to rozumie. Gdyby by\u0142y jakiej\u015b do\u015b\u0107 istotne b\u0142\u0119dy w t\u0142umaczeniu kodu to pisa\u0107.<\/p>\n\n\n\n<p>Zach\u0119cam do komentowania i wytykania ewentualnych b\u0142\u0119d\u00f3w. W razie jakichkolwiek pyta\u0144 postaram si\u0119 na nie odpowiedzie\u0107 &#8211; na tyle na ile b\u0119d\u0119 potrafi\u0142 (dopiero z programowanie w C# raczkuj\u0119).<\/p>\n\n\n\n<p>W za\u0142\u0105czniku do tego wpisu udost\u0119pniam wam ca\u0142y projekt.<\/p>\n\n\n\n<a  data-e-Disable-Page-Transition=\"true\" class=\"download-link download-button aligncenter\" title=\"Wersja 1.0\" href=\"https:\/\/daniel.slask.pl\/m\/download\/509\/?tmstv=1788163884\" rel=\"nofollow\" id=\"download-link-509\" >\n\t<p>\n\t\tPobierz &ldquo;Cs_01_Terminal.zip&rdquo;\t<\/p>\n\t<small>Cs_01_Terminal.zip\t\t&ndash; Pobrano 1126 razy\t\t&ndash; 34,96 KB<\/small>\n<\/a>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>P.S.<br>Podobny wpis zosta\u0142 r\u00f3wnie\u017c umieszczony przeze mnie na forum <a href=\"http:\/\/www.microgeek.eu\">microgeek<\/a> &#8211; zach\u0119cam do rejestracji i cz\u0119stych wizyt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Witam. W pewnym momencie dla hobbysty elektronika przychodzi taki moment w kt\u00f3rym potrzebne jest, aby wykonane urz\u0105dzenie skomunikowa\u0142o si\u0119 z komputerem &#8211; np. aby wys\u0142a\u0107 warto\u015bci zmierzonej temperatury. Dodatkowo chcemy aby odbieraniem i interpretacj\u0105 danych zajmowa\u0142 si\u0119 dedykowany program, najlepiej&#8230;<br \/><a class=\"read-more-button\" href=\"https:\/\/daniel.slask.pl\/m\/visual-studio-2015-obsluga-komponentu-serialport-tworzymy-prosty-terminal-dla-portu-szeregowego\/\">Wi\u0119cej<\/a><\/p>\n","protected":false},"author":1,"featured_media":372,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[61,59],"tags":[33,67,65,68,64,63,66],"views":3874,"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/daniel.slask.pl\/m\/wp-content\/uploads\/2015\/12\/code-1076536_640.jpg","jetpack_shortlink":"https:\/\/wp.me\/pcPgV3-86","_links":{"self":[{"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/posts\/502"}],"collection":[{"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/comments?post=502"}],"version-history":[{"count":8,"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/posts\/502\/revisions"}],"predecessor-version":[{"id":1643,"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/posts\/502\/revisions\/1643"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/media\/372"}],"wp:attachment":[{"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/media?parent=502"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/categories?post=502"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daniel.slask.pl\/m\/wp-json\/wp\/v2\/tags?post=502"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}