• Please review our updated Terms and Rules here

Qbasic Sending Characters by Serial Ports

erkdw

New Member
Joined
Jul 25, 2008
Messages
8
Hi,

Slightly weird problem.

I have a Qbaisc program that simply sits and listens to a serial port which is hooked up at 9600/8/N/1 to a system, and simply records whatever it recived both on screen and in a text file.
This bit works great.

Every few days the system im listening to falls over and crashes. i need to be able to realise when it crashes (it send an "@" sign out only) and then send some commands back at it. the problem i have is i cant send it at 9600 back as the system only polls the port once every 10ms (its designed to have hyperterminal connected, therefor you type with keyboard not send strings)
It also echos back every character.

I need to be able to send short strings, followed by CHR(10) and CHR(13) and then log both the echoed letters, and its responce (the debug info)

Anyone have any ideas?

Below is the code im currently using to record the logs at present:

10 OPEN "wipcom.txt" FOR OUTPUT AS #3
20 COM(1) ON
30 OPEN "com1:9600,N,8,1,asc,cd0,cs0,ds0,op0,tb1024,rb1024" FOR INPUT AS #1
35 ON ERROR GOTO etrap
40 CLS
50 LOCATE 2, 15
60 PRINT "WIP CONSOLE LOGGER - V1.00 01/05/2008"
LOCATE 24, 20
PRINT "Press `CTRL + BREAK' to exit - Errors Logged in wipcom.txt"
70 VIEW PRINT 3 TO 22

80 DO WHILE NOT INKEY$ = CHR$(27)
90 LINE INPUT #1, Line$
100 TestTIME$ = TIME$
110 TestDATE$ = DATE$
120 PRINT Line$, TestTIME$, TestDATE$
130 PRINT #3, TestDATE$, TestTIME$, Line$
140 LOOP
150 CLOSE #1

160 CLOSE #3
170 SYSTEM
180 END


200 etrap:
205 PRINT TestDATE$, TestTIME$, "Software Link Fault - Error Logged"
210 PRINT #3, TestDATE$, TestTIME$, "SOFTWARE REPORT - The Error number is err #"; ERR
220 RESUME



Note - theres a weird thing happeneing when im connected and we switch off the other syste, i get an error and the software crashes, thus the etrap subrouten


Any help or suggestions/example code would be fantastic, iv been trying to get this dam thing working for a few weeks now and i cant find an awful lot online that iv been able to convert into working code.

Cheers
 
It sounds as if the problem is on the listening end, polling once ever 10 msec or so.

Why poll at all? Why not use an interrupt-driven handler to accumulate the sent characters? If you're sending well-formed messages, terminated by a CR or LF, the interrupt handler can accumulate a whole message, handling the echoplexing and only then notifying your main routine that a complete message has been accumulated.

Of course, you can't do this entirely in BASIC; you'll need some assembly code. But there's code out there--have you checked the SIMTEL library?
 
I think most BASICS have "interrupt" capability with "ON COM," no?

But I don't think that's relevant here; I don't see the problem - what's the difference between HT sending characters and your software sending them?

I have systems running at client sites that do something similar, written in BASIC many years ago. They send an account number out the serial port which is connected to a LAN terminal through an RS-232 to PS/2 converter and the terminal thinks the number was typed on the keyboard and brings up the account info; after a short delay the driving system sends a printscreen, which the terminal sends back to the RS-232 port through the generic (com) printer driver. Had to do it this way 'cause there's no practical way to access the main system, but it works like a charm.

First thing ya need is another file for com output, or is there a #2 somewhere that you haven't told us about?

More info needed

And change the version number; V 1.00 never works ;-)

m
 
I had to look it up right quick to check if I was thinking right (been a while) and I guess you already read Microsoft's link http://support.microsoft.com/kb/28149 lol, but if you're sending non-readable ASCII characters to interpret maybe you need your open to use RANDOM instead of INPUT?
 
I tried opening as RANDOM and using the command

PRINT #1 "GPTEST PQ01"

but it send it too fast, the reciving system (which i cant change) only recived the G

9600 baud = 1000 odd characters per second, where as my terminal polling ever 10ms can only recive 100 characters per second.

i need to be able to:
Send G
Wait for G be echo'ed
Send P
Wait for P to be echo'ed
.
.
.
.
Send 1
Wait for 1 to be echo'ed
Send CR/LF
Log multi line responce from other system


any thougts?
 
