BS2: SEROUT/SERIN at 38400 easy-peasy
tomcrawford
Posts: 1,129
in BASIC Stamp
There have been some discussions recently about (relatively) fast serial I/O with the BS2. I decided to experiment. I chose to use only "standard" baud rates.
1. SEROUT works just fine up to and including 38,400 with formatting.
BS2OutComplete shows the complete output. The first six characters are the text string, then 4 characters of HEX4 formatting, and finally 5 characters of DEC5 formatting. There are plenty of extra STOP bits, but that is perfectly legal. Async is asynchronous.
BS2OutDetail shows a single character. The bit time is 25.92, corresponding to 38,580 baud rate, less than 1% fast.
2. SERIN works up to 38,400, but WITHOUT formatting. Here is a driver I wrote for propellor. I wrote my own because I wanted explicit control over the protocol including number of stop bits. It turns out that a single stop bit was adequate.
and here is the BS2 program that received it.
Note that SERIN uses only STR (capture a string). Formatting like HEXn and DECn do work only to 9600. So any conversion you need to do needs to be done by hand.
1. SEROUT works just fine up to and including 38,400 with formatting.
' {$STAMP BS2} ' {$PBASIC 2.5} TxOut PIN 1 RxIn PIN 2 'receive data here Baud CON 6 '38400 baud ByteSize VAR Byte WordSize VAR Word main: WordSize = 12345 DO SEROUT TxOut, baud, ["String", HEX4 Wordsize, DEC5 WordSize, CR] PAUSE 50 LOOP
BS2OutComplete shows the complete output. The first six characters are the text string, then 4 characters of HEX4 formatting, and finally 5 characters of DEC5 formatting. There are plenty of extra STOP bits, but that is perfectly legal. Async is asynchronous.
BS2OutDetail shows a single character. The bit time is 25.92, corresponding to 38,580 baud rate, less than 1% fast.
2. SERIN works up to 38,400, but WITHOUT formatting. Here is a driver I wrote for propellor. I wrote my own because I wanted explicit control over the protocol including number of stop bits. It turns out that a single stop bit was adequate.
{Serial Character Stream Generator Transmit test streams for formstted testing} CON _clkmode = xtal1 + pll16x 'Standard clock mode _xinfreq = 5_000_000 '* crystal frequency = 80 MHz TxOut = 17 BaudRate = 38400 ' HalfStops = 0 '1 stop bit VAR long Command '<> 0 says => driveer busy '14..0 : Address in hub memory long MyParm[6] 'passing addresses, etc to display driver byte Cog byte TheString[10] word DecVal ' OBJ pst : "parallax serial terminal" PUB main pst.Start (115_200) 'start up ser terminal pst.str(String("hello, world ")) 'runs in cog 1 pst.NewLine waitcnt(clkfreq/10 + cnt) MyParm[0] := @Command 'address of string to send MyParm[1] := 80_000_000/BaudRate 'bit time in clock cycles MyParm[2] := HalfStops 'optional extra half stop bits cog := cognew(@PCog, @MyParm) 'start up the output cog pst.str(String("Transmit Cog: ")) ' pst.hex(Cog,1) pst.NewLine waitcnt(clkfreq/10+cnt) repeat DecVal from 0 to 65_000 Dec2ASC(DecVal, @TheString) Command := @TheString 'transmit dec repeat while (Command <> 0) waitcnt(clkfreq/20 + cnt) pst.char("*") PUB Dec2ASC(InVal, Point)| Count 'convert word to 5 ascii digits byte[Point][0] := "0"+InVal / 10_000 byte[Point][1] := "0"+(Inval//10_000) / 1_000 Byte[Point][2] := "0"+(InVal//1_000) / 100 Byte[Point][3] := "0"+(InVal//100) / 10 Byte[Point][4] := "0"+(InVal//10) byte[Point][5] := 13 'terminator for BS2 byte[Point][6] := 0 'terminator for serial out DAT PCog org 0 'This PASM driver is a serial driver mov AdPar,Par 'get the address of input parameters rdlong AdCommand, AdPar 'address of command long add AdPar, #4 rdlong BitTime, AdPar 'clocks per bit mov HalfBT, BitTime shr HalfBT, #1 'clocks per half bit time add AdPar, #4 rdlong HalfSB, AdPar 'number of half stop bits or outa, TxMask 'comes up high or dira, TxMask 'transmitter is an output '*********************wait here for something to do************************* top rdlong AdString, AdCommand wz 'wait for a command (address of string) if_Z jmp #top 'just hang here Cloop rdbyte TheChar, AdString wz 'get the (first)(next) character if_Z jmp #done 'zero terminated string add AdString, #1 'point to following char mov BitCount, #8 '8 bits per character mov time, BitTime add time, cnt 'time at end of start bit andn outa, TxMask 'send start bit waitcnt time, BitTime 'time start bit BLoop shr TheChar, #1 wc 'next (first) bit into carry muxc outa, TXMask 'then onto pin waitcnt time, BitTime 'one bit time djnz BitCount, #BLoop 'eight bits per character or outa, TXMask 'stop bit waitcnt time, HalfBT 'one stop bit mov BitCount, HalfSB wz 'optional half stop bits if_Z jmp #CLoop 'no optional stop bits SLoop waitcnt time, HalfBT 'at least one half stop bit djnz BitCount, #SLoop 'however many jmp #CLoop 'on to next character done wrlong zero, AdCommand 'tell boss cog done jmp #top 'and wait for another ' zero long 0 'constants TxMask long 1<<TxOut 'mask corresponding to transmit pin BitTime res 'clocks per bit time AdPar res 'address into parameter list AdCommand res 'address in hub of command long MyCommand res 'my copy of the command BitCount res 'number of bits per character time res 'time to wait AdString res 'current address in string theChar res 'the character we are transmitting HalfSB res 'number of optional half stop bits HalfBT res 'half bit time (for optional 1/2 stops)
and here is the BS2 program that received it.
' {$STAMP BS2} ' {$PBASIC 2.5} RxIn PIN 2 'receive data here baud CON 6 '38400 Baud SerString VAR Byte(10) 'buffer so as to use STR Result VAR Word 'decimal value from convert CharCount VAR Byte 'number of characters to convert Point VAR Byte 'pointer into character string main: DO SERIN RXIn, baud, [STR serString\10\13] 'up to 10 chars, teerminated with CR DEBUG STR SerString, " " 'display raw string for manual inspection CharCount = 5 'convert 5 digits GOSUB Asc2Dec 'convert ASCII decimal string to binary DEBUG DEC5 Result, CR 'display result in decimal LOOP Asc2Dec: 'convert ascii string Result = 0 'remove previous result FOR Point = 0 TO CharCount - 1 'work way through string Result = (Result * 10) + (SerString(Point) - "0") 'shift and add NEXT RETURN
Note that SERIN uses only STR (capture a string). Formatting like HEXn and DECn do work only to 9600. So any conversion you need to do needs to be done by hand.