|
|
| Author |
Message |
victorf
Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York
|
|
Posted: 06 January 2006, 14:02 PM Post subject: Using Com3 |
|
|
I wish to use com3 to communcate with a device. The device I want to talk to implements an RS232 interface using a MAX232A. I am a bit confuses as to whether I should use inverted or non-inverted logic to configure Com3. The communications will be 9600 baud, 8 data bits, No parity and 1 stop bit. I wish to transmit on pin PC6 and receive on PC5.
I must admit that I am confused by how to prepare Com3. What routines need be called to get this going?
Any enlightenment will be appreciated.
Vic |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR
|
|
Posted: 06 January 2006, 17:11 PM Post subject: |
|
|
First, a little background information. The RS232 standard calls for a logic 1 (also called "mark") to be transmitted as a level between -3 and -15 volts and a logic 0 (also called "space") as a level between +3 and +15 volts. A level converter like the MAX232(A) performs both inversion and level conversion. A +5 volt input on the TTL side yields a negative voltage on the RS232 side and a zero volt input on the TTL side generates a positive voltage on the RS232 side.
Since the device that you're connecting will be generating and expecting RS232 voltage levels, you need to add circuitry between the ZX and the device to perform the level conversion. A MAX232 is probably the easiest way to do this. Appendix C of the ZBasic Reference manual shows several alternatives to performing the level conversion.
Once you have the level converter in place, you'll want to select non-inverting mode for Com3.
Some devices have serial interfaces that don't conform to the RS232 standard but still work in most cases. The Com1 channel on the ZX-24 is an example of this. A mark is transmitted as zero volts and a space is transmitted as +5 volts. If you wanted to connect two ZX-24s using Com1 on one and Com3 on the other, you'd need to select inverting mode.
It is also possible to using inverting mode and a few resistors and diodes to connect to a device with a conforming RS232 interface. This should only be done if the connection is short (a few feet or so). To implement this interface, you need clipping diodes and a limiting resistor on the input to the ZX and a limiting resistor on the output from the ZX. Again, this is not recommended (because doing it incorrectly can damage the ZX) but it should work. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR
|
|
Posted: 06 January 2006, 17:23 PM Post subject: |
|
|
I neglected to answer the second part of your question.
To set up Com3 you have to prepare two queues, define the Com3 configuration and then open the port. Here is a code fragment that shows how it might be done.
| Code: |
Const rxPin as Byte = 20
Const txPin as Byte = 19
Const qsize as Byte = 40
Dim oq3(1 to qsize) as Byte
Dim iq3(1 to qsize) as Byte
Call OpenQueue(iq3, SizeOf(iq3))
Call OpenQueue(oq3, SizeOf(oq3))
Call DefineCom(3, rxPin, txPin, &H08)
Call OpenCom(3, 9600, iq3, oq3)
|
You may need to adjust the queue size. It may make sense in your application to have one queue larger than the other. It may also make sense to completely eliminate one of them if you will only be sending data or only receiving data.
If you want to use Com4, Com5 or Com6 you must first invoke ComChannels() to specify the overall parameters. This is required because the same software is used internally for all 4 software UARTs and it needs to know, before any of the channels are opened, the maximum number of channels that will be used and the maximum baud that will be used. Com3 is handled as a special case (for compatibility reasons) so this special setup is not required if you only use Com3. Looked at another way, the firmware is pre-configured for 1 software UART with a maximum baud of 19200 and if you want a different configuration you need to use ComChannels() to specify what you want. |
|
| Back to top |
|
 |
pjc30943
Joined: 02 Dec 2005
Posts: 220
|
|
Posted: 07 January 2006, 4:56 AM Post subject: |
|
|
Just a clarification question:
The docs say ComChannels has no effect on coms are already open... but I'm not clear which ports this is referring to: all of them, even ones to be opened in the future, or just ones that are already open (is it a compile-level statement, or runtime-level, etc.)
If I go from 3 ports to 2, for example, by closing a port, it may be benificial to redefine ComChannels for higher maximum baudrates. For this, _all_ coms must first be closed, right?
Or can ComChannels statement affect only the next port that is opened, just not those already in place? This still fits with the documentation's description, I believe. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR
|
|
Posted: 07 January 2006, 6:52 AM Post subject: |
|
|
| Quote: | | The docs say ComChannels has no effect on coms are already open. |
Just to clarify, it says that invoking ComChannels() has no effect if any of Com3 to Com6 is open. This means that if you want to change the number of available (software-based) channels or change the maximum speed, you can only do so when none if those channels is open.
The reason that this is so is because both the number of channels and the maximum speed affect the way that the timing is generated. The timing and sequencing cannot be changed when a channel is open because it would corrupt any character that was in the process of being transmitted or received. |
|
| Back to top |
|
 |