I don't understand why the one system is sleeping for 10ms between checks of the COMM port. Even a PC XT can drive the serial port at 9600.

Polling is actually *faster* that interrupt driven communication .. Interrupts cause extra instructions to be run. But you can't poll then sleep for 10 ms .. that's broken. Not unless you are buffering characters and reading more than one char per interrupt or polling interval.

So please explain where the 10ms figure is coming from ..
 
Yeah, I'd like to know the same thing; are you sure you don't have a handshaking issue?
In any case, why not just delay between characters? But if you must wait for each echoed character, then ON COM is probably your friend.

You will almost always get framing errors (57) when you connect/disconnect or turn the remote power on/off; that's what ON ERROR is for.

Finally, I don't think you want to use random files for this, and I don't know why you'd want to.

m
 
Polling is actually *faster* that interrupt driven communication .. Interrupts cause extra instructions to be run. But you can't poll then sleep for 10 ms .. that's broken. Not unless you are buffering characters and reading more than one char per interrupt or polling interval.

Interrupt-driven I/O doesn't have as its advantage that it's faster than polling, but that you can do other things without having to constantly poll for I/O ready. Makes multi-tasking much easier, when one of the tasks is interrupt-driven.

I'm making an assumption here that the reason for the 10msec poll that he's doing something else on the other end, other than waiting for characters. Maybe I'm assuming wrongly...

In my experience, you should devote a bit of thought to using ON COM. It's not fast; depending on the CPU, you can actually get pretty far behind at 9600 bps. ON COM indicates when something has happened; it might be a character received or a framing error. So if you use ON COM, check how many characters have been received using LOC, then get however many is in the buffer using INPUT$.

Or use an assembly-language handler...
 
Basically the system at the other end is a safety critical monitoring system which devoted 99.9% of its time to monitoring safety systems. the communications port im using is only the processors debug port, so a very low priority.
because of the ability to affect the main systems operation by typing a command, (one of the commands is to dump its memory via comm port) it only sends or recived on character every 10ms. its running on an SX180 6MHz CPU Card (STE Bus Archetecture)
 
Ok,
Iv reworked it a little,


10 OPEN "wipcom.txt" FOR OUTPUT AS #3
20 COM(1) ON
30 OPEN "com1:9600,N,8,1,asc,cd0,cs0,ds0,op0,tb1024,rb1024" FOR RANDOM AS #1
35 ON ERROR GOTO etrap
40 CLS
50 LOCATE 2, 15

60 PRINT "WIP CONSOLE LOGGER - V1.01 26/07/2008"
LOCATE 24, 20
PRINT "Press `CTRL + BREAK' to exit - Errors Logged in wipcom.txt"
70 VIEW PRINT 3 TO 22

80 DO WHILE NOT INKEY$ = CHR$(27)
81 PRINT #1, " "
82 PRINT #1, "DS"
90 LINE INPUT #1, line$
100 TestTIME$ = TIME$
110 TestDATE$ = DATE$
120 PRINT line$, TestTIME$, TestDATE$
130 PRINT #3, TestDATE$, TestTIME$, line$

132 IF INSTR("@", line$) > 0 THEN GOTO breakcommands
ret:
140 LOOP
150 CLOSE #1
160 CLOSE #3
170 SYSTEM
180 END


200 etrap:
205 PRINT TestDATE$, TestTIME$, "Software Link Fault - Error Logged"
PRINT #3, TestDATE$, TestTIME$, "SOFTWARE REPORT - The Error number is err #"; ERR
RESUME

250 breakcommands:
260 PRINT #1, "DS"; CHR$(10)
261 PRINT #1, "L80"; CHR$(10)
GOTO ret


I was just trying to make the software send "DS" then CR LF, but i cant figure out how to slow it down, the reciving system only see's "D" with No S or CR/LF
 
Well, if the program doing the input only looks once every 10 msec, you'll have to dribble your output more slowly than that.

To get around the buffering that QBASIC does, how about sending one character at a time and closing and then re-opening COM1 to flush the buffer each time? You can use your own delay routines.
 
I don't think you have to worry about BASIC buffering the output, but I will agree (again) that you'd probably be better off using ON COM for the input unless you are certain that there will always be a response ending in CR. Besides, you've already got COM ON in there which AFAIK is only relevant if you use ON COM.

But if all you want to do is pace the output characters, just add a delay:

m$="DS"+chr$(10)+chr$(13)+"L80"+chr$(10)+chr$(13):gosub SEND

