The following code should define and open a com port (com1) with 7 data bits, 2 stop bits, no parity at 19200 baud. While the baud rate selection works properly, I cannot verify that the 7 bit data is correct. It is certainly possible that Hyperterminal is not handling the protocol correctly. Perhaps someone can test this.
Sub Main()
Call DefineCom(1, 0, 0, &h07, 2)
'And Open the port
Call OpenCom(1, 19200, CByteArray(Register.RxQueue), CByteArray(Register.TxQueue))
Do
Console.WriteLine("This is a test")
Call Sleep(1.0)
Loop
End Sub
mikep wrote:I think you should close the COM1 port first before reopening it. Does the same code work for regular ZVM devices?
I changed your code to use 1 stop bit but that didn't help. When I tried a ZVM device and a host PC terminal, the connection is 8 bit data plus 1 stop bit. Configuring for 7 bit data and 1 stop bit resulted in garbage. So I'm not sure what is wrong either. It looks like a problem with DefineCom of com1.
Don_Kirby wrote:The following code should define and open a com port (com1) with 7 data bits, 2 stop bits, no parity at 19200 baud.
As Mike pointed out, you have to close a Com port before you can redefine it. However, even if you do that the DefineCom() for Com1 is ineffective due to an internal logic issue. The same problem exists in the VM version. The problem has been tracked down and resolved.
The workaround is to set the UART registers directly.
' wait for all characters to be transmitted
Do While CBool(StatusCom(1) And &H04)
Loop
' set the UART for 7 bit data
Call SetBits(Register.UCSR0C, &H06, &H04)
stevech wrote:what the heck device uses 7 data bits?
Absolutely none that I know of. It was simply an exercise in serial port protocols that uncovered the issue. Most serial port capable software and/or devices give the standard options of port speed, data bits, parity, stop bits, and flow control. While I'm not going to implement flow control, I thought it a good idea to conform to the pseudo-standard and provide the option to change the remaining settings.
Don_Kirby wrote:Is this true even if the port is already closed [...]
What I should have said is that a port must be in the closed state in order for DefineCom() to be effective. Upon startup, all channels other than Com1 are in the closed state.
Com1 is unique in that it is never really closed. If you call CloseCom() on channel 1, it simply reinitializes it to the default settings. That gave rise to the problem - the code for DefineCom() saw that the channel was open and refused to change the configuration. The solution was to record the fact that CloseCom() was called so that DefineCom() could change the configuration.
So for Com1, I need to close the (apparently, but not actually) closed port before calling DefineCom. I suppose CloseCom knows that it should still perform it's function (record the closed state) even if an OpenCom hasn't been previously called.
Would it be possible to record the fact that the port is closed automatically at startup, then record the opposite as soon as there is a call to OpenCom, Debug.Print, Console.Read, or Console.Write? If implemented in that matter, the usage of DefineCom would be consistent across all of the ports.
Effectively, Com1 is opened automatically for you at startup. Therefore, if you want to change the configuration (speed, stop bits, etc) you have to first close it, call DefineCom() and then call OpenCom(). The sequence is the same for all other channels it's just that none of them are automatically opened at startup.
The solution to the internal problem was simply to add a flag that indicates that CloseCom was called for Com1. If that flag is set then DefineCom is allowed to proceed with configuring Com1. When OpenCom() is later called, the flag is cleared. Calling OpenCom() for channel 1 essentially performs a "reopen" operation since it is always open.
Except for the effects of Com1 being automatically opened and always remaining open, all channels are handled consistently. You'll notice that if you call StatusCom(1) immediately after startup the return value indicates that the channel is open. The same value is returned if you call CloseCom(1) indicating the the channel is really still open. This aspect is documented on the manual page for CloseCom().
If you desired, you could add code that checks the status and closes the channel if it is open before proceeding with DefineCom(). This isn't really necessary, however, because calling CloseCom() for a channel that is not open is essentially a no-op.