jorsam
Joined: 10 Jun 2008
Posts: 1
|
|
Posted: 29 October 2008, 21:00 PM Post subject: |
|
|
Hi,
Great chat and very clear how to define, set and open the serial communication using rxPin and txPin as rx and tx, etc.
But I have a basic question, sorry I'm a beginner:
Which command is used to send and receive serial communication using this open port?
Example: how to code a simple program to send and ASCII character to txPin and how to read a string from the rxPin?
Any help will be very much appreciated. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR
|
|
Posted: 29 October 2008, 21:41 PM Post subject: |
|
|
| jorsam wrote: | | Which command is used to send and receive serial communication using this open port? | The serial channels in ZBasic are all buffered; the transmit and receive queues that you specify when a channel is opened are used for the transmit and receive buffers. Consequently, you don't send and receive characters directly to and from the channel's rx and tx pins. Rather, you put characters to be transmitted into the channel's transmit queue and you read the received characters from the channel's receive queue. Although this design may seem complicated, it has the significant advantage that data transmission and reception can be done in the background.
| jorsam wrote: | | Example: how to code a simple program to send and ASCII character to txPin and how to read a string from the rxPin? | Here is a simple example program showing how to set up a serial channel and then send a character and a string of characters to a serial channel's output queue. | Code: | Const txPin as Byte = 5
Const rxPin as Byte = 6
Const CR as Byte = &H0d
Const LF as Byte = &H0a
Dim iq(1 to 25) as Byte
Dim oq(1 to 40) as Byte
Sub Main()
' initialize the queues
Call OpenQueue(iq)
Call OpenQueue(oq)
' define the characteristics of the serial channel
Call DefineCom(3, rxPin, txPin, &H08)
' open the serial channel
Call OpenCom(3, 9600, iq, oq)
' send a carriage return and line feed as individual bytes
Call PutQueueByte(oq, CR)
Call PutQueueByte(oq, LF)
' send a string with a CRLF
Call PutQueueStr(oq, "Hello, world!" & Chr(CR) & Chr(LF))
End Sub |
Reading data received via the serial channel is slightly more complicated because you don't know when the data you want is going to start arriving and when it will have been completely received. Whether you're wanting to read single characters or sequences of characters from the receive queue, the StatusQueue() and GetQueueCount() functions will be useful to determine when enough data has arrived. The difference between these functions is that StatusQueue() will return True if the queue contains one or more characters. On the other hand, GetQueueCount() returns the number of characters available in the queue. The example below is the Main() subroutine from above with the addition of a loop that echos the received characters to the debug output.
| Code: | Sub Main()
' initialize the queues
Call OpenQueue(iq)
Call OpenQueue(oq)
' define the characteristics of the serial channel
Call DefineCom(3, rxPin, txPin, &H08)
' open the serial channel
Call OpenCom(3, 9600, iq, oq)
' send a carriage return and line feed as individual bytes
Call PutQueueByte(oq, CR)
Call PutQueueByte(oq, LF)
' send a string with a CRLF
Call PutQueueStr(oq, "Hello, world!" & Chr(CR) & Chr(LF))
' echo all received characters to the debug console
Do
If (StatusQueue(iq)) Then
Dim c as Byte
Call GetQueue(iq, c, 1)
If (c = CR) Then
Debug.Print
ElseIf (c <> LF) Then
Debug.Print Chr(c);
End If
End If
Loop
End Sub |
Here is an alternate implementation of the echo loop using GetQueueStr(). | Code: | ' echo all received characters to the debug console
Do
If (StatusQueue(iq)) Then
Dim str as String
Dim strLen as Integer, idx as Integer
str = GetQueueStr(iq)
strLen = Len(str)
For idx = 1 to strLen
Dim c as Byte
c = Asc(str, idx)
If (c = CR) Then
Debug.Print
ElseIf (c <> LF) Then
Debug.Print Chr(c);
End If
Next idx
End If
Loop
| One of the challenges related to reading from a queue is you can't tell ahead of time whether or not it contains a specific character or sequence of characters (e.g. a CR/LF). If your application requires that you wait for receipt of such a termination character, it may be best to read characters from the queue into an array or string until you get the termination character(s). |
|
| Back to top |
|
 |
|