Reading bytes from PC via RS232
I am trying to send commands to the SX board from the COM port on my Linux box. The circuit I have is pin 3 from the DB9 -> 3.3KOhm Resistor -> RA.1. This pin is pulled up via a 4.7K Resistor. I also have port C wired up to a 7-segment display (This part has been tested and is working fine). Also I'm using the 50Mhz resonator.
When I send a character (0x9 for example) to the COM port (/dev/ttyS0) I get a response, but only seem to be getting hex 1s and 0s. I have done everything I can think of to try to ensure that the baud rates match (9600), etc.
I'm wondering if there is anyone that has experience trying to interface a linux system to the SX this way and has any suggestions. I actually thought this was going to be the "easy" part![smile.gif](http://forums.parallax.com/images/smilies/smile.gif)
Unfortunately I don't have a windows machine with a com port [noparse]:([/noparse] to do any testing.
Any help would be greatly appreciated.
Here is my SX/B code (I started with the SERIN example in the SX/B Online Help PDF):
'
' Device Settings
'
DEVICE SX28, OSCHS1, TURBO, STACKX, OPTIONX
FREQ 50_000_000
ID "SERIAL"
'
' IO Pins
'
LED PIN RC OUTPUT '7-segment display
SIO PIN RA.1 INPUT 'pull-up via 4.7K
'
' Constants
'
kDash CON %00010000
kBaud CON "OT9600"
'
' Variables
'
serByte VAR Byte 'serial I/O byte
tmpB1 VAR Byte 'parameter
' =========================================================================
PROGRAM Start
' =========================================================================
Pgm_ID:
DATA "SERIAL", 0
'
' Subroutines / Jump Table
'
MAKE_DIGIT FUNC 1,1 ' make 7-segs digit
RX_BYTE FUNC 1 ' receive serial byte
'
' Program Code
'
Start:
PLP_A = %0010 ' pull up unused pins
PLP_B = %00000000
Testing:
LED = kDash ' clear display
serByte = RX_BYTE
IF serByte <= $F THEN
LED = MAKE_DIGIT serByte
ENDIF
'FOR serByte = $0 to $f '--- for testing the 7-seg display
' LED = MAKE_DIGIT serByte
PAUSE 150
'NEXT
GOTO Testing
'
' Subroutine Code
'
' Use: rxInput = RX_BYTE
' reads byte from serial input and places it in 'rxInput'
FUNC RX_BYTE
SERIN SIO, kBaud, tmpB1 ' receive a byte
RETURN tmpB1
ENDFUNC
'
' Use: destination = MAKE_DIGIT value
' converts number in 'value' to 7-segment digit pattern
' and places it in 'destination'
FUNC MAKE_DIGIT
tmpB1 = __PARAM1 ' copy value
IF tmpB1 <= $F THEN ' check range
READ SegMap + tmpB1, tmpB1 ' read table value
ELSE
tmpB1 = kDash ' display dash -- out of range
ENDIF
RETURN tmpB1
ENDFUNC
' =========================================================================
' User Data
' =========================================================================
SegMap:
' bafg.cde
DATA %11100111 ' 0
DATA %10000100 ' 1
DATA %11010011 ' 2
DATA %11010110 ' 3
DATA %10110100 ' 4
DATA %01110110 ' 5
DATA %01110111 ' 6
DATA %11000100 ' 7
DATA %11110111 ' 8
DATA %11110110 ' 9
DATA %11110101 ' A
DATA %00110111 ' b
DATA %01100011 ' C
DATA %10010111 ' d
DATA %01110011 ' E
DATA %01110001 ' F
Here is the script I run on the Linux box to send bytes to the serial port:
echo -n 0x0 >> /dev/ttyS0
sleep .2
echo -n 0x1 >> /dev/ttyS0
sleep .2
echo -n 0x2 >> /dev/ttyS0
sleep .2
echo -n 0x3 >> /dev/ttyS0
sleep .2
echo -n 0x4 >> /dev/ttyS0
sleep .2
echo -n 0x5 >> /dev/ttyS0
sleep .2
echo -n 0x6 >> /dev/ttyS0
sleep .2
echo -n 0x7 >> /dev/ttyS0
sleep .2
echo -n 0x8 >> /dev/ttyS0
sleep .2
echo -n 0x9 >> /dev/ttyS0
sleep .2
echo -n 0xA >> /dev/ttyS0
sleep .2
echo -n 0xB >> /dev/ttyS0
sleep .2
echo -n 0xC >> /dev/ttyS0
sleep .2
echo -n 0xD >> /dev/ttyS0
sleep .2
echo -n 0xE >> /dev/ttyS0
sleep .2
echo -n 0xF >> /dev/ttyS0
When I send a character (0x9 for example) to the COM port (/dev/ttyS0) I get a response, but only seem to be getting hex 1s and 0s. I have done everything I can think of to try to ensure that the baud rates match (9600), etc.
I'm wondering if there is anyone that has experience trying to interface a linux system to the SX this way and has any suggestions. I actually thought this was going to be the "easy" part
![smile.gif](http://forums.parallax.com/images/smilies/smile.gif)
Unfortunately I don't have a windows machine with a com port [noparse]:([/noparse] to do any testing.
Any help would be greatly appreciated.
Here is my SX/B code (I started with the SERIN example in the SX/B Online Help PDF):
'
' Device Settings
'
DEVICE SX28, OSCHS1, TURBO, STACKX, OPTIONX
FREQ 50_000_000
ID "SERIAL"
'
' IO Pins
'
LED PIN RC OUTPUT '7-segment display
SIO PIN RA.1 INPUT 'pull-up via 4.7K
'
' Constants
'
kDash CON %00010000
kBaud CON "OT9600"
'
' Variables
'
serByte VAR Byte 'serial I/O byte
tmpB1 VAR Byte 'parameter
' =========================================================================
PROGRAM Start
' =========================================================================
Pgm_ID:
DATA "SERIAL", 0
'
' Subroutines / Jump Table
'
MAKE_DIGIT FUNC 1,1 ' make 7-segs digit
RX_BYTE FUNC 1 ' receive serial byte
'
' Program Code
'
Start:
PLP_A = %0010 ' pull up unused pins
PLP_B = %00000000
Testing:
LED = kDash ' clear display
serByte = RX_BYTE
IF serByte <= $F THEN
LED = MAKE_DIGIT serByte
ENDIF
'FOR serByte = $0 to $f '--- for testing the 7-seg display
' LED = MAKE_DIGIT serByte
PAUSE 150
'NEXT
GOTO Testing
'
' Subroutine Code
'
' Use: rxInput = RX_BYTE
' reads byte from serial input and places it in 'rxInput'
FUNC RX_BYTE
SERIN SIO, kBaud, tmpB1 ' receive a byte
RETURN tmpB1
ENDFUNC
'
' Use: destination = MAKE_DIGIT value
' converts number in 'value' to 7-segment digit pattern
' and places it in 'destination'
FUNC MAKE_DIGIT
tmpB1 = __PARAM1 ' copy value
IF tmpB1 <= $F THEN ' check range
READ SegMap + tmpB1, tmpB1 ' read table value
ELSE
tmpB1 = kDash ' display dash -- out of range
ENDIF
RETURN tmpB1
ENDFUNC
' =========================================================================
' User Data
' =========================================================================
SegMap:
' bafg.cde
DATA %11100111 ' 0
DATA %10000100 ' 1
DATA %11010011 ' 2
DATA %11010110 ' 3
DATA %10110100 ' 4
DATA %01110110 ' 5
DATA %01110111 ' 6
DATA %11000100 ' 7
DATA %11110111 ' 8
DATA %11110110 ' 9
DATA %11110101 ' A
DATA %00110111 ' b
DATA %01100011 ' C
DATA %10010111 ' d
DATA %01110011 ' E
DATA %01110001 ' F
Here is the script I run on the Linux box to send bytes to the serial port:
echo -n 0x0 >> /dev/ttyS0
sleep .2
echo -n 0x1 >> /dev/ttyS0
sleep .2
echo -n 0x2 >> /dev/ttyS0
sleep .2
echo -n 0x3 >> /dev/ttyS0
sleep .2
echo -n 0x4 >> /dev/ttyS0
sleep .2
echo -n 0x5 >> /dev/ttyS0
sleep .2
echo -n 0x6 >> /dev/ttyS0
sleep .2
echo -n 0x7 >> /dev/ttyS0
sleep .2
echo -n 0x8 >> /dev/ttyS0
sleep .2
echo -n 0x9 >> /dev/ttyS0
sleep .2
echo -n 0xA >> /dev/ttyS0
sleep .2
echo -n 0xB >> /dev/ttyS0
sleep .2
echo -n 0xC >> /dev/ttyS0
sleep .2
echo -n 0xD >> /dev/ttyS0
sleep .2
echo -n 0xE >> /dev/ttyS0
sleep .2
echo -n 0xF >> /dev/ttyS0
Comments
Also, change your series limiter to 20K and add a 50K pull-down after between the SX and the 20K (the pull-down is only needed for when the PC is disconnected). The 20K will limit the current into your SX should your PC be pumping out full RS-232 levels (+/-15 volts). The 20K/50K combination will form a bit of a divider for high-going bits but should put the input well about the TTL input threshold of 1.5v, even with non standard (i.e., low voltage) serial ports.
I have implemented these changes, but I'm still getting garbage, although it seems a different sort. Do you have any suggestions for a setup that will let me test this? Preferably a Linux character based solution, but if I need to I'll get a Windows box with a com port for testing. Ultimately I do need to hook it up to a Linux box, but If I can get the serial stuff working reliable I can do the Linux stuff later: one problem at a time.
On the Linux box I've run stty on the port, setting it to 9600 cs8 no parity, and have tried sending hex (per the above script) no dice.
Generally speaking, does RS-232 communications with the SX have the capacity for being highly reliable? I have a programing background, but I'm very new to micro controllers, so I apologize in advance for any stupid questions.
Another question is do I need to send Hex to the SX or should I be able to send ASCII? Phase 2 is creating a buffered serial interface so I can send some actual data, and ASCII will be easier to deal with.
BTW I've been working my way through Practical SX/B and I have found it to be very helpful. I haven't done any assembly for over 20 years, and I'd like to keep it that way
-C
Serial communications on the SX is rock solid as long as you have a good oscillator. Since you're using a resonator, you should be fine.
You mentioned that you're getting a "different sort" of garbage. What exactly? Also, rather than sending the value 0 to 15 in hex, just try sending the same character over and over. you need some way to determine what you're sending and what you're getting. If you're sending a different value each time, it makes it hard to correlate what is coming from the Linux box with what is being received on the SX. You first need to make sure that you're getting a consistent value into the SX each time. Sending the same value over and over will let you find out if this is happening or not.
Thanks,
PeterM
I'm currently using a 50Mhz, but for 9600 baud, a 4Mhz (external) should be sufficient, right?
You mentioned that you're getting a "different sort" of garbage. What exactly?
I'm not sure. I'm getting a byte, but regardless of what I send (echo 0x7 > /dev/ttyS0, for example) whatever I'm getting is outside the $0 - $F range. I'm not sure how to tell specifically what I'm getting on the SX side.
Also, rather than sending the value 0 to 15 in hex, just try sending the same character over and over. you need some way to determine what you're sending and what you're getting. If you're sending a different value each time, it makes it hard to correlate what is coming from the Linux box with what is being received on the SX. You first need to make sure that you're getting a consistent value into the SX each time. Sending the same value over and over will let you find out if this is happening or not.
Agreed. I'm modifying the code to send a hex 7 every .2 seconds.
I do have some questions about sending bytes. My understanding is that it doesn't really matter if the source is hex or ascii, right? For example, sending an "A" is equivalent to sending 0x41 - SERIN would see the same value, correct? So I could test for either $41 or "A" in the SX/B code?
Thanks,
-Craig
The basic problem was that I was trying to send hex values but the shell was treating them literally, so 0xf was '0xf', not $f. I rewrote my scripts to output ASCII, made the proper stty settings, and it works great. For those of you that want to send serial to a SX from a linux box, I have a sample PHP script that uses PHP Serial class by R
Column #125: Control from Your Favorite Terminal
Thanks all for you help.
ctrl-a then z will bring up the main menu.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-Craig