RS232 transmission

Status
Not open for further replies.

crush

New Member
programming novice here,
tryin to transmit a start bit 3 variables and a stop bit.
all varaibles contain numbers
I have written the code (refer end of post) to perform the RS232 transmission and am monitoring the data recieved on a prgramme called serial watcher, which shows me data in decimal.

The problem is on of the variables is 16bit variable (off_time), hence i am only recieving the lower 8 bits.
this is because the protocol is data width - 8 bits.
Any ideas as to how to overcome this problem wld be much appreciated.
Thanks
Nick.

Code:

init:
{ SPBRG=64; //baud rate 4800
BRGH=0;
SYNC=0; //asynchronous mode
SPEN=1;
TX9=0;
TXEN=1;
}
transmit:
{ start = 1;
TXREG = start;
while(TRMT == 0){};
TXREG = off_time; // 16 bit variable
while(TRMT == 0){};
TXREG = mux_number;
while(TRMT == 0){};
TXREG = grid_number;
while(TRMT == 0){};
TXREG = start; //transmits Stop bit - 1
while(TRMT == 0){};
}
 
Can't help you with C, but you simply send each 8 bits seperately, with their own start and stop bits - it's often a good idea though to convert the number to ACSII and send it as an ASCIII string, this avoids any null or special character problems.
 
if you don't like sending in ASCII string, just send 8 bit seperately and then reassemble into 16 bit in your receiver.
 
in my opinion ,you should use interrupt function to tranmist and receive the data
via RS-232 communication .It is not very difficult .You should use C language to program .It is easy to do it
 
I only program in asm, however, from your code the "off_time" varible that you are tx'ing, can only be tx'd as an 8bit number (hence the missing higher byte).

You need to divide your "off_time" number into 2 bytes, the way to do this in asm is to rotate "off_time" 8 times, into another register ("off_time_high"?) and then transmit this you will then end up with 2 bytes at your PC.

I wish I could help you more in "C" it's something that I am looking into, a lot of us old dinosaurs only program in ASM it's all there was when we started

I hope this helps (a bit!).
 
as mentioned before in this thread, transmitting a 16 bit number can basicly be done in 2 diffrent ways. Either convert it to ASCII text and send that (i would recomend this), or you send each 8 bit part of the number seperatly.

To split a 16 bit number into two 8 bits do one of the following:
Lets say you have the following variables:
a 16 bit integer called nVal;
a 8 bit integer called nHighByte;
a 8 bit integer called nLowByte;

What you want is instead of sending the nVal alone, split it onto the nhighByte and nLowByte and send each of these seperatly;

Alt. 1)
nHighByte = nVal / 256; // this gives you the highest 8 bits
nLowByte = nVal % 256 // this gives you the lowest 8 bits

you can also do this instead of the last line:

nLowByte = nVal-(nVal/256)*256;
The result would be the same.


Now both these ways is very bad programing and causes your cpu to do more work then is stricly needed.
If you have a compiler that is very good at optimising asembly code it will notice that a diviton by 256 is the same as shifting 8 places to the right.

You can do bit shitinglike this in c like this:

Alt. 2)

nLowByte = nVal; // since nLowByte is only 8 bits, it will store only the first 8 bits of nVal, the lower 8 bits;

nHighByte = nVal >> 8; //this shigts all the bits in nVal 8 places to the right, wich is equivalent to dividing by 256, exept its done alot faster, unles your compiler can optimise good enoguh to figure it out.



What c-compiler are you using? Ive opnly used CCS and in this compiler you can send stuff over the rs232 lines by using simple printf and puts statments (similar to old dos code). This sends values in asci text, and is very easy to use. Id recomend doing that, and if that dont work, try Alt. 2 above for splitting a 16 bit integer.

Cheers,
Magnum
 
Last edited:
I don't use C (and have no intention of ever doing so), but doesn't it have a function like High() and Low() which return the upper and lower parts of a 16 bit variable?.

I also agree though that it's better to send it as ASCII characters.

In fact, in my tutorial 11.4, I use a couple of flags to select LCD or RS232, if it's flag is set the value is send as ASCII to that device, if both are set, then both devices receive it - with the RS232 version getting a CR/LF after it. It's a really nice simple routine, that works extremely well.
 
Most c-compilers have macros called HI() and LO() (or somthing similar) that basicly does the nVal >> 8 shift thing.

I usualy just write the >> things, cus it makes the code clearer to read to my eyes (i like to keep things simple ... to many fancy code things makes it harder to read imo)

but sure, you can check your c-compiler if you have somthing like that .
In my ccs compiler there are some functions called shift_left(...), shift_right(...), etc... but they are confusoing to me...

I like the >> better
 
Thank you all for the information. After some reading i found the most common way as suggested by "ombrastein" , "penoy_balut", "Nigel Goodwin" was to break the 16 bit variable into 2 8 bits.

I achieved this by just going through it and checking how value transfers were taking place on the watchwindow(novice-remember! so went to basics. Tedious - but it works!!) :

off_time_temp = off_time; //offtime is 16bit, assigning to a temp
off_time_L = off_time; // transferring 8 LSB's
off_time_temp = off_time_temp >> 8; //shifting the MSB's
off_time_H = off_time_temp; //transferring 8 MSB's

Elsewhere in my program i had to transfer 2 8bit variables into 16 bits, i achieved that by going back to boolean first principles (OR)

the method most described in microchip
edge_1 = (CCPR1H<<8)+CCPR1L; // not working

was not giving expected answer due to overflow in register

so im simply OR'd the each register individually, shifting after transferring the MSB's

Thanx again to all posts
 
off_time_temp = off_time; //offtime is 16bit, assigning to a temp
off_time_L = off_time; // transferring 8 LSB's
off_time_temp = off_time_temp >> 8; //shifting the MSB's
off_time_H = off_time_temp; //transferring 8 MSB's

could be simplified to:


off_time_L = off_time; // transferring 8 LSB's
off_time_H = off_time_temp >> 8; //transferring 8 MSB's

saves you 2 bytes of memory and a few instructions of code, not to mention its alot easier to read


edge_1 = (CCPR1H<<8)+CCPR1L;

This could probably be done witha type cast like this:

edge_1 = ((unsigned long)CCPR1H<<8)+CCPR1L;

//asuming long is a 16 bit on the compiler your using


or just:
edge_1 = (CCPR1H)
edge_1 = (edge_1<<8)+CCPR1L;

Cheers
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…