SEND:
for i=1 to len(m$): print#1,mid$(m$,i,1);:delay .2:next:return

If your BASIC doesn't have DELAY, just use "for j=1 to x:next" instead, with x adjusted to your system speed.

mike
 
Latest Version still not working correctly tho

10 OPEN "wipcom.txt" FOR OUTPUT AS #3
20 COM(1) ON
30 OPEN "com1:9600,N,8,1,asc,cd0,cs0,ds0,op0,tb2048,rb2048" FOR RANDOM AS #1
35 ON ERROR GOTO etrap
40 CLS
50 LOCATE 2, 15
60 PRINT "WIP CONSOLE LOGGER - V1.02 28/07/2008"
70 LOCATE 24, 20
80 PRINT "Press `CTRL + BREAK' to exit - Errors Logged in wipcom.txt"
90 VIEW PRINT 3 TO 22

100 m$ = CHR$(10) + CHR$(13) + "DS" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 7500000: GOSUB SEND
101 m$ = CHR$(10) + CHR$(13) + "DT01" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
102 m$ = CHR$(10) + CHR$(13) + "DT02" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
103 m$ = CHR$(10) + CHR$(13) + "DT03" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
104 m$ = CHR$(10) + CHR$(13) + "DT04" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
105 m$ = CHR$(10) + CHR$(13) + "DT05" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
106 m$ = CHR$(10) + CHR$(13) + "DT06" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
107 m$ = CHR$(10) + CHR$(13) + "DT07" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
108 m$ = CHR$(10) + CHR$(13) + "DT08" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
109 m$ = CHR$(10) + CHR$(13) + "DT09" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
110 m$ = CHR$(10) + CHR$(13) + "DT0A" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
111 m$ = CHR$(10) + CHR$(13) + "DT0B" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
112 m$ = CHR$(10) + CHR$(13) + "DT0C" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
113 m$ = CHR$(10) + CHR$(13) + "DT0D" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND
114 m$ = CHR$(10) + CHR$(13) + "DT0E" + CHR$(10) + CHR$(13): charwaittime = 10000: msgwaittime = 3000000: GOSUB SEND


300 DO WHILE NOT INKEY$ = CHR$(27)
310 LINE INPUT #1, line$
320 TestTIME$ = TIME$
330 TestDATE$ = DATE$
340 PRINT line$, TestTIME$, TestDATE$
350 PRINT #3, TestDATE$, TestTIME$, line$

360 LOOP
370 CLOSE #1
380 CLOSE #3
390 SYSTEM
399 END


400 etrap:
410 PRINT TestDATE$, TestTIME$, "Software Link Fault - Error Logged"
420 PRINT #3, TestDATE$, TestTIME$, "SOFTWARE REPORT - The Error number is err #"; ERR
430 RESUME


500 SEND:
505 PRINT #3, "BREAKPOINT COMMAND - SENDING MESSAGE - "; m$
510 FOR i = 1 TO LEN(m$)
520 PRINT #1, MID$(m$, i, 1);
530 FOR j = 1 TO charwaittime
540 NEXT
550 NEXT
560 FOR k = 1 TO msgwaittime
570 NEXT
580 RETURN
 
On, im looking into how to use the ON COM

Am i right in thinking, the following would be correct:

ON COM(1) GOSUB RXDATA

RXDATA:
INPUT$ #1 line$
PRINT line$, TestTIME$, TestDATE$
PRINT #3, TestDATE$, TestTIME$, line$
Return

Or would i be better of waiting until a full line and CRLF had been recived before outputting the data to the screen and text file? - if so, any thought on how to check if the character is a crlf?
 
Your reading machine probably has a 16650 UART on it, which is capable of buffering up to 16 bytes at a time when probably configured. QBasic probably is not going to support the extra features of the chip.

I would investigate FOSSIL drivers. I don't know if Qbasic will work with one, but the FOSSIL driver can enable the on chip buffering that you need.
 
Ok, i tinkered ouround with the ON COM function and managed to make something work, this is the code and so far, it seems to be working perfectly well.

10 OPEN "wipcom.txt" FOR OUTPUT AS #3
20 COM(1) ON
30 OPEN "com1:9600,N,8,1,asc,cd0,cs0,ds0,op0,tb2048,rb2048" FOR RANDOM AS #1
35 ON ERROR GOTO etrap
40 CLS
50 LOCATE 2, 15
60 PRINT "WIP CONSOLE LOGGER - V1.03a 28/07/2008"
70 LOCATE 24, 20
80 PRINT "Press `CTRL + BREAK' to exit - Errors Logged in wipcom.txt"
90 VIEW PRINT 3 TO 22
95 ON COM(1) GOSUB RXDATA
100 m$ = CHR$(10) + CHR$(13) + "DS" + CHR$(10) + CHR$(13): msgwaittime = 7500000: GOSUB SEND
101 m$ = CHR$(10) + CHR$(13) + "DT01" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
102 m$ = CHR$(10) + CHR$(13) + "DT02" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
103 m$ = CHR$(10) + CHR$(13) + "DT03" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
104 m$ = CHR$(10) + CHR$(13) + "DT04" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
105 m$ = CHR$(10) + CHR$(13) + "DT05" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
106 m$ = CHR$(10) + CHR$(13) + "DT06" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
107 m$ = CHR$(10) + CHR$(13) + "DT07" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
108 m$ = CHR$(10) + CHR$(13) + "DT08" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
109 m$ = CHR$(10) + CHR$(13) + "DT09" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
110 m$ = CHR$(10) + CHR$(13) + "DT0A" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
111 m$ = CHR$(10) + CHR$(13) + "DT0B" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
112 m$ = CHR$(10) + CHR$(13) + "DT0C" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
113 m$ = CHR$(10) + CHR$(13) + "DT0D" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND
114 m$ = CHR$(10) + CHR$(13) + "DT0E" + CHR$(10) + CHR$(13): msgwaittime = 3000000: GOSUB SEND

300 DO WHILE NOT INKEY$ = CHR$(27)
360 LOOP
370 CLOSE #1
380 CLOSE #3
390 SYSTEM
399 END

400 etrap:
410 PRINT TestDATE$, TestTIME$, "Software Link Fault - Error Logged"
420 PRINT #3, TestDATE$, TestTIME$, "SOFTWARE REPORT - The Error number is err #"; ERR
430 RESUME

500 SEND:
505 PRINT #3, "BREAKPOINT COMMAND - SENDING MESSAGE - "; m$
510 FOR i = 1 TO LEN(m$)
520 PRINT #1, MID$(m$, i, 1);
530 FOR j = 1 TO 1000000
540 NEXT
550 NEXT
560 FOR k = 1 TO msgwaittime
570 NEXT
580 RETURN

600 RXDATA:
602 FOR C = 1 TO 1000000
603 NEXT
605 ALL = LOC(1): IF ALL < 1 THEN RETURN
610 LINE$ = INPUT$(ALL, #1)
640 PRINT LINE$, TIME$, DATE$
650 PRINT #3, TestDATE$, TestTIME$, LINE$
660 RETURN
 
try opening the port with a BINARY access method.

OPEN "COM1:9600,N,8,1,BIN" FOR BINARY AS whatever

see if that helps
of course, use GET #filenum, , thestring$ and PUT #filenum, , thestring$

rather than prints and inputs

as far as GET, if you make a string 1 byte long like thestring$ = SPACE$(1) then it will only wait for one byte.

you may have to not have ",BIN" in the filename to open, i forget. i haven't messed with serial comm in ages.

good luck.
 
Voltage current properties

Voltage current properties

I am new to this forum but I have got programs that send and receive over the serial port.
It will take me a while to read up and try some of the things you folks discussed.
Today though I have a new problem. I want to use the handshaking signals to control and sense external circuits which I can build. Also I want to test the newer ports on laptops to see why they are so different from my expectation. There used to be specs on voltage and impedance. Then I may test an old laptop to destruction before disposing of it. I have the 16550D spec printed and I read it. I am not certain what I have to do to make the chip go. Fortunately I don't have to worry about timing. The 486 does that on one end and at the other I read a meter and adjust a pot. I hope someone did this already.
I work with the win 3.1.1 supplied quick basic but hope to also use turbo C the old Borland V 3.
 
Last edited:
Resurrectling a 5 year old thread? You might be better off starting a new one.

At any rate--it isn't the UART chip that you should be worried about if you're wondering about voltage and impedance--it's the transcievers. For years now, every laptop has used some version of the old Maxim MAX232 transceiver, which includes a voltage "step up" converter. There exist many versions of this thing--some operate from 3.3V, others use smaller charge pump capacitors, some have "power down" mode. 6-9V output for mark and space is not unusual and the current output tends to be rather small when compared to the old MC1488 bipolar drivers, but you should start with the MAX232 IC for some solid specs.
 
Back
Top