snafu
15.04.2011, 06:57
Hi all,
Hier zu eurer Verfügung ein Progrämmchen, mit dem ein AVR Befehle wie ein Modem "at irgendwas" annehmen kann. Die Eingabezeile wird in bis zu acht Worte zu 16 Zeichen zerlegt, die man dann untersuchen und darauf Unterprogramme starten kann.
Ich brauchte das, weil ich mehrere Controller über Bluetooth via meinem Android-Telefon erreichen wollte.
Gruss
snafu
'receiving input from serial interface, test for leading "at" string and
'interprete various commands to be executed in subroutines
$crystal = 20000000
$regfile = "m168def.dat"
$baud = 38400
Config Portc.4 = Output
Weiss_0 Alias Portc.4
Config Portc.5 = Output
Weiss_1 Alias Portc.5
Config Portd = Output
Config Lcdbus = 4
Config Lcd = 20 * 2 'configure lcd screen
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Rem with the config lcdpin statement you can override the compiler settings
'all neccessary for interrupt input of serial chars
Dim Ser_rx_char As String * 1
Dim Ser_rx_char_byte As Byte
Dim Serialinput As String * 100 'int routine is collecting input string in this variable
Dim New_input_string As String * 100 'if complete string received it will be saved here
Dim Parse_string As String * 100 'parser gets this string
Dim New_input_string_received As Bit
Dim Input_zaehl As Byte
Dim String_len As Byte
'variablen für den parser
Dim Parser_string_len As Byte
Dim Parser_split_pointer As Byte
Dim Parse_wd(8) As String * 16
Dim Parse_wd_counter As Byte
'hardware UART is used
Config Serialin = Buffered , Size = 10 'PD0 = TXO, PD1 = RXI
'10 Byte input buffer
Enable Interrupts 'neccessary because uart fires interrupt if new char received
'-------------- INIT -----------------------------------------------------------
Cls
Upperline
'---"01234567890123456789"
Lcd "PARSER"
Lowerline
Lcd "0.32"
Cursor Off Noblink
Serialinput = "" 'Inputpuffer reset
New_input_string = "" 'input string reset reset
New_input_string_received = 0 'flag reset
Print "--- RESET ---"
'-------------- MAIN -----------------------------------------------------------
Do
'-------------- fetch waiting chars
If Ischarwaiting() = 1 Then 'poll buffer of uart routine
Gosub Serial_zeichen_abholen
End If
'-------------- test for new input string
If New_input_string_received = 1 Then 'complete string was received
New_input_string_received = 0 'flag reset
Parse_string = New_input_string 'prepare string for parser
Print
Gosub Parse_input_string 'analyze words in received string
End If
Loop
'-------------- end MAIN -------------------------------------------------------
'-------------- subroutines ----------------------------------------------------
Parse_input_string:
'-------------- parse input string
For Parse_wd_counter = 1 To 8
'strip leading blanks
While Left(parse_string , 1) = " "
Parser_string_len = Len(parse_string)
Parser_string_len = Parser_string_len - 1
Parse_string = Right(parse_string , Parser_string_len)
Wend
'find first blank char
Parser_split_pointer = Instr(parse_string , " ") 'look for first blank character
If Parser_split_pointer > 0 Then '= 0 if no blank found
Parser_split_pointer = Parser_split_pointer - 1
End If
'isolate first parse word
If Parser_split_pointer > 16 Then 'avoid to set Parse_wd(n) with strings longer than 16 chars
Parser_split_pointer = 16
End If
Parse_wd(parse_wd_counter) = Mid(parse_string , 1 , Parser_split_pointer)
'reduce parse string to remaining chars which are still due to parse
If Parser_split_pointer > 0 Then '
Parser_split_pointer = Parser_split_pointer + 1
Parser_string_len = Len(parse_string)
Parser_string_len = Parser_string_len - Parser_split_pointer
Parse_string = Right(parse_string , Parser_string_len)
Else 'last command word in parse string found
Parse_string = ""
End If
'Print "[" ; Parse_wd(parse_wd_counter) ; "]";
Next
'-------------- interprete commands with arguments
Select Case Parse_wd(1)
Case "at" : Gosub Attention
Case Else
Print "missing at string, received: [" ; Parse_wd(1) ; "]"
Print "send [at command argument]"
End Select
Return
'-------------- commands
Attention:
Select Case Parse_wd(2)
Case "led0" : Gosub Led0
Case "led1" : Gosub Led1
Case Else
Print "missing or wrong command, received: [" ; Parse_wd(2) ; "]"
Print "send [led0 | led1]"
End Select
Return
Led0:
Select Case Parse_wd(3)
Case "on"
Weiss_0 = 1
Print "ok"
Case "off"
Weiss_0 = 0
Print "ok"
Case Else
Print "missing or wrong argument, received: [" ; Parse_wd(3) ; "]"
Print "send [on | off]"
End Select
Return
Led1:
Select Case Parse_wd(3)
Case "on"
Weiss_1 = 1
print "ok"
Case "off"
Weiss_1 = 0
Print "ok"
Case Else : Print "missing or wrong argument, received: [" ; Parse_wd(3) ; "]"
End Select
Return
'-------------- receive serial characters --------------------------------------
' collect received chars and assemble them to input string
Serial_zeichen_abholen:
If Ischarwaiting() = 1 Then
Ser_rx_char = Inkey()
Ser_rx_char_byte = Asc(ser_rx_char)
String_len = Len(serialinput)
Select Case Ser_rx_char_byte
Case 13 'return chra was recognized
New_input_string = Serialinput 'copy string for main routine
New_input_string_received = 1 'set flag that new string is ready
Serialinput = "" 'reset all for new string
Ser_rx_char = ""
Case 127 'backspace - char
If String_len > 0 Then
Print Chr(8) ; " " ; Chr(8); 'android recognizes no chr(127), therefore i use backspace, writing blank, backspace again
String_len = String_len - 1
If String_len = 0 Then 'because "left" returns even with (string,0) one char
Serialinput = ""
Else
Serialinput = Left(serialinput , String_len)
End If
End If
Case Is < 32 'drop all ather control chars
Ser_rx_char = ""
Case Is > 127
Ser_rx_char = ""
Case Else 'valid input char
If String_len < 100 Then 'room left in input string?
Serialinput = Serialinput + Ser_rx_char 'append received char
Print Ser_rx_char ; 'and echo via serial
Else 'abort if 99 chars without enter received
New_input_string = Serialinput 'then string will be closed without enter
Serialinput = ""
New_input_string_received = 1
Ser_rx_char = ""
End If
End Select
End If
Return
Hier zu eurer Verfügung ein Progrämmchen, mit dem ein AVR Befehle wie ein Modem "at irgendwas" annehmen kann. Die Eingabezeile wird in bis zu acht Worte zu 16 Zeichen zerlegt, die man dann untersuchen und darauf Unterprogramme starten kann.
Ich brauchte das, weil ich mehrere Controller über Bluetooth via meinem Android-Telefon erreichen wollte.
Gruss
snafu
'receiving input from serial interface, test for leading "at" string and
'interprete various commands to be executed in subroutines
$crystal = 20000000
$regfile = "m168def.dat"
$baud = 38400
Config Portc.4 = Output
Weiss_0 Alias Portc.4
Config Portc.5 = Output
Weiss_1 Alias Portc.5
Config Portd = Output
Config Lcdbus = 4
Config Lcd = 20 * 2 'configure lcd screen
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Rem with the config lcdpin statement you can override the compiler settings
'all neccessary for interrupt input of serial chars
Dim Ser_rx_char As String * 1
Dim Ser_rx_char_byte As Byte
Dim Serialinput As String * 100 'int routine is collecting input string in this variable
Dim New_input_string As String * 100 'if complete string received it will be saved here
Dim Parse_string As String * 100 'parser gets this string
Dim New_input_string_received As Bit
Dim Input_zaehl As Byte
Dim String_len As Byte
'variablen für den parser
Dim Parser_string_len As Byte
Dim Parser_split_pointer As Byte
Dim Parse_wd(8) As String * 16
Dim Parse_wd_counter As Byte
'hardware UART is used
Config Serialin = Buffered , Size = 10 'PD0 = TXO, PD1 = RXI
'10 Byte input buffer
Enable Interrupts 'neccessary because uart fires interrupt if new char received
'-------------- INIT -----------------------------------------------------------
Cls
Upperline
'---"01234567890123456789"
Lcd "PARSER"
Lowerline
Lcd "0.32"
Cursor Off Noblink
Serialinput = "" 'Inputpuffer reset
New_input_string = "" 'input string reset reset
New_input_string_received = 0 'flag reset
Print "--- RESET ---"
'-------------- MAIN -----------------------------------------------------------
Do
'-------------- fetch waiting chars
If Ischarwaiting() = 1 Then 'poll buffer of uart routine
Gosub Serial_zeichen_abholen
End If
'-------------- test for new input string
If New_input_string_received = 1 Then 'complete string was received
New_input_string_received = 0 'flag reset
Parse_string = New_input_string 'prepare string for parser
Gosub Parse_input_string 'analyze words in received string
End If
Loop
'-------------- end MAIN -------------------------------------------------------
'-------------- subroutines ----------------------------------------------------
Parse_input_string:
'-------------- parse input string
For Parse_wd_counter = 1 To 8
'strip leading blanks
While Left(parse_string , 1) = " "
Parser_string_len = Len(parse_string)
Parser_string_len = Parser_string_len - 1
Parse_string = Right(parse_string , Parser_string_len)
Wend
'find first blank char
Parser_split_pointer = Instr(parse_string , " ") 'look for first blank character
If Parser_split_pointer > 0 Then '= 0 if no blank found
Parser_split_pointer = Parser_split_pointer - 1
End If
'isolate first parse word
If Parser_split_pointer > 16 Then 'avoid to set Parse_wd(n) with strings longer than 16 chars
Parser_split_pointer = 16
End If
Parse_wd(parse_wd_counter) = Mid(parse_string , 1 , Parser_split_pointer)
'reduce parse string to remaining chars which are still due to parse
If Parser_split_pointer > 0 Then '
Parser_split_pointer = Parser_split_pointer + 1
Parser_string_len = Len(parse_string)
Parser_string_len = Parser_string_len - Parser_split_pointer
Parse_string = Right(parse_string , Parser_string_len)
Else 'last command word in parse string found
Parse_string = ""
End If
'Print "[" ; Parse_wd(parse_wd_counter) ; "]";
Next
'-------------- interprete commands with arguments
Select Case Parse_wd(1)
Case "at" : Gosub Attention
Case Else
Print "missing at string, received: [" ; Parse_wd(1) ; "]"
Print "send [at command argument]"
End Select
Return
'-------------- commands
Attention:
Select Case Parse_wd(2)
Case "led0" : Gosub Led0
Case "led1" : Gosub Led1
Case Else
Print "missing or wrong command, received: [" ; Parse_wd(2) ; "]"
Print "send [led0 | led1]"
End Select
Return
Led0:
Select Case Parse_wd(3)
Case "on"
Weiss_0 = 1
Print "ok"
Case "off"
Weiss_0 = 0
Print "ok"
Case Else
Print "missing or wrong argument, received: [" ; Parse_wd(3) ; "]"
Print "send [on | off]"
End Select
Return
Led1:
Select Case Parse_wd(3)
Case "on"
Weiss_1 = 1
print "ok"
Case "off"
Weiss_1 = 0
Print "ok"
Case Else : Print "missing or wrong argument, received: [" ; Parse_wd(3) ; "]"
End Select
Return
'-------------- receive serial characters --------------------------------------
' collect received chars and assemble them to input string
Serial_zeichen_abholen:
If Ischarwaiting() = 1 Then
Ser_rx_char = Inkey()
Ser_rx_char_byte = Asc(ser_rx_char)
String_len = Len(serialinput)
Select Case Ser_rx_char_byte
Case 13 'return chra was recognized
New_input_string = Serialinput 'copy string for main routine
New_input_string_received = 1 'set flag that new string is ready
Serialinput = "" 'reset all for new string
Ser_rx_char = ""
Case 127 'backspace - char
If String_len > 0 Then
Print Chr(8) ; " " ; Chr(8); 'android recognizes no chr(127), therefore i use backspace, writing blank, backspace again
String_len = String_len - 1
If String_len = 0 Then 'because "left" returns even with (string,0) one char
Serialinput = ""
Else
Serialinput = Left(serialinput , String_len)
End If
End If
Case Is < 32 'drop all ather control chars
Ser_rx_char = ""
Case Is > 127
Ser_rx_char = ""
Case Else 'valid input char
If String_len < 100 Then 'room left in input string?
Serialinput = Serialinput + Ser_rx_char 'append received char
Print Ser_rx_char ; 'and echo via serial
Else 'abort if 99 chars without enter received
New_input_string = Serialinput 'then string will be closed without enter
Serialinput = ""
New_input_string_received = 1
Ser_rx_char = ""
End If
End Select
End If
Return