Transfering integer via rs232 without converting to string.

Hi all,

I would like to transfer an integer (4bytes) from a vb program running on my main computer to an ATmega8 microcontroller without having to convert it to a string and sending every char of the number. Is this at all possible? Haven't found out how to get to the 4bytes represending the integer in vb yet..

It's not transfer of the bytes that is the problem but how to get to the 4 bytes in vb, and how to tell the microcontroller that the 4 bytes is to represent an integer?!

Hope someone out there knows a solution to this "small" problem, as this would simplify my microcontroller code a lot...

Thanks

Reply to
Henning Mortensen
Loading thread data ...

Which version of VB are you using, VB6 or VB.NET?

Hmm, since you are mentioning a 4 byte integer, I'll assume you mean VB.NET, as ints are 16 bit in VB6 by default. (and if memory serves)

Probably the simplest way to do this (if you are determined to do it at all - is the overhead really that big resp. converting back from a string representation really that difficult?) is to send the value byte by byte - e.g. like so:

Imports System.Runtime.InteropServices

Public Class Form1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim theInteger As Int32 theInteger = Convert.ToInt32(TextBox1.Text)

ListBox1.Items.Clear() For i As Integer = 1 To Marshal.SizeOf(theInteger) Dim byteToSend As Byte byteToSend = theInteger And &HFF ' Here, you would send your byte instead of adding it to the listbox ListBox1.Items.Add(byteToSend) theInteger >>= 8 Next

End Sub End Class

This is a quick hack with a form containing a button, a textbox and a listbox. (I left the default names so you can easily reconstruct the sample)

Enter your int to be sent in the textbox - pressing the button will disassemble it into bytes and add them to the listbox.

Instead of adding the bytes to the listbox you would send them to the AVR, in whichever way this happens in your setup (you didn't mention).

On the AVR side (assuming you are using some higher-level language, I am not familiar with BASCOM here, only gcc), you'd initialize a 32 bit integer variable (a long) with zero, shift the first byte 0 times and add (or "OR") it to the total, left-shift the second byte by 8 bits and "add", the third one 16 bits and the fourth one 24 bits and add again.

Of course, you'll have to KNOW that you expect an int to be sent at that time, that it is exactly four bytes wide, and that it comes in lower-valued bytes first.

Things are trickier in VB6 since there is no bit shift operator there, when replacing it with integer division you have to be careful with the handling of negative numbers.

Regards, Gilles.

Reply to
Gilles Kohl

¨ Hi Gilles.

Thanks for the quick responds, and solution :) (Why didn't I think of that??!! It's so simpel when you got the >>= operator..!!) I found something else that will also do the trick @

formatting link
and yes it's Vb.net and gcc..

I like your solution tho, nice and simple and no creapy memcopy (that could create caos...).

Thanks again, now I can finally get the last programming done...

Best Regards, - Henning

Reply to
Henning Mortensen

Hi again,

Now the project is almost done, I find myself in a bit of Debugging HELL...... I have spent hours trying to figure out that I'm doing wrong..

Here is the Microcontroller rs232 interrupt reciving data.. (I have rewritten it many times, so maybe it's a bit explicit.. )

ISR(USART_RXC_vect) { Letter=UDR; Buffer[BufferPointer]=Letter;

if (++BufferPointer==12) { BufferPointer=0;

LongIntTemp = 0; LongIntTemp = Buffer[3]; Rxcord = LongIntTemp; LongIntTemp = 0; LongIntTemp = Buffer[2]; LongIntTemp = LongIntTemp >= 8 strOutBuffer(10) = UInt32Temp And 255 UInt32Temp >>= 8 strOutBuffer(9) = UInt32Temp And 255 uInt32Temp >>= 8 strOutBuffer(8) = uInt32Temp And 255 SerialPort.Write(strOutBuffer, 0, 12) ' send x,y,z coordinat strInBuffer = SerialPort.ReadByte() ' Wait for the Microcontroller to 0

If I programmes the microcontroller with coordinates at "boot/reset" to moveto(x,y,z); everything works fine. So I pretty sure that the problem is in the convertion some where..? I have tryed to ecco the send bytes back to the main program, and that looks ok as well. I have also tryed to convert the recived bytes using the "Buffer[3]+Buffer[2]*256+Buffer[1]*256*256+Buffer[0]*256*256*256" methode but with same result at the above code..

I hope it's some thing simpel I have missed..

- Henning

k
Reply to
Henning Mortensen

What is happening - wrong behaviour, no response at all, lockups?

Of what type are the elements of Buffer - make sure it is unsigned (uint8_t), otherwise you will get sign extension for values over 0x7f when copying them into your long.

What C compiler are you using for the AVR side, does it give any warnings?

Oh, one more thing: is the "moveto()" a time-consuming operation? You want to avoid those in an ISR. (Usually, the ISR just handles receiving and storing the characters e.g. in a ring buffer, the main program handles processing them)

Let's get the basic communication to work first in principle, then make your code a bit more compact :-)

Regards, Gilles.

Reply to
Gilles Kohl

Hi Gilles,

You did it with nothing more than "make sure it is unsigned (uint8_t)" I used a char as i was 110% sure that was equal to an unsigned 8 bit byte... I have used char a billion times without problems. But here it was what gave all the problems..

Thanks for all your help.

Now my homemade CNC cutter (plotter for now, still need Z-axes hardware) can draw nice shapes :)

- Henning

Reply to
Henning Mortensen

You're welcome, glad that I was able to help :-)

Here's a suggestion for an alternate coordinate reading function:

uint32_t ReadCoordinate(void) { uint32_t receivedValue = 0L;

for(int i=0; i < 4; i++) { receivedValue |= (long)GetSerialByte() = 0; bitStart -= 4) { TransmitSerialByte("0123456789ABCDEF"[(coordinate >> bitStart) &

0x0F]); } SendSerialString("\r\n"); }

This is a test routine that uses the above functions:

void CoordinateTest(void) { uint32_t coordinate; while(1) { SendSerialString("Waiting for coordinate\r\n"); coordinate = ReadCoordinate(); EchoCoordinate(coordinate); } }

I quickly tested that in Hyperterminal - you can e.g. press Ctrl-A, Ctrl-B, Ctrl-C, Ctrl-D, and should get back "Received: 0x04030201"

I'm appending excerpts from the routines used in the above - take these with a grain of salt though:

- they may not be complete (pasted, not tested :-)

- they are from an Atmega128 project of mine, so you'll have to adapt the hardware specific stuff (e.g. register names) for your Atmega8

- I'm an AVR noob although I've been programming in C for some while :-)

- your newsreader (or mine) may have messed up line wraps.

- this is using gcc in gnu99 mode which may not be compatible with your makefile / remaining code.

Regards, Gilles.

serialcomm.c:

------------------------------

#include

#include #include

#include "serialcomm.h"

/// Size of ring buffer for reception (RINGBUFFER-1 bytes may be received without being processed) #define RINGBUFFER_SIZE 64

static volatile uint8_t ringBuffer[RINGBUFFER_SIZE]; static volatile uint8_t bufferHead; ///< incoming bytes will be stored here static volatile uint8_t bufferTail; ///< Retrieved bytes will be delivered from here

/// Set up serial hardware /// @param divisor divisor to set up baudrate - use BAUDDIVISOR macro void InitializeSerialPort(uint16_t divisor) { cli(); // don't disturb while we're setting up // Set baud rate UBRR1H = (uint8_t)(divisor>>8); UBRR1L = (uint8_t)divisor; // Enable receiver, transmitter, and received character interrupt UCSR1B = _BV(RXEN)|_BV(TXEN)|_BV(RXCIE); // Set frame format: 8 data, 1 stop bit UCSR1C = _BV(USBS)|(3

Reply to
Gilles Kohl

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.