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.

Beginning 8051 with (keil) C

Status
Not open for further replies.

bitsurfer

Member level 3
Joined
Jul 19, 2012
Messages
56
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
Croatia
Activity points
1,734
Hello,
I am absolute beginner in microcontrollers and uC programming.
With some experience in PC C programming I started with first program in keil C.
So I have few questions for experienced programmers.

1) In my uVision3 project I have included file "AT89X51.H" in which bit 0 of port 2 is defined as:
Code:
    sbit P2_0 = 0xA0;

Later in program I want to simplify this bit by giving him understandable name, like:
Code:
   sbit relay = P2_0;
... but I get error "BLINK.C(12): error C146: 'P2_0': invalid base address"

However, later I find that I can declare "relay" as such: "sbit relay = P2^0;" or "sbit relay = 0xA0;" but anyway I would like to know why I can't assign "P2_0" to "relay" when both are of same type (sbit).

2) My first project is a simple counter with few delays which shift led's, turn on/off relay and print counted number to lcd.
Somewhere in my code I have to make a string (unsigned char[]) from my (counted ) number so I include <stdio.h> at top of program and use
Code:
   sprintf(buf1, "%d", counted);
... like I would do in C programming at PC.
But while all program (hex) is long about 1,5 kb this single line takes additional 3 kb of program!
Using <stdio.h> seems to me very comfortable for use but price (in bytes) seem's very high.
Is this normal?
And if is:
How to convert counted number to char array to be suitable to show on display without too much spended bytes?
 

According to Keil forum:-

This error message indicates that the byte base address specified for an SBIT is not valid. The byte address of an SBIT must be an SFR whose least significant nibble must be 0 or 8. For example:

sfr P1 = 0x90;
sbit P1_0 = P1^0; // This is valid

sfr P4 = 0xD1;
sbit P4_0 = P4^0; // This is NOT valid since P4 is not an a 0 or 8 boundary
For SFR addresses that are not bit-addressable, you might use standard AND and OR operations to access the indivitual SFR bits.

Example:

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
sfr P4 = 0xD1;
 
void test (void)  {
  if (P4 & 0x01)   {   // if bit 0 set
    P4 |= 0x80;        // set bit 7
  }
  else  {
    P4 &= ~0x02;       // reset bit 1
  }
}

 
2) My first project is a simple counter with few delays which shift led's, turn on/off relay and print counted number to lcd.
Somewhere in my code I have to make a string (unsigned char[]) from my (counted ) number so I include <stdio.h> at top of program and use
Code:
   sprintf(buf1, "%d", counted);
... like I would do in C programming at PC.
But while all program (hex) is long about 1,5 kb this single line takes additional 3 kb of program!
Using <stdio.h> seems to me very comfortable for use but price (in bytes) seem's very high.
Is this normal?
And if is:
How to convert counted number to char array to be suitable to show on display without too much spended bytes?



This is because of sprintf function.
Normally it is chosen to display floating numbers.
As you are displaying Integers don't use sprintf function and don't load hex file of stdio.h
It will increase the size of .HEX file.
Just try to convert your value in ASCII code and then send it to LCD.
No need of sprintf function in your logic.
Hope this helps you
 

OK, thanks, I understand now something more about declaring.

@Jigar, How can I convert int value to ascii code?
I try to cast and also with itoa, but this seem's not work in keil C.
 

If you're willing to convert values of 0 to 255 Decimal range (8 bit data) then the program will be like this :
(and if you have 16 bit data then I'll post that too, just tell me)

Code:
void main()
{
unsigned char x,y,d1,d2,d3;
y = 0xFD;                   // y is your value, here I've take 0xFD  (253 in Decimal)
x = y / 10;                 // after execution x will have answer and y will have remainder (x=25 & y=3)
d1 = y % 10;                // after execution y will have no change and d1 will have remainder (y=3 & d1=3)
                            // means you've got d1;your LSD (Least Significant Digit)
d2 = x % 10;                // after execution x will have no change and d2 will have remainder (x=25 & d2=5) 
                            // means you've got d2;your middle Digit
d3 = x / 10;                // after execution d3 will have answer and x will have remainder (d3=2 & x=5)  
                            // means you've got d3;your MSD (Most Significant Digit)

// now we need to display all three digits 'd3=2' , 'd2=5' & 'd1=3'.
// for that you need to add 30 in these values

d1+=30;
d2+=30;
d3+=30;
// Now you have 'd3=32' , 'd2=35' & 'd1=33'

// And these new values are the Ascii Code of your actual numbers (Remember : by adding 30 you get ASCII)

// Now just send these variables to LCD and display them

// Hope this helps you
}
 
Very interesting and helpful soulution Jigar, thank you.
Never seen before such approach but I understand how it works.
I would like to see solution for longer value types if you want to post it.

In order to show data in lcd I have to get those data (d1, d2, d3) in char array.
I will try to get it working by myself and ask for help if I stuggle in problems.

But when we talk, maybe is possible to use a same or similar technique to show floats?

I get it working (somehow) :)
This takes 0,23 kb in my hex file :)

declarations:
Code:
unsigned char buf0[16] = {0};
unsigned char x,y,d1,d2,d3;

conversion:
Code:
y = myint;
x = y / 10;
d1 = y % 10;
d2 = x % 10;
d3 = x / 10;

d1+=0x30;
d2+=0x30;
d3+=0x30;

buf0[0]=d3;
buf0[1]=d2;
buf0[2]=d1;

showing:
Code:
lcd_pos(0); //first row, first character
p = 0;
while(buf0[p] != '\0')
{						 
	lcd_wchr(buf0[p]);
	p++;
}

This show's numbers from 000 to 999.
It would be useful to make a function for converting like:

void convf(unsigned char buffer[16], float number, int decimals=0)

where arguments are char array, any kind of number, optional number of decimals to show.

Is it possible and reasonable to make such function for reuse?
 
Last edited:

It can be even small:
(I've used 16x2 LCD, hope you get all the pins like RS,E,RW...)

Code:
void command(unsigned char value)         // Function to give command to LCD
{
	P2 = value;
	RS = 0;
	RW = 0;
	E = 1;
	delay(1);                                     // delay of 1ms
	E = 0;
}

void display()                                        // Function to Display
{
        d+=30;
	P2 = d;                                       // sending data to P^2 (LCD)
	RS = 1;
	RW = 0;
	E = 1;
	delay(1);
	E = 0;
}

void main()                   // HERE IS THE MAIN FUNCTION
{

unsigned char x,y,d;       // 3 variables are enough, NO NEED OF ANY ARRAY
y = myint;
x = y / 10;
d = y % 10;
command(0x83);            // command function to set cursor at 3rd place of the LCD for LSD
display();
d = x % 10;
command(0x82);           // command function to set cursor at 2nd place of the LCD for Middle digit
display();
d = x / 10;
command(0x81);          // command function to set cursor at 1st place of the LCD for MSD
display();

}

// In short try to use MINIMUM variables and no. of Lines.
// Main concept is just use 1 variable and place it wherever you want on LCD. NOTHING ELSE
 

Referring to previous questions

Later in program I want to simplify this bit by giving him understandable name, like:
sbit relay = P2_0;

What you want to achieve isn't actually an assigment and can't use assignment syntax.

Instead, you can use a preprocessor command to create an alias name for the originally defined object. This isn't a Keil specific thing rather than basic C syntax which you should review in your favourite C text book.
Code:
#define relay P2_0

I try to cast and also with itoa, but this seem's not work in keil C.
Nothing that could be done with type casts. itoa() would be a correct way, but isn't supported by the Keil C51 library. Did you notice the Keil library help files listing the available functions? In fact sprintf() is the only general number to ASCII formatting method provided by Keil
 

@FvM, I still don't became familiar with keil and any other micro related C.
Just ask here is it normal to spend 3 kb of hex file to get conversion from number to string.
OK, sprintf offers formatting and joining strings so I search for other methods to achieve this.
Can you recommend some "better C" to start with when we talk about 8051 family, mostly 89s52?
 

bitsurfer,

Its not a question of "better C". As Fwm told you, and I also think that you should go for "basic C syntax which you should review in your favourite C text book."
And try to write your own functions where possible. The code size will be smaller and you will get a chance to know "what is going on"
Jigar 4 Electronics showed you an example above.
Read books like Muhammad Mazidi's PIC Microcontroller.
 

Can you recommend some "better C" to start with when we talk about 8051 family, mostly 89s52?


There is the only option to use C in field of embedded systems and that is " Embedded C ".

What you're doing/asking about is all called " Embedded C Programming Language ".

No other Type does exist like : Keil C or any other better C !!!

Just you need to know all functions, data types etc etc.. of Embedded C to use it.

Then You need to know that how much functions your software's Library have.

And then implement your logic through those available functions.
No need to be confuse, Just go through the below link :

https://www.phaedsys.com/principals/bytecraft/bytecraftdata/bcfirststeps.pdf


This is the basic book of Embedded C, includes everything you should know about it AS A BEGINNER.

All the best :)
 

Just ask here is it normal to spend 3 kb of hex file to get conversion from number to string.
sprintf() with integer support doesn't need 3 kB according to my observations, it's only about 1 kB. If you are also using float variables in your code, the printf() float support is added, whether you are actually printing float variables or not.
Can you recommend some "better C" to start with when we talk about 8051 family, mostly 89s52?
There's a number of other commercial C51 compilers as well as free ones. Keil can be considered as the industry standard and is known to generate rather effective code.

The problem with printf() respectively sprintf() is that the library code is included without checking which format options are actually used in your application, even if no numeric output is needed. This is o.k. for most applications that are using a number of different print format strings anyway.
 

OK guys, here is very much to read and it is easier to ask good and experienced people for help and advices :)
I will surely read as much as possible but parallel with work and experimenting.
I know c already but usage with this kind of c is a bit different.
For example I need some time to connect '%' symbol with 'mod' which I used often on PC programming :)
Now I have this:
Code:
    buf0[3]=(myint%10)|0x30;     	
    buf0[2]=(myint/10)%10|0x30;
    buf0[1]=(myint/100)%10|0x30;  
    buf0[0]=(myint/1000)%10|0x30;

Works OK :)
@Jigar, I have array because I have old display routine which asks for array.

Finally, not much but I learned something here anyway!

Thanks for helping.
 

Well, after all I come to floating point.
My ADC (0832) work good and by applying upper formulas I get values from 000 to 255.
Now my code look's like this:
Code:
	radc = read_adc(0);		
		
		buf0[3]=(radc%10)|0x30;     	
		buf0[2]=(radc/10)%10|0x30;
		buf0[1]=(radc/100)%10|0x30;  
		
		fradc = radc/255.0*5.0;
And here is a problem with 'fradc' which is number of float type and I need to show him with whole and decimal numbers.
With using of:
Code:
	sprintf(buf1, "%2.3f", fradc);
...the size of hex file grows much.

So I would kindly ask if here is a way to do conversion to ascii with decimals without using stdio.h.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top