Serial-Port Handler - Kann timer nicht starten

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von gfcwfzkm.

    Serial-Port Handler - Kann timer nicht starten

    Hallo,

    ich habe eine Sub, die jedes mal aufgerufen wird wenn über die Serielle Schnittstelle Daten reinkommen.
    Dort starte ich ein Timer. Jedoch wird der Timer nicht gestartet und es passiert nicht das was ich möchte.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Drawing2D
    2. Imports System.IO.Ports
    3. Imports System ' BitConverter-Klasse
    4. Imports System.Collections ' BitArray-Klasse
    5. Imports System.Runtime.CompilerServices ' Extension-Attribut
    6. Imports System.Net.NetworkInformation
    7. Public Class Form1
    8. Dim i As Integer
    9. Dim y As Integer
    10. Dim pen1 As New System.Drawing.Pen(Color.Black, 1)
    11. Dim fnt As Font = New Font("Courier New", 8)
    12. Dim DIGIT As Font = New Font("Quartz MS", 20)
    13. Dim _sp As New SerialPort()
    14. Public COMPORT As String
    15. Public Baudrate As Integer
    16. Dim bmp As New Bitmap(128, 64, Imaging.PixelFormat.Format24bppRgb)
    17. Dim g As System.Drawing.Graphics
    18. Dim cdrive As System.IO.DriveInfo
    19. Dim length As Integer = 65
    20. Dim spos As Integer = 28
    21. Dim NUM As Integer = 0
    22. Dim selected As Integer = 1
    23. Function MENU(ByVal Control As PictureBox, ByVal num As Integer)
    24. ' Grafikbereich bereitstellen
    25. g = Graphics.FromImage(bmp)
    26. ' Textrenderer herunterschrauben (Keine Graustufen)
    27. g.TextRenderingHint = Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit
    28. ' Grafikbereich löschen (mit "Weiss" übermalen)
    29. Dim clearall As New Rectangle(0, 0, 128, 64)
    30. Dim clearallbrush As New LinearGradientBrush(clearall, Color.White, Color.White, LinearGradientMode.Horizontal)
    31. g.FillRectangle(clearallbrush, clearall)
    32. ' Menü-Bereich Zeichnen
    33. Dim menubl As New Rectangle(0, 0, 128, 14)
    34. Dim menublbrush As New LinearGradientBrush(menubl, Color.Black, Color.Black, LinearGradientMode.Horizontal)
    35. g.FillRectangle(menublbrush, menubl)
    36. g.DrawString("MENU", fnt, Brushes.White, 50, 0)
    37. ' Verfügbare Funktionen anzeigen
    38. g.DrawString("PC-INFO", fnt, Brushes.Black, 40, 15)
    39. g.DrawString("DIGI-CLOCK", fnt, Brushes.Black, 30, 30)
    40. ' "Ausgewählt"-Feld anzeigen
    41. g.DrawString("->", fnt, Brushes.Black, 5, (15 * num))
    42. g.DrawRectangle(pen1, 0, 15 * num, 127, 14)
    43. 'Grafik "konvertieren" und senden
    44. BitmapToBLCD(bmp)
    45. Return bmp
    46. End Function
    47. Function Digital_Clock(ByVal Control As PictureBox)
    48. ' Grafikbereich bereitstellen
    49. g = Graphics.FromImage(bmp)
    50. ' Textrenderer herunterschrauben (Keine Graustufen)
    51. g.TextRenderingHint = Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit
    52. ' Grafikbereich löschen (mit "Weiss" übermalen)
    53. Dim clearall As New Rectangle(0, 0, 128, 64)
    54. Dim clearallbrush As New LinearGradientBrush(clearall, Color.White, Color.White, LinearGradientMode.Horizontal)
    55. g.FillRectangle(clearallbrush, clearall)
    56. ' Ein "Weisses Rechteck" definieren
    57. Dim cleararea As New Rectangle(1, 29, 126, 34)
    58. Dim _cleararea As New LinearGradientBrush(cleararea, Color.White, Color.White, LinearGradientMode.Horizontal)
    59. ' Ein "Schwarzes Rechteck" definieren
    60. Dim filled As New Rectangle(0, 28, 128, 36)
    61. Dim _filled As New LinearGradientBrush(filled, Color.Black, Color.Black, LinearGradientMode.Horizontal)
    62. ' Datum usw auslesen
    63. Dim Jahr As Integer = Date.Now.Year
    64. Dim _Monat As Integer = Date.Now.Month
    65. Dim _Tag As Integer = Date.Now.DayOfWeek
    66. ' Monats-Tabelle
    67. Dim Monat_Liste() As String = {"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"}
    68. ' Tag-Tabelle
    69. Dim Tag_Liste() As String = {"Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"}
    70. ' Tag in der Tabelle auslesen und in einer Variable abspeichern
    71. Dim Monat As String = Monat_Liste(_Monat - 1)
    72. Dim Tag As String = Tag_Liste(_Tag - 1)
    73. ' Schwarzer Rand zeichnen
    74. g.FillRectangle(_filled, filled)
    75. g.FillRectangle(_cleararea, cleararea)
    76. 'Datum und Uhr zeichnen
    77. g.DrawString(Tag & ", den " & Date.Now.Day.ToString & ".", fnt, Brushes.Black, 1, 1)
    78. g.DrawString(Monat & " " & Jahr.ToString, fnt, Brushes.Black, 1, 12)
    79. g.DrawString(Date.Now.ToString("HH:mm:ss"), DIGIT, Brushes.Black, 1, 27)
    80. 'Grafik "konvertieren" und senden
    81. BitmapToBLCD(bmp)
    82. Return bmp
    83. End Function
    84. Function PCInfo(ByVal Control As PictureBox)
    85. ' Zeilen definieren
    86. Dim zeile1 As Integer = 4
    87. Dim zeile2 As Integer = 16
    88. Dim zeile3 As Integer = 28
    89. Dim zeile4 As Integer = 40
    90. ' Grafikbereich bereitstellen
    91. g = Graphics.FromImage(bmp)
    92. ' Textrenderer herunterschrauben (Keine Graustufen)
    93. g.TextRenderingHint = Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit
    94. ' Grafikbereich löschen (mit "Weiss" übermalen)
    95. Dim clearall As New Rectangle(0, 0, 128, 64)
    96. Dim clearallbrush As New LinearGradientBrush(clearall, Color.White, Color.White, LinearGradientMode.Horizontal)
    97. g.FillRectangle(clearallbrush, clearall)
    98. ' Kategorieren und Leere Ladebalken zeichen
    99. g.DrawString("CPU", fnt, Brushes.Black, 0, zeile1 - 1)
    100. g.DrawRectangle(pen1, spos, zeile1, length, 10)
    101. g.DrawString("RAM", fnt, Brushes.Black, 0, zeile2 - 1)
    102. g.DrawRectangle(pen1, spos, zeile2, length, 10)
    103. g.DrawString("DSK", fnt, Brushes.Black, 0, zeile3 - 1)
    104. g.DrawRectangle(pen1, spos, zeile3, length, 10)
    105. g.DrawString("NET", fnt, Brushes.Black, 0, zeile4 - 1)
    106. ' -CPU-
    107. ' CPU-Infos auslesen
    108. i = PerformanceCounter1.NextValue
    109. y = (length * i) / 100
    110. If y = 0 Then y = 1
    111. Dim rect As New Rectangle(spos, zeile1, y, 10)
    112. g.DrawString(i.ToString + "%", fnt, Brushes.Black, 95, zeile1 - 1)
    113. Dim gradientBrush As New LinearGradientBrush(rect, Color.Black, Color.Black, LinearGradientMode.Horizontal)
    114. g.FillRectangle(gradientBrush, rect)
    115. ' -RAM-
    116. ' RAM-Infos auslesen
    117. i = PerformanceCounter2.NextValue
    118. y = (length * i) / 100
    119. If y = 0 Then y = 1
    120. rect = New Rectangle(spos, zeile2, y, 10)
    121. g.DrawString(i.ToString + "%", fnt, Brushes.Black, 95, zeile2 - 1)
    122. gradientBrush = New LinearGradientBrush(rect, Color.Black, Color.Black, LinearGradientMode.Horizontal)
    123. g.FillRectangle(gradientBrush, rect)
    124. ' -DISK C:\-
    125. ' DSK-Infos auslesen
    126. cdrive = My.Computer.FileSystem.GetDriveInfo("C:\")
    127. i = (100 * (cdrive.TotalSize - cdrive.AvailableFreeSpace) / cdrive.TotalSize)
    128. y = (length * i) / 100
    129. If y = 0 Then y = 1
    130. rect = New Rectangle(spos, zeile3, y, 10)
    131. g.DrawString(i.ToString + "%", fnt, Brushes.Black, 95, zeile3 - 1)
    132. gradientBrush = New LinearGradientBrush(rect, Color.Black, Color.Black, LinearGradientMode.Horizontal)
    133. g.FillRectangle(gradientBrush, rect)
    134. 'Netzwerk Up- & Download lesen
    135. Dim up As Integer = Math.Round(PerformanceCounter3.NextValue / 1024)
    136. Dim dn As Integer = Math.Round(PerformanceCounter4.NextValue / 1024)
    137. Dim speed As String = " kB/s"
    138. 'Überprüfung, ob die Variable "Zu gross" ist und entsprechend umrechnen...
    139. If up > 9999 Then
    140. up = Math.Round(up / 1024)
    141. speed = " MB/s"
    142. End If
    143. If dn > 9999 Then
    144. dn = Math.Round(dn / 1024)
    145. speed = " MB/s"
    146. End If
    147. g.DrawString("UP " + up.ToString + speed, fnt, Brushes.Black, 25, zeile4 - 1)
    148. g.DrawString("DN " + dn.ToString + speed, fnt, Brushes.Black, 25, zeile4 + 9)
    149. 'Grafik "konvertieren" und senden
    150. BitmapToBLCD(bmp)
    151. Return bmp
    152. End Function
    153. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    154. If NUM = 1 Then PictureBox1.Image = PCInfo(PictureBox1)
    155. If NUM = 2 Then PictureBox1.Image = Digital_Clock(PictureBox1)
    156. End Sub
    157. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    158. Call _UP()
    159. End Sub
    160. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    161. Call _Enter()
    162. End Sub
    163. Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    164. Call DOWN()
    165. End Sub
    166. Public Sub _UP()
    167. If NUM = 0 Then
    168. ' Menü "Hoch"
    169. If selected = 1 Then Exit Sub
    170. selected = selected - 1
    171. Debug.Print(selected.ToString)
    172. PictureBox1.Image = MENU(PictureBox1, selected)
    173. ElseIf NUM = 2 Then
    174. 'Analog- /Digitaluhr switcher
    175. End If
    176. End Sub
    177. Public Sub _Enter()
    178. If NUM = 0 Then
    179. ' Im Menü die "LCD-App" öffnen & anzeigen
    180. NUM = selected
    181. Timer1.Start()
    182. Else
    183. ' Timer stoppen und zum Menü zurückkehren
    184. Timer1.Stop()
    185. NUM = 0
    186. PictureBox1.Image = MENU(PictureBox1, selected)
    187. End If
    188. End Sub
    189. Public Sub DOWN()
    190. If NUM = 0 Then
    191. ' Menü "Runter"
    192. If selected = 2 Then Exit Sub
    193. selected = selected + 1
    194. Debug.Print(selected.ToString)
    195. PictureBox1.Image = MENU(PictureBox1, selected)
    196. ElseIf NUM = 2 Then
    197. 'Analog- /Digitaluhr switcher
    198. End If
    199. End Sub
    200. Public Sub BitmapToBLCD(ByVal _bmp As Bitmap)
    201. ' Bitmap-Konvertierer
    202. ' Konvertiert ein 128x64 Bitmap in das richtige
    203. ' Format für das LCD-Display um.
    204. Dim x As Integer = 0
    205. Dim y As Integer = 0
    206. Dim page As Integer = 0
    207. Dim result As Integer = 0
    208. Dim col As Color
    209. Dim r, g, b, gem As Integer
    210. _sp.Write("S")
    211. Do While (Not page = 8)
    212. ' Pixel einlesen
    213. col = _bmp.GetPixel(x, y + (8 * page))
    214. ' Pixel in die Grundfarben aufteilen
    215. r = col.R
    216. g = col.G
    217. b = col.B
    218. ' Diese Zusammenrechnen und Teilen
    219. gem = (r + g + b) / 3
    220. ' Vergleichen, ob das Pixel "Hell" oder "dunkel" ist
    221. If Not gem > 128 Then result = result + (2 ^ y) 'Schwarz
    222. y += 1
    223. If y = 8 Then
    224. x += 1
    225. y = 0
    226. 'Hier wird die Sache gesendet
    227. Dim tbyte As Byte() = BitConverter.GetBytes(result)
    228. _sp.Write(tbyte, 0, 1)
    229. 'result clearen
    230. result = 0
    231. End If
    232. ' Überprüfen, ob die aktuelle Page voll ist (Zeilenende)
    233. If x = 128 Then
    234. page += 1
    235. x = 0
    236. End If
    237. Loop
    238. X:
    239. End Sub
    240. Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    241. ' SerialPort schliessen
    242. _sp.Close()
    243. End Sub
    244. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    245. ' Setup-Form Anzeigen
    246. Me.Hide()
    247. Form2.ShowDialog()
    248. ' Zeichnungsbereich beschreiben
    249. Dim xyz As Boolean = True
    250. Dim xc As Integer = 0
    251. Dim yc As Integer = 0
    252. While (xyz)
    253. bmp.SetPixel(xc, yc, Color.White)
    254. xc += 1
    255. If xc = 128 Then
    256. xc = 0
    257. yc += 1
    258. End If
    259. If yc = 64 Then
    260. xyz = False
    261. End If
    262. End While
    263. ' SerialPort-Setup
    264. _sp.PortName = COMPORT
    265. _sp.BaudRate = Baudrate
    266. _sp.Parity = Parity.None
    267. _sp.DataBits = 8
    268. _sp.StopBits = StopBits.One
    269. _sp.Handshake = Handshake.XOnXOff
    270. _sp.Open()
    271. ' "Interrupt" für SerialPort_DataReceived
    272. AddHandler _sp.DataReceived, AddressOf DataReceivedHandler
    273. PictureBox1.Image = bmp
    274. PictureBox1.Image = MENU(PictureBox1, selected)
    275. End Sub
    276. Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
    277. Dim sp As SerialPort = CType(sender, SerialPort)
    278. 'Daten lesen
    279. Dim indata As String = sp.ReadExisting()
    280. Debug.Print(indata.ToString() + "-" + indata.Length.ToString)
    281. ' Empfangene Daten durchgehen
    282. Select Case indata.ToLower.Trim
    283. Case "`"
    284. Call _UP()
    285. Exit Sub
    286. Case "b"
    287. Call _Enter()
    288. Exit Sub
    289. Case "d"
    290. Call DOWN()
    291. Exit Sub
    292. End Select
    293. End Sub
    294. Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
    295. Call BitmapToBLCD(bmp)
    296. End Sub
    297. End Class

    (Vollständigkeitshalber habe ich den ganzen Code drauf)

    Es geht um die Sub DataReceivedHandler (Zeile 311) und um die Sub _Enter (Zeile 204).
    Wenn ich die Buttons benutze, funktioniert es einwandfrei, halt per SerialPort wills nicht. Es kommen keine Fehler, nix. Aber der Timer reagiert nicht, wenn dieser über die Sub _Enter von der Sub DataReceivedHandler 'gestartet' wird.

    Kennt jemand die Lösung bitte?

    mfg

    gfc
    Habe mir den Code jetzt nicht angesehen. Aber DataReceived wird nicht gleich beim ersten Byte erhöht. Das ist abhängig vom Threshold Parameter. Entweder diesen auf 1 setzen (dann wird aber bei jedem Byte das Ereignis ausgelöst) oder so, wie ich es mache. Ich prüfe per Timer die Daten im Puffer und wenn diese größer 0 ist, dann sind Daten eingetroffen.
    Gruß
    Peterfido

    Keine Unterstützung per PN!
    Das ist nicht das Problem, das funktioniert RushDen.

    @peterfido
    Er empfängt die Daten. Nur wenn ich von diesem Thread aus den Timer starten will, passiert nix.
    Edit://
    Habs nun so eingerichtet, das der Timer immer läuft. Jedoch kann es passieren, das z.B. die Menu-Sub in das Bitmap eingreifen will, obwohl es noch von der Bitmap-Konverterklasse bearbeitet wird und so entsteht wieder ein neuer Fehler :/

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „gfcwfzkm“ ()

    gfcwfzkm schrieb:

    Nur wenn ich von diesem Thread aus den Timer starten will, passiert nix.

    Hast doch die Lösung schon selbst gesagt. ;) Du musst es über Invoke() machen, weil SerialPort-Handler in einem anderen Thread läuft als die GUI.

    Trotzdem solltest du den Tipp von @RushDen: berücksichtigen, "Form2" ist eine Klasse und kein Objekt der Form.
    :) Danke, genau das ist es, jetzt funzt es.
    Und habe den Tipp um eine neue Frm zu öffnen berücksichtigt.

    mfg

    gfc