Please be aware of all shipping deadlines before placing your order - we cannot guarantee orders will arrive before Christmas!

How to send raw hex over RS-232?
Moderators: adafruit_support_bill, adafruit

How to send raw hex over RS-232?

by TheDon125 on Wed Sep 23, 2009 11:19 am

Hi everyone.

For a project I'm working on, I would to send raw hexadecimal bytes over RS-232. Is there any particularly easy way to do this? Most terminal applications that I've seen can only accept ascii input, and so don't work very well for sending the raw data.

The project involves sending 4 bytes of data at a time to the microcontroller (ATMega16A). The first three bytes control 24 LEDs, and the last byte is used to tell the uC how to interpret the first 3 bytes. Since the first 3 bytes control 24 LEDs, I would like to be able to use the full range of values per byte (0-255) to get individual control over the LEDs.

I realize that I can simply increase the data sent from 4 bytes to 12 bytes, and then process the incoming data on the uC (i.e. sending ascii 2, subtract x30, multiply by 100, store, send ascii 3, subtract x30, multiply by 10, add to total, send ascii 4, subtract x30, add to total), but I figure its probably better to use the PC to do the bulk of the processing, and let the uC sit back and gather the data. I probably have enough clock cycles to spare in between serial data transmissions now (currently operating at 4800 bps w/ 8MHz clock), but if I increase that number later (to 19200 bps, for example), I'm concerned about hitting the uC's processing limit.

Why increase the speed? Because a later version of this project could very well involve sending 1Mb of data (or more), and 1Mb@4800bps = about 218 seconds = about 3.75 minutes. Tripling the data as the proposed solution would of course increase transfer time to almost 11min, a bit of a wait. 19200bps is a much more reasonable (though still not fantastic) 1min/3min for data transfer.
TheDon125
 
Posts: 23
Joined: Tue Jan 09, 2007 9:58 pm

Re: How to send raw hex over RS-232?

by Hinermad on Wed Sep 23, 2009 12:29 pm

If you know there will be a significant time period between transmissions, you could use a simple packet protocol. The simplest I can think of would be to send a byte (or two, or four, as long as it's a fixed length) that gives the number of following bytes to expect, then that number of data bytes.

For the example you give you'd send something like this:

0x04 (length, 4 bytes to follow)
0x00 (interpretation byte)
0x01 (first pattern byte)
0x55 (second pattern byte)
0x12 (last pattern byte)

This can be risky if the receiver ever gets out of sync with the sender, because it might grab the 0x55 and think it's the length byte. If there's a long delay between transmissions you can code a timeout so that if the receiver is waiting for a data byte and the timeout expires it gives up and goes back to waiting for the next length byte.

As for a PC program to send the data, that's going to be tricky. The easiest would be to use a terminal emulator like Tera Term (-highly- recommended, I use it at work) that supports transmitting raw files (i.e. not using an upload protocol). Then use a hex editor to create a file with the binary data you need to send. Or you can write a PC program to create and transmit the data out the comm port.

Dave
User avatar
Hinermad
 
Posts: 56
Joined: Sun Sep 13, 2009 1:25 pm
Location: Upstate New York, USA

Re: How to send raw hex over RS-232?

by uoip on Wed Sep 23, 2009 6:14 pm

One of the easiest quick-and-dirty ways to send raw data over the RS-232 port is to use the "MODE" command from a command shell. That lets you set up your serial port's parameters. It's a remnant from the old DOS days, but it still works in the newest versions of Windows. You might use something like

MODE COM1: BAUD=9600 PARITY=n DATA=8 STOP=1

After you've done that, you can type

MODE COM1:

to verify the settings.

When you've got the port set up right, just use the redirection operator to send output to COM1. For example, if you've got the data in a file called myfile.hex, you'd just enter:

TYPE MYFILE.HEX >COM1:

Of course, you can write a script in your favorite scripting language to print output to COM1 using redirection, as well.

There are almost certainly more robust methods of handling serial I/O, but they'll vary a bit depending on the language you're using, and you don't say what language(s) you're familiar with. See your language's reference manuals or google. You might want to search for your language name and the keyword "dcb", "SetCommState", "Serial I/O", or "COM1".


But using the mode command plus redirection is probably the simplest quick-and-dirty method to send a few bytes out, at least to make sure your hardware and concept is working.
uoip
 
Posts: 127
Joined: Wed Sep 23, 2009 5:48 pm

Re: How to send raw hex over RS-232?

by TheDon125 on Thu Sep 24, 2009 3:07 pm

Looks like a terminal sending raw hex files is the way to go, thanks!

As for a packet protocol, I'll have to look into that, but there currently is no time in between transmissions. Its basically going to be a solid block of any multiple of 4 bytes that can be stored into the uC's RAM.
TheDon125
 
Posts: 23
Joined: Tue Jan 09, 2007 9:58 pm

Re: How to send raw hex over RS-232?

by iexpress on Fri Feb 07, 2014 9:15 am

I do it this way though you may have to interpret it to suit your needs.

Code: Select all | TOGGLE FULL SIZE
dim b as byte
dim i as integer
dim s as string
dim s1 as string
dim s2 as string

' open your file in binary mode, and get each byte.
' do this to each byte.

i = val(b)

s = hex(i)

if len(s) = 1 then
s = "0" & s
end if

s1 = microsoft.visualbasic.left(s, 1)
s2 = microsoft.visualbasic.right(s, 1)

' send s1 first
' send s2 2nd.

' MCU will receive two Hex chars as regular 7 bit ASCII
' on the MCU end, listen for ASCII chars

scanf(%c, uint8_t);

if (uint8_t){
'do some stuff here
}

' Converting back to a usable number, uint16_t usually, is easy but you'll have to do something
' like this:

switch ( uint8_t ){
 case 'F':
 uint16_t = 15;
 break;
 case 'E':
 uint16_t = 14;
 break;
}
' And so on for 0. There you use the 2nd 16 bit uint for operations.

' sending data back to the PC goes like this:

printf(%X, uint16_t); ' I use a uint8_t to make sure I'm only sending one byte at a time.
Last edited by adafruit_support_bill on Fri Feb 07, 2014 9:34 am, edited 1 time in total.
Reason: Please use the 'code' button when submitting code - click 'code' and paste your code between the tags.
iexpress
 
Posts: 1
Joined: Thu May 16, 2013 5:15 pm