Hallo an alle,
ich möchte mittels der MVCOM-Befehle mit einem µController kommunizieren. Das Problem ist die Erfassung der vom µC gesendeten Daten.
Normalerweise benutze ich eine Schleife, die ständig die RS232-Schnittstelle abfragt, ob Daten vom µC gesendet wurden.
Gitb es keine Möglichkeit über einen Interrupt, wie z.B. in VisualBasic 'OnComm', auf gesendete Daten vom µC zu reagieren.
serielle Schnittstelle
-
- Beiträge: 100
- Registriert: 06.11.2004 11:23
- Computerausstattung: PB 5.30 (x64) Win7
- Wohnort: Österreich
Habe das auf meiner Platte gefunden ... ist für Atmel µController
ist mit api und nicht MVCom .... aber müsste sich einfach umschreiben lassen
PS. war damals nur ein kurzer Versuch also (Quick & Dirty)
vielleicht hilft es
ist mit api und nicht MVCom .... aber müsste sich einfach umschreiben lassen
PS. war damals nur ein kurzer Versuch also (Quick & Dirty)
vielleicht hilft es
Code: Alles auswählen
#TIMEOUT = 1000
Global handle
Procedure open_port()
handle = CreateFile_("COM2:", #GENERIC_READ | #GENERIC_WRITE,0, 0, #OPEN_EXISTING, 0, 0)
If handle = #INVALID_HANDLE_VALUE
Debug("Couldn't open serial device!")
Else
ct.COMMTIMEOUTS
ct\ReadIntervalTimeout = 0
ct\ReadTotalTimeoutMultiplier = 0
ct\ReadTotalTimeoutConstant = 0
ct\WriteTotalTimeoutMultiplier = 0
ct\WriteTotalTimeoutConstant = 0
SetCommTimeouts_(handle,@ct)
DCB.dcb
dcb\DCBlength=8
dcb\BaudRate=9600
;BPCDD STOIENR AD2345678901234567
dcb\fbits= %00000100000001000000000000000000
dcb\wReserved=0
dcb\XonLim=2048
dcb\XoffLim=2048
dcb\ByteSize=8
dcb\Parity=0
dcb\StopBits=0
dcb\XonChar=$11
dcb\XoffChar=$13
dcb\ErrorChar=0
dcb\EofChar=0
dcb\EvtChar=0
dcb\wReserved1=0
SetCommState_(handle,@dcb)
PurgeComm_(handle,#PURGE_TXCLEAR|#PURGE_RXCLEAR)
x.l
GetCommMask_(handle,@x)
SetCommMask_(handle, 0)
ClearCommBreak_(handle)
SetCommBreak_(handle)
Delay(100)
EndIf
EndProcedure
Procedure setA(bit);Output bit on B channel
If bit; = 1
EscapeCommFunction_(handle,#SETRTS)
Else
EscapeCommFunction_(handle,#CLRRTS)
EndIf
EndProcedure
Procedure setB(bit);Output bit on A channel
If bit; = 1
EscapeCommFunction_(handle, #SETDTR)
Else
EscapeCommFunction_(handle, #CLRDTR)
EndIf
EndProcedure
Procedure getA();Input bit on A channel
status.l
GetCommModemStatus_(handle,@status)
If (#MS_DSR_ON & status) <> 0
r = #True
Else
r = #False
EndIf
ProcedureReturn r
EndProcedure
Procedure getB();Input bit on B channel
status.l
GetCommModemStatus_(handle,@status)
If (#MS_CTS_ON & status) <> 0
ProcedureReturn = #True
Else
ProcedureReturn = #False
EndIf
EndProcedure
Procedure close_port()
CloseHandle_(handle)
EndProcedure
Procedure waitA(bit);Wait For pin To settle
i = #TIMEOUT
While (i > 0) And (bit <> getA() )
i-1
If i = 0
Debug("ERROR: Signal A is stuck!")
EndIf
Wend
EndProcedure
;Define the SPI programming Interface signals
Procedure GETMISO()
ProcedureReturn getB()
EndProcedure
Procedure SCK(X)
setA(X)
EndProcedure
Procedure MOSI(X)
setB(X)
EndProcedure
Procedure WAITSCK(X)
waitA(X)
EndProcedure
Procedure spiwr(cin)
For j = 7 To 0 Step -1
SCK(0)
If ((cin>>j)&1)
MOSI(1)
Else
MOSI(0)
EndIf
WAITSCK(0)
SCK(1)
WAITSCK(1)
cout = (cout<<1)|GETMISO()
Next j
ProcedureReturn cout
EndProcedure
Procedure spiwr4(byte1,byte2,byte3,byte4)
spiwr(byte1)
spiwr(byte2)
spiwr(byte3)
ProcedureReturn spiwr(byte4)
EndProcedure
Procedure eraseprogram()
spiwr4($AC,$80,0,0)
Delay(20); // At least 9 ms delay after chip erase
EndProcedure
Procedure readprogram(addr)
ProcedureReturn (spiwr4($28, (addr >> 8), addr & $ff, 0) << 8) + spiwr4($20, (addr >> 8), addr & $ff,0)
EndProcedure
Procedure loadprogram(addr,hi,lo)
spiwr4($40, 0, addr & $1f, lo); // load low byte first!
spiwr4($48, 0, addr & $1f, hi);
EndProcedure
Procedure writeprogram(pageaddr)
spiwr4($4c, (pageaddr >> 8), pageaddr & $ff, 0);
Delay(20); // At least 5 ms delay after writing a page
EndProcedure
; -------- MAIN
open_port()
MOSI(1)
SCK(0)
spiwr($AC)
spiwr($53)
If (spiwr($00) <> $53)
Debug "ERROR: Programming enable command didn't respond."
Else
Debug "Programming enable command worked fine."
EndIf
spiwr($00)
Debug "Vendor code: "+Hex(spiwr4($30,0,0,0))
Debug "Part family and memory size: "+Hex(spiwr4($30,0,1,0))
Debug "Part number: "+Hex(spiwr4($30,0,2,0))
Debug "Calibration byte: "+Hex(spiwr4($38,0,0,0))
eraseprogram()
Debug "Address 0: "+ Hex(readprogram(0))
Debug "Programming first instruction to 0x1234. "
loadprogram(0,$12,$34)
writeprogram(0)
Debug "Address 0: "+Hex(readprogram(0))
close_port()
Du kannst das mit WaitCommEvent machen. So wie ich es in dem
Beispiel machen, blockiert aber die Funktion. Deshalb in einem Thread.
Man kann es auch anderst machen, das ist aber aufwendiger.
Viel Spaß
Georg
Beispiel machen, blockiert aber die Funktion. Deshalb in einem Thread.
Man kann es auch anderst machen, das ist aber aufwendiger.
Code: Alles auswählen
;PureBasic 3.94
Declare ThreadEmpf()
Global ComPort.s , hCom , ThreadID , ComEvent ,BufferRx.s , CountBuffer , ComError
Global IDWndMain , hWndMain ,StrEmpf
;Die benötigten Strukturen
Global dcb.DCB ;Einstellungen der Schnittstelle
Global ccf.COMMCONFIG
Global o.OVERLAPPED ;Damit andere Prozesse Zugriff haben. Vorletzter Parameter bei CreateFile
Global timeouts.COMMTIMEOUTS
BufferRx = Space(255); Hier schreibt ReadFile die empfangenden Daten rein
ComPort = "COM2" ;
FillMemory_(@ccf\dcb, SizeOf(dcb), 0);DCB-Struktur mit Nullen füllen
dcb\DCBlength = SizeOf(DCB); Größe der Struktur ermitteln
ccf\dwSize = SizeOf(COMMCONFIG) + dcb\DCBlength ; Größe der Struktur ermitteln
;Einstellungen aus dem Gerätemanager verwenden.
; Man kann die Struktur aber auch selbst füllen. Z.Bsp mit "BuildCommDCB", oder von Hand
GetDefaultCommConfig_(ComPort, @ccf, @ccf\dwSize)
SetDefaultCommConfig_(ComPort, @ccf, @ccf\dwSize)
;Comport öffnen.;z.Bsp Com2. Das "\\.\" ist nur für ComPortnummern über 12 erforderlich
hCom = CreateFile_("\\.\"+ComPort, #GENERIC_READ |#GENERIC_WRITE ,0,0, #OPEN_EXISTING ,#FILE_FLAG_OVERLAPPED ,0)
If hCom <> #INVALID_HANDLE_VALUE
SetCommMask_(hCom,#EV_RXCHAR );Event festlegen. Wenn ein Byte emfangen wird, wird ein Event ausgelöst
SetCommState_(hCom,@ccf\dcb) ; Einstellungen übernehmen
SetupComm_(hCom, 255,255);Empangs- und SendeBuffer einstellen
GetCommTimeouts_( hCom,@timeouts)
timeouts\ReadIntervalTimeout = #MAXWORD
timeouts\ReadTotalTimeoutMultiplier = 0
timeouts\ReadTotalTimeoutConstant = 300 ; Wartet 300ms
timeouts\WriteTotalTimeoutMultiplier = 0
timeouts\WriteTotalTimeoutConstant = 0
SetCommTimeouts_( hCom,@timeouts)
ClearCommError_(hCom,@ComError,#NULL); Löscht alle evt. Fehler
PurgeComm_(hCom,#PURGE_TXCLEAR | #PURGE_RXCLEAR);Leert die Buffer
ThreadID = CreateThread(@ThreadEmpf(),0);Thread starten
Else
MessageRequester("","ComPort kann nicht geöffnet werden")
End ;Wenn man will, Programm beenden
EndIf
;Jetzt die Threadfunktion. An dieser Stelle im Code muss sie aber declariert werden!!
Procedure ThreadEmpf()
;So wie " WaitCommEvent" hier verwendet wird , blockiert sie den Thread bis das Event eintritt. Man kann es auch anderst machen.
;Aber aufwendiger
Repeat
ClearCommError_(hCom,@ComError,#NULL)
WaitCommEvent_(hCom, @ComEvent,@o);
;Dann mit Readfile den Buffer auslesen. Der dritte Parameter gibt an, wieviele Byte gelesen werden sollen.
;ReadFile wartet dann solange bis alle Byte empfangen wurde. Geht ein Byte verloren, dann blockiert ReadFile.
;Um das zu verhinder kann man mit "SetCommTimeouts" Timeouts setzen.
;Man kann den dritten Parameter auch auf 1 setzen und in einer Schleife solange lesen bis der Speicher leer ist..
;"ClearCommError" gibt vorhandene Byte im Buffer zurück.
ReadFile_(hCom, BufferRx,4,@CountBuffer,0)
SetGadgetText(StrEmpf , BufferRx)
ForEver
EndProcedure
IDWndMain =OpenWindow(#PB_Any,0,0,380,160, #PB_Window_SystemMenu | #PB_Window_WindowCentered ,"USB zu RS232 Konvertertest")
hWndMain = WindowID(IDWndMain)
CreateGadgetList(hWndMain)
StrEmpf = StringGadget(#PB_Any,10,10,360,140,"")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_CloseWindow
If EventWindowID() = IDWndMain
SetCommMask_(hCom,0 ) ;Maske auf Null setzten
KillThread(hThread) ; Thread beenden
CloseHandle_(hThread); ThreadHandle schließen. Ob bei PB4.0 noch erforderlich ?
CloseHandle_(hCom) ; ComPort schließen.
End
EndIf
EndSelect
ForEver
End
Georg