Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

C Changing variable types K*E*I*L

Status
Not open for further replies.

GrandAlf

Advanced Member level 2
Joined
Mar 9, 2002
Messages
520
Helped
47
Reputation
92
Reaction score
6
Trophy points
1,298
Location
UK
Activity points
4,730
keil variable types

I have an int variable that in certain parts of the program contains a number less than 255. I need to send this as a single byte to the serial port (SBUF=xx). Just before transmitting I copy the contents to a char variable and send that instead, at the other end the numbers 1,2,3 are received ok, but 4,5,6 etc are not. I cannot directly use a char variable, as in other parts of the program it need to be 16bits. Have also tried sending int variable directly. Also with AND to mask out upper byte, and with >>4 and <<4 to shift bits. None of these attempts seem to work correctly. I would be most appreciative of any advice.
 

What about this:

union
{
unsigned char bytevar[2];
char charvar[2];
unsigned int wordvar;
int intvar;
}variable;

If you want to use it as 16 bit variable.wordvar or variable.intvar
Or as 8 Bit varible.bytevar[0] or variable.bytevar[1] or variable.charvar[0] or variable.charvar[1]

Keil puts the lowbyte of the 16 bit variable in bytevar[1] Hi-Tech on the Pic does it the other way round ...

hope this helps
 

Thanks C-Man,
To the rescue once again!.

Just a small point, if K*eil puts just the the lower byte when copied, why cannot one just do the following?.

unsigned int a;
unsigned char b;
b = a;
 

Just a small remark: shifting a byte is >>8 or <<8, not >>4 or <<4.
Maybe this explains...

FD.
 

Hi,
this comments are non compiler specific, but may be of additional interest for you if you try to send single chars over the serial port:
- you can cast your int to unsigned char when assigning the variable to SBUF
- maybe you have an timing problem; some MCUs have fifo styled xmt buffers for transmitting chars and thus allowing to write multiple chars in sequence before they got sent out by your serial port

hope it helped,
Maddin
 

Thx FD, Just a Silly typo.

Maddin, Think it may be a timing prob as received data varies. Maybe because of using SBUF direct?.
 

The interpretation of int and char , meant whether they are signed or unsiogned is compiler specific feature .
Is it the signed int you trying to send ?
If number in signed int is possitive try to cast like
(unsigned char)((unsigned int)tnum) before sending .

Another approach , but I do not know whether machine is big endian or little endian

unsigned char *pchar = (unsigned char*)(&intnumber);
then
sendByte(*pchar) - if it is little endian
or
sendByte(*(++pchar)) if it is big endian
 

GrandAlf said:
Thx FD, Just a Silly typo.

Maddin, Think it may be a timing prob as received data varies. Maybe because of using SBUF direct?.

This could be the case if you write too frequently to the serial buffer. Try to introduce some simple queuemanagement that extends your MCU's fifo or, if you have plenty of time, just check your MCU datasheet for a flag that can be polled to check when your xmt buffer is free again for writing into it.
The better way will of course be using the queue in conjunction with an xmt-interrupt service routine....
Maddin
 

GrandAlf if you use the hardware UART of the 8051 you might have to wait until a previous character has been sent out and the transmit buffer is empty.

Here is a snippet of the code I am using:

void serial_out(unsigned char character)
{
while(!TI)
continue;

TI=FALSE;
SBUF=character;
}

The routine waits until the TI (transmit interrupt) flag gets set which signs that the previous character has been sent completely.

hope you can use it, best regards
 

Thx artem,
Both char and int are unsigned. Have tried putchar(b); , but it locks up the cpu. Still learning C, maybe I can use printf to send raw data, rather than using SBUF directly.
 

As lasst resort try to catch the value you send to the port and sese what is the assembler output . This for sure is the last resort if nothing wrong with hardware .
 

Thanks everyone,
C-Man, I used your routine, but changed FALSE to 0, as I do not have it defined. Program stays in this routine forever. This leads me to suspect that the flag is never set/unset. Must have some register settings wrong. Will have to a bit more reading I think.
 

GrandAlf send me your code either by PM or post it here, I will have a look at it for you ...

best regards
 

Thats very kind of you C-Man,

This is the code that I use to setup the serial port, I am only transmitting (blind) BTW, and not receiving.

//FUNCTIONS
void serial_init (void) {
SCON = 0x50; // mode 1: 8-bit UART, enable receiver
TMOD = 0x20; // timer 1 mode 2: 8-Bit reload
TH1 = 0x98; // reload value 300 baud
TR1 = 1; // timer 1 run
ES = 0; // Disable serial port interrupt
EA = 0; // Disable
RI = 1;
TI = 1;
 

Sorry, I forgot to say the cpu is Atmel 89S8252.
 

Try this new initialization code instead of the posted code

TMOD = 0x20; // timer 1 mode 2: 8-Bit reload
TH1 = 0x98; // reload value 300 baud
SCON = 0x52; // mode 1: 8-bit UART, enable receiver TI remains set
TR1 = 1; // timer 1 run
ES = 0; // Disable serial port interrupt
EA = 0; // Disable

I know I gave you the old code but after checking my code I saw that I use an extra flag which gets the status of the TI flag in the serial interrupt routine (and of course I set this flag at power on).

At power on the TI bit is set which means you can put a new byte into SBUF but as the old initialisation code erases TI (it is located in SCON) it will never get set again (it would get set if you put a byte into SBUF without waiting for TI to get H).

I think you can only clear (and not set) TI and RI by software as it is set by hardware.

Hope things will be working with this code ...

best regards
 

C-Man.

Still pretty much the same with this configuration. I can send 1,2,3 and receive them correctly, but 4 upwards is not received or wrong. I am pretty sure that the receiving end is ok, difficult to check what is being sent out as they are non printable characters. Also difficult to do a simulation without a major change to s/w, as I have probs with peripherals and eeprom.

Stange thing though, if I try to use printf or putchar insted of SBUF, the prog does not return from the function, thus effectivly locking the mpu. I would sumise that these funcions are waiting for a flag to be changed, and this it is not happening.

I think I will have to re-write a small section of code that I can simulate, and then go on from there.

I really appreciate all your advice, thank you so much.
 

I think I have found the problem, seems to be with rtos. Single task is ok. At least I have something to work on now. Thanks for all your advice chaps.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top