This Blog is created for Embedded Systems Lovers irrespective of whether they are freshers or experienced. This blog gives a chance to everyone to learn new things and stay updated with the latest Embedded Technology. Articles, Tutorials, Project Source codes, PCB Layouts, Free Ebooks, and other free downloads would be available! The author is not responsible for any kind of mishaps,while developing applications. If you are not an expert in electronics, kindly take help from your seniors before starting with any of the projects described here. Hope you enjoy the Blog. Reader Comments would be highly appreciated !

Total Pageviews

Career in Embedded Systems

Many students are not aware of the lucrative opportunities available in the field of Embedded Systems. Most graduates go after the popular “IT” industry to seek a good career. I think there are 2 reasons for this1)lack of awareness 2) entry barrier. While studying most students may come across the name “Embedded Systems”. Apart from that they may not be aware of -”what is an embedded system”, how do they work, what knowledge and skills should be acquired to build a great career in the field of embedded systems, which companies are working in this field etc etc. If it is in the case of computer science – the industry is readily known – the lucrative IT industry. The leading companies are Microsoft,Google,Adobe (product based) and there are many smaller and medium ones. There are service based IT firms like Wipro, Infosys, Accenture,Cognizant etc. Knowledge and skills required is mainly about programming languages and technologies – like Java, Asp.net, C & C++, Python, Php etc etc.. the list goes on. Entry barrier to the IT industry is very low. Any fresher with a basic skill and knowledge can get a job in this IT industry and that too with a decent entry level salary (well, that’s not the case always!!)
embedded systems career
When it comes to Embedded systems – do you know who all are the leading players in this industry? Let’s have a look.
Samsung – They make mobile phones and gadgets, consumer electronics like washing machine, microwave oven, television, air conditioners etc. You must know that there are “n” number of competitors for Samsung who make similar products. All these products has embedded systems – with its own hardware and software. For example:- In an air conditioner functions like – ‘intelligent room temperature control’ will be controlled by the embedded device inside the air conditioner. This embedded device will be made of a microcontroller, its associated hardware and software for intelligent temperature sensing
Siemens – They make products in the field of medical electronics and automation industry.The products will be scanner, doppler, cardiograph machines, radiology machines etc etc.. its a big list. 
Bosch – They make products for automotive industry.
I just mentioned 3 companies serving 3 different industries. There are thousands of other companies in the field of embedded systems – offering various kinds of services, consultation and product building.
Now we got an idea of companies that can offer a job in embedded systems. Now lets take a look at who all can opt for a career in embedded systems. The basic requirements will be a graduation/post graduation in electronics. There are many such courses offered by various kinds of universities. I will say, easy entry is for engineering degree holders in different streams of Electronics engineering – like Electrical and electronics, Electronics and communication, Electronics and instrumentation etc.  Other degree holders in electronics like Bachelor of Science (Electronics as main), Master of Science (Electronics) as main can also opt for a career in Embedded systems. 
Knowledge and skills  required in these areas are-  Good knowledge in theory and practical of one or two micro controllers like PIC, 8051, or AVR etc. Deep and sound knowledge in programming language C – especially embedded C. Knowledge in these 2 areas will help you to get an entry level job in the field of embedded systems. The real “learning curve” will only start at your first job – where you will deal with real issues and problem solving methods.  After gaining much experience from the first job (may be a 2 years) you can always switch to big companies.
The trend we see here in India is, freshers will boost their knowledge in these areas – especially in controllers and C programming by taking a good training after their graduation. The reason is an “outdated” and inefficient curriculum used by many universities in India. Even in an engineering course, there is only a single paper about microcontrollers. Most fresh graduates are unemployable in Embedded systems (unless some mavericks build their own way up learning all themselves).  To supplement this, fresh graduates take 3 or 6 months additional training. This will help them to land at an entry level job, usually in a medium level company. They gain more knowledge at this job and later switch  to bigger ones like Bosch, Samsung etc.
The first job you take will have a very high influence on your career. Example:- An employee working with a “Consulting type” company is likely to work his career in that direction. Where as a “Product based” company is a little different and they function in an entirely different way than a “Consulting company”. So be aware of your first job – what you learn there will decide the way your career is headed!

By- CircuitsToday

Are you looking for final year projects, embedded projects. Get it from the experts. Visit www.embedsols.com for more details.

Robot Assisted Surgery

Technology is revolutionizing the medical field with the creation of robotic devices and complex imaging. Though these developments have made operations much less invasive, robotic systems have their own disadvantages that prevent them from replacing surgeons. Minimally invasive surgery is a broad concept encompassing many common procedures that existed prior to the introduction of robots, such as laparoscopic cholecystectomy or gall bladder excisions. It refers to general procedures that avoid long cuts by entering the body through small (usually about 1cm) entry incisions, through which surgeons use long-handled instruments to operate on tissue within the body. Such operations are guided by viewing equipment (i.e. endoscope) and, therefore, do not necessarily need the use of a robot. However, it is not incorrect to say that computer-assisted and robotic surgeries are categories under minimally invasive surgery.

Both computer-assisted and robotic surgeries have similarities when it comes to preoperative planning and registration. Because a surgeon can use computer simulation to run a practice session of the robotic surgery beforehand, there is a close tie between these two categories and this may explain why some people often confuse them as interchangeable. However, their main distinctions lie in the intraoperative phase of the procedure: robotic surgeries may use a large degree of computer assistance, but computer-assisted surgeries do not use robots.
Computer-assisted surgery (CAS), also known as image-guided surgery, surgical navigation, and 3-D computer surgery, is any computer-based procedure that uses technologies such as 3D imaging and real-time sensing in the planning, execution and follow-up of surgical procedures. CAS allows for better visualization and targeting of sites as well as improved diagnostic capabilities, giving it a significant advantage over conventional techniques. Robotic surgery, on the other hand, requires the use of a surgical robot, which may or may not involve the direct role of a surgeon during the procedure. A robot is defined as a computerized system with a motorized construction (usually an arm) capable of interacting with the environment. In its most basic form, it contains sensors, which provide feedback data on the robot’s current situation, and a system to process this information so that the next action can be determined. One key advantage of robotic surgery over computer-assisted is its accuracy and ability to repeat identical motions.

Further division

Robotic surgery can be further divided into three subcategories depending on the degree of surgeon interaction during the procedure: supervisory-controlled, telesurgical, and shared-control. In a supervisory-controlled system, the procedure is executed solely by the robot, which will act according to the computer program that the surgeon inputs into it prior to the procedure. The surgeon is still indispensable in planning the procedure and overseeing the operation, but does not partake directly. Because the robot performs the entire procedure, it must be individually programmed for the surgery, making it extremely expensive to gather several images and data for one patient. A telesurgical system, also known as remote surgery, requires the surgeon to manipulate the robotic arms during the procedure rather than allowing the robotic arms to work from a predetermined program. Using real-time image feedback, the surgeon is able to operate from a remote location using sensor data from the robot. Because the robot is still technically performing the procedure, it is considered a subgroup of robotic surgery. The da Vinvi® Surgical System, the current leading device in this field, belongs to this section of robotic surgery. The third shared-control system has the most surgeon involvement. The surgeon carries out the procedure with the use of a robot that offers steady-hand manipulations of the instrument. This enables both entities to jointly perform the tasks.
Before these procedures can be carried out, robotic surgery requires the use of computer imaging to diagnose and perform the operation. These imaging modalities can generate either 3-D figures through computed tomography (CT) and magnetic resonance imaging (MRI) or 2-D ones through ultrasonography, fluoroscopy, and X-ray radiography. Out of the various methods of imaging, the main one in use is computer tomography (CT). CT scans use back projection and detectors to obtain cross-section images that are particularly useful when diagnosing cancers and viewing the chest and the abdomen. This kind of imaging is critical to diagnosis. Because these images can pinpoint pathologies, the surgeon is given a great degree of precision in guiding the instruments around healthy tissue with minimal injury. However, before the procedure can be carried out, there are three steps that must be overcome: planning, registration, and navigation. Planning is achieved through the careful observation of the images that are generated through these different imaging modalities. The surgeon uses this information to determine surgical pathways and methodologies. Following this step, the surgeon must coordinate the image data with the actual patient in a process known as registration. Once this is achieved, a surgeon or robot can implement the navigation step. Using the planning and images, surgeons can manually guide instruments through the patient (computer-assisted) or robotic arms can carry out the procedure (robotic) using sensor feedback. The decision between robotic or manual navigation depends on cost, safety concerns, difficulty of execution, and other factors. These variables are changing, however, with the advent of cheaper robotic production methods and added safety features.
Because computer-assisted and robotic surgeries are so integrated, the advanced imaging techniques and robotics we explore will be classified as robotic surgery, or computer-assisted robotic surgery. Even if nothing is ever one hundred percent safe, devices have the potential to be fatal if they malfunction. Therefore, considerable consternation exists in the medical field over these equipment. Industries have attempted to reduce these risks through redundant sensors and robot movement barriers, but these safety features increase cost, making them inaccessible to some physicians. Nevertheless, robotic arms can access the body much easily through the small incisions than a surgeon can, and can integrate large amounts of data and images to access areas deep within the body with precision. And though they cannot process qualitative information to make judgments during the surgery, they are still able to filter out hand tremors and scale the surgeon’s large movements into smaller ones in the patient.

Are you looking for final year projects, embedded projects. Get it from the experts. Visit www.embedsols.com for more details.

Curiosity on Mars

NASA's Mars rover Curiosity has beamed back an incredible image of its surroundings, showing a spectacularly clear view of the enormous mountain that it will clamber up in the next few years.
The photo — with one of the rover's wheels visible in the bottom left corner, the rover's shadow stretched out in front, and the huge Mount Sharp looming in the background — was released by NASA today (Aug. 6) in a news briefing from the agency's Jet Propulsion Laboratory in Pasadena, Calif.
The image was sent back to Earth less than 24 hours after Curiosity (also known as the Mars Science Laboratory, or MSL) touched down on the Red Planet late Sunday night (Aug. 5 PDT; Aug. 6 EDT and GMT).
The photo is a full-resolution image that was taken by one of the rover's Hazard Avoidance cameras, or Hazcams, said Joy Crisp, MSL deputy scientist at JPL.
Mount Sharp is a giant Martian peak that rises 3 miles (5 kilometers) from the center of Gale Crater. The mountain's many geological layers are particularly intriguing to mission scientists, as they could hold a record of how the Red Planet has changed over time.
In the newly released image, Mount Sharp is clearly visible in the background.
"It's taller than any mountain in the lower 48 states, [so it's] pretty spectacular," Crisp said. "What catches your eye are the dark dunes piled up along the base of Mount Sharp." [1st Photos of Mars by Curiosity Rover (Gallery)]
The photo reveals that there are no major obstacles directly in front of Curiosity that could block its path to the mountain, Crisp added.
From the photo, Crisp and her colleagues were able to determine that Mount Sharp is located roughly 4 miles (6.5 kilometers) away from Curiosity. Mission controllers aim to eventually drive up part of the mountain to explore the layers of Martian rocks and soil.
The new photo is also the sharpest view yet seen of Curiosity's shadow against the Martian surface.
A separate Hazcam photo, taken by a camera on the rover's rear-left side, was also released during today's news briefing. The photo captures the view behind Curiosity, looking at the horizon and the northwest rim of Gale Crater, which is located approximately 17 miles (28 km) away, Crisp said.
"We can see the wheel of the rover," she explained. "It's very flat with these pebbles — no obstacles for driving. We'll be able to drive front or rearwards."
In the coming days, scientists will continue to receive and analyze photos from Curiosity, including a series of images taken as the rover descended to the surface of Mars.
These images, from the rover's Mars Descent Imager (MARDI), provide insight into the rover's thrilling seven-minute journey through the Martian atmosphere. Early MARDI images show the spacecraft's heat shield falling away shortly before it touched down on the surface of the Red Planet.

Are you looking for final year projects, embedded projects. Get it from the experts.
Visit www.embedsols.com for more details.

Embedded Systems Interview Questions

These are some of the common questions asked during interviews for the position of Embedded Software developer. There are plenty of other questions as well, I will keep on updating the list.

1.       What is an inline function?
2.       How are macros different from functions?
3.       In embedded systems perspective which is better to use. Macro or function?
4.       What is a volatile keyword? How it helps in the embedded perspective?
5.       How ISR is serviced?
6.       What is interrupt latency?
7.       What are the stages of compilation?
8.       What is booting?
9.       What is PID?
10.   What is hysterysis?
11.   Co-relation between pointers and arrays?
12.   If A and B finishes a work in 5 days. Where is does the work twice that of B. Suppose they finished the work in 3 days and B is doing the work normally then at what rate should A work to finish the work in 3 days?
13.   What is a constant pointer?
14.   What is a memory leak in structures? How can we rectify that?
15.   When the execution id going to service a interrupt what happens to stack and what are the registers saved?
16.   Without using pointer write a program to print the elements of an array?
17.   How are unions useful in embedded systems?
18.   What is optimization?
19.   How many pins are used in SPI? What are they?
20.   Explain the Start and Stop operation of I2C protocol?
21.   Is it possible to access or modify PC (program counter)?
22.   If int data type is occupying 4 bytes then on how many bit  uC does the code is running?
23.   Is C++ a superset of C?
24.   All C programs are executable in C++? True or False Why?
25.  What is a static storage class? How is it useful?
26.  How static is different from auto?

Are you looking for final year projects, embedded projects. Get it from the experts. Visit www.embedsols.com for more details.

Pointers, Arrays, Unions, Structure in Embedded C

Using Pointers, Arrays, Structures and Unions in 8051 C Compilers

Although both the Keil and Raisonance 8051 C compiler systems allow you to use pointers, arrays, structures and unions as in any PC-based C dialect, there are several important extensions allowing to generate more efficient code.

Using Pointers And Arrays

One of C's greatest strengths can also be its greatest weakness - the pointer. The use and, more appropriately, the abuse of this language feature is largely why C is condemned by some as dangerous!

Pointers In Assembler

For an assembler programmer the C pointer equates closely to indirect addressing. In the 8051 this is achieved by the following instructions
  1. MOV R0,#40     ; Put on-chip address to be indirectly
  2. MOV A,@RO      ; addressed in R0
  3. MOV R0,#40     ; Put off-chip address to be indirectly
  4. MOVX A,@RO     ; addressed in R0
  5. MOVX A,@DPTR   ; Put off-chip address to be indirectly
  6.                ; addressed in DPTR
  7. CLR A
  8. MOV DPTR,#0040 ; Put off-chip address to be indirectly
  9. MOVC A,@A+DPTR ; addressed in DPTR
In each case the data is held in a memory location indicated by the value in registers to the right of the '@'.

Pointers In C

The C equivalent of the indirect instruction is the pointer. The register holding the address to be indirectly accessed in the assembler examples is a normal C type, except that its purpose is to hold an address rather than a variable or constant data value.

It is declared by:
  1. unsigned char *pointer0 ;
Note the asterisk prefix, indicating that the data held in this variable is an address rather than a piece of data that might be used in a calculation etc..

In all cases in the assembler example two distinct operations are required:

   1. Place address to be indirectly addressed in a register.
   2. Use the appropriate indirect addressing instruction to access data held at chosen address.

Fortunately in C the same procedure is necessary, although the indirect register must be explicitly defined, whereas in assembler the register exists in hardware.
  1. /* 1 - Define a variable which will hold an address */
  2. unsigned char *pointer ;
  3. /* 2 - Load pointer variable with address to be accessed*/
  4. /*indirectly */
  5. pointer = &c_variable ;
  6. /* 3 - Put data '0xff' indirectly into c variable via*/
  7. /*pointer */
  8. *pointer = 0xff ;
Taking each operation in turn...
  1. Reserve RAM to hold pointer. In practice the compiler attaches a symbolic name to a RAM location, just as with a normal variable.
  2. Load reserved RAM with address to be accessed, equivalent to 'MOV R0,#40'. In English this C statement means: "take the 'address of' c_variable and put it into the reserved RAM, i.e, the pointer" In this case the pointer's RAM corresponds to R0 and the '&' equates loosely to the assembler '#'.
  3. Move the data indirectly into pointed-at C variable, as per the assembler 'MOV A,@R0'.
The ability to access data either directly, x = y, or indirectly, x = *y_ptr, is extremely useful. Here is C example:
  1. /* Demonstration Of Using A Pointer */
  2. void function(void)
  3. {
  4. unsigned char c_variable ; // 1 - Declare a c variable unsigned char
  5. *ptr ;                     // 2 - Declare a pointer (not pointing at anything yet!)
  6.   c_variable = 0xff ;      // 3 - Set variable equal to 0xff directly
  7.                            // OR, to do the same with pointers:
  8.   ptr = &c_variable ;      // 4 - Force pointer to point at c_variable at run time
  9.   *ptr = 0xff ;            // 5 - Move 0xff into c_variable indirectly
  10. }
Note: Line 8 causes pointer to point at variable. An alternative way of doing this is at compile time thus:
  1. /* Demonstration Of Using A Pointer */
  2. void function (void)
  3. {
  4. unsigned char c_variable;         // 1-Declare a c variable
  5. unsigned char *ptr = &c_variable; // 2-Declare a pointer, intialized to pointing at
  6.                                      c_variable during compilation
  7.    c_variable = 0xff ;   // 3 - Set variable equal to 0xff directly
  8.                          // OR - use the pointer which is already initialized
  9.    *ptr = 0xff           // 5 - Move 0xff into c_variable indirectly
  10. }
Pointers with their asterisk prefix can be used exactly as per normal data types. The statement:
  1. x = y + 3 ;
could equally well perform with pointers, as per
  1. char x, y ;
  2. char *x_ptr = &x ;
  3. char *y_ptr = &y ;
  4. *x_ptr = *y_ptr + 3 ;
  1. x = y * 25 ;
  2. *x_ptr = *y_ptr * 25 ;
The most important thing to understand about pointers is that
  1. *ptr = var ;
means "set the value of the pointed-at address to value var", whereas
  1. ptr = &var ;
means "make ptr point at var by putting the address of (&) in ptr, but do not move any data out of var itself".

Thus the rule is to initialize a pointer:
  1. ptr = &var ;
To access the data indicated by *ptr:
  1. var = *ptr ;

Pointers To Absolute Addresses

In embedded C, ROM, RAM and peripherals are at fixed addresses. This immediately raises the question of how to make pointers point at absolute addresses rather than just variables whose address is unknown (and largely irrelevant).

The simplest method is to determine the pointed-at address at compile time:
  1. char *abs_ptr = 0x8000 ; // Declare pointer and force to 0x8000
However if the address to be pointed at is only known at run time, an alternative approach is necessary. Simply, an uncommitted pointer is declared and then forced to point at the required address thus:
  1. char *abs_ptr ; // Declare uncommitted pointer
  2. abs_ptr = (char *) 0x8000 ; // Initialize pointer to 0x8000
  3. *abs_ptr = 0xff ; // Write 0xff to 0x8000
  4. *abs_ptr++ ; // Make pointer point at next location in RAM

Arrays And Pointers - Two Sides Of The Same Coin?

Uninitialized Arrays

The variables declared via
  1. unsigned char x ;
  2. unsigned char y ;
are single 8 bit memory locations. The declarations:
  1. unsigned int a ;
  2. unsigned int b ;
yield four memory locations, two allocated to 'a' and two to 'b'. In other programming languages it is possible to group similar types together in arrays. In basic an array is created by DIM a(10).
Likewise 'C' incorporates arrays, declared by:
  1. unsigned char a[10] ;
This has the effect of generating ten sequential locations, starting at the address of 'a'. As there is nothing to the right of the declaration, no initial values are inserted into the array. It therefore contains zero data and serves only to reserve ten contiguous bytes.

Initialized Arrays

A more usual instance of arrays would be
  1. unsigned char test_array [] = { 0x00,0x40,0x80,0xC0,0xFF } ;
where the initial values are put in place before the program gets to "main()". Note that the size of this initialized array is not given in the square brackets - the compiler works-out the size automatically upon compilation.

Another common instance of an array is analogous to the BASIC string as per:
  1. A$ = "HELLO!"
In C this equates to:
  1. char test_array[] = { "HELLO!" } ;
In C there is no real distinction between strings and arrays as a C array is just a series of sequential bytes occupied either by a string or a series of numbers. In fact the realms of pointers and arrays overlap with strings by virtue of :
  1. char test_array = { "HELLO!" } ;
  2. char *string_ptr = { "HELLO!" } ;
Case 1 creates a sequence of bytes containing the ASCII equivalent of "HELLO!". Likewise the second case allocates the same sequence of bytes but in addition creates a separate pointer called *string_ptr to it. Notice that the "unsigned char" used previously has become "char", literally an ASCII character.
The second is really equivalent to:
  1. char test_array = { "HELLO!" } ;
Then at run time:
  1. char arr_ptr = test_array ; // Array treated as pointer - or;
  2. char arr_ptr = &test_array[0] ;
  3. // Put address of first element of array into pointer
This again shows the partial interchangeability of pointers and arrays. In English, the first means "transfer address of test_array into arr_ptr". Stating an array name in this context causes the array to be treated as a pointer to the first location of the array. Hence no "address of" (&) or '*' to be seen.

The second case reads as "get the address of the first element of the array name and put it into arr_ptr". No implied pointer conversion is employed, just the return of the address of the array base.

The new pointer "*arr_ptr" now exactly corresponds to *string_ptr, except that the physical "HELLO!" they point at is at a different address.

Using Arrays

Arrays are typically used like this
  1. /* Copy The String HELLO! Into An Empty Array */
  2. unsigned char source_array[] = { "HELLO!" } ;
  3. unsigned char dest_array[7];
  4. unsigned char array_index ;
  5. array_index = 0 ; // First character index
  6. while(array_index < 7)   // Check for end of array
  7. {
  8.     dest_array[array_index] = source_array[array_index] ;      
  9.     // Move character-by-character into destination array
  11.     array_index++ ;  // Next character index
  12. }
The variable array_index shows the offset of the character to be fetched (and then stored) from the starts of the arrays.

As has been indicated, pointers and arrays are closely related. Indeed the above program could be re-written as:
  1. /* Copy The String HELLO! Into An Empty Array */
  2. char *string_ptr = { "HELLO!" } ;
  3. unsigned char dest_array[7] ;
  4. unsigned char array_index  ;
  5. array_index = 0 ; // First character index
  6. while(array_index < 7)     // Check for end of array
  7. {
  8.     dest_array[array_index] = string_ptr[array_index] ;  
  9.     // Move character-by-character into destination array.
  10.     array_index++ ;
  11. }
The point to note is that only the definition of string_ptr (previous source_array) changed. By removing the '*' on string_ptr and appending a '[ ]' pair, this pointer can be turned back into an array!

However in this case there is an alternative way of scanning along the HELLO! string, using the *ptr++ convention:
  1. /* Copy The String HELLO! Into An Empty Array */
  2. char *string_ptr = { "HELLO!" } ;
  3. unsigned char dest_array[7] ;
  4. unsigned char array_index  ;
  5. array_index = 0 ; // First character index
  6. while(array_index < 7)     // Check for end of array
  7. {
  8.     dest_array[array_index] = *string_ptr++ ;  
  9.     // Move character-by-character into destination array.
  10.     array_index++ ;
  11. }
This is an example of C being somewhat inconsistent; this *ptr++ statement does not mean "increment the thing being pointed at" but rather, increment the pointer itself, so causing it to point at the next sequential address. Thus in the example the character is obtained and then the pointer moved along to point at the next higher address in memory.

Summary Of Arrays And Pointers

To summarize

Create An Uncommitted Pointer
  1. unsigned char *x_ptr ;
Create A Pointer To A Normal C Variable
  1. unsigned char x ;
  2. unsigned char *x_ptr = &x ;
Create An Array With No Initial Values
  1.  unsigned char x_arr[10] ;
Create An Array With Initialized Values
  1. unsigned char x_arr[] = { 0,1,2,3 } ;
Create An Array In The Form Of A String
  1. char x_arr[] = { "HELLO" } ;
Create A Pointer To A String
  1. char *string_ptr = { "HELLO" } ;
Create A Pointer To An Array
  1. char x_arr[] = { "HELLO" } ;
  2. char *x_ptr = x_arr ;
Force A Pointer To Point At The Next Location
  1. *ptr++ ;


Structures are perhaps what makes C such a powerful language for creating very complex programs with huge amounts of data. They are basically a way of grouping together related data items under a single symbolic name.

Why Use Structures?

Here is an example: A piece of C51 software had to perform a linearization process on the raw signal from a variety of pressure sensors manufactured by the same company. For each sensor to be catered for there is an input signal with a span and offset, a temperature coefficient, the signal conditioning amplifier, a gain and offset. The information for each sensor type could be held in "normal" constants thus:
  1. unsigned char sensor_type1_gain = 0x30 ;
  2. unsigned char sensor_type1_offset = 0x50 ;
  3. unsigned char sensor_type1_temp_coeff = 0x60 ;
  4. unsigned char sensor_type1_span = 0xC4 ;
  5. unsigned char sensor_type1_amp_gain = 0x21 ;
  6. unsigned char sensor_type2_gain = 0x32 ;
  7. unsigned char sensor_type2_offset = 0x56 ;
  8. unsigned char sensor_type2_temp_coeff = 0x56 ;
  9. unsigned char sensor_type2_span = 0xC5 ;
  10. unsigned char sensor_type2_amp_gain = 0x28 ;
  11. unsigned char sensor_type3_gain = 0x20 ;
  12. unsigned char sensor_type3_offset = 0x43 ;
  13. unsigned char sensor_type3_temp_coeff = 0x61 ;
  14. unsigned char sensor_type3_span = 0x89 ;
  15. unsigned char sensor_type3_amp_gain = 0x29 ;
As can be seen, the names conform to an easily identifiable pattern of:
  1. unsigned char sensor_typeN_gain = 0x20 ;
  2. unsigned char sensor_typeN_offset = 0x43 ;
  3. unsigned char sensor_typeN_temp_coeff = 0x61 ;
  4. unsigned char sensor_typeN_span = 0x89 ;
  5. unsigned char sensor_typeN_amp_gain = 0x29 ;
Where 'N' is the number of the sensor type. A structure is a neat way of condensing this type of related and repeating data. In fact the information needed to describe a sensor can be reduced to a generalized:
  1. unsigned char gain ;
  2. unsigned char offset ;
  3. unsigned char temp_coeff ;
  4. unsigned char span ;
  5. unsigned char amp_gain ;
The concept of a structure is based on this idea of generalized "template" for related data. In this case, a structure template (or "component list") describing any of the manufacturer's sensors would be declared:
  1. struct SENSOR_DESC
  2. {
  3.   unsigned char gain ;
  4.   unsigned char offset ;
  5.   unsigned char temp_coeff ;
  6.   unsigned char span ;
  7.   unsigned char amp_gain ;
  8. } ;
This does not physically do anything to memory. At this stage it merely creates a template which can now be used to put real data into memory.

This is achieved by:
  1. struct SENSOR_DESC sensor_database ;
This reads as "use the template SENSOR_DESC to layout an area of memory named sensor_database, reflecting the mix of data types stated in the template". Thus a group of 5 unsigned chars will be created in the form of a structure.

The individual elements of the structure can now be accessed as:
  1. sensor_database.gain = 0x30 ;
  2. sensor_database.offset = 0x50 ;
  3. sensor_database.temp_coeff = 0x60 ;
  4. sensor_database.span = 0xC4 ;
  5. sensor_database.amp_gain = 0x21 ;

Arrays Of Structures

In the example though, information on many sensors is required and, as with individual chars and ints, it is possible to declare an array of structures. This allows many similar groups of data to have different sets of values.
  1. struct SENSOR_DESC sensor_database[4] ;
This creates four identical structures in memory, each with an internal layout determined by the structure template. Accessing this array is performed simply by appending an array index to the structure name:
  1. /*Operate On Elements In First Structure Describing */
  2. /*Sensor 0 */
  3. sensor_database[0].gain = 0x30 ;
  4. sensor_database[0].offset = 0x50 ;
  5. sensor_database[0].temp_coeff = 0x60 ;
  6. sensor_database[0].span = 0xC4 ;
  7. sensor_database[0].amp_gain = 0x21 ;
  8. /* Operate On Elements In First Structure Describing */
  9. /*Sensor 1 */
  10. sensor_database[1].gain = 0x32 ;
  11. sensor_database[1].offset = 0x56 ;
  12. sensor_database[1].temp_coeff = 0x56 ;
  13. sensor_database[1].span = 0xC5 ;
  14. sensor_database[1].amp_gain = 0x28 ;
  15. // and so on...

Initialized Structures

As with arrays, a structure can be initialized at declaration time
  1. struct SENSOR_DESC sensor_database = { 0x30, 0x50, 0x60, 0xC4, 0x21 } ;
so that here the structure is created in memory and pre-loaded with values.
The array case follows a similar form:
  1. struct SENSOR_DESC sensor_database[4] =
  2. {
  3.   {0x20,0x40,0x50,0xA4,0x21},
  4.   {0x33,0x52,0x65,0xB4,0x2F},
  5.   {0x30,0x50,0x48,0xC4,0x3A},
  6.   {0x32,0x56,0x56,0xC5,0x28}
  7. } ;

Placing Structures At Absolute Addresses

It is sometimes necessary to place a structure at an absolute address. A typical example are CAN interfaces or other peripheral chips that offer arrays of data groups.

For example, the registers of a memory-mapped real time clock chip are to be grouped together as a structure. The template in this instance might be
  1. // Contents Of RTCBYTES.C Module
  2. struct RTC
  3. {
  4.   unsigned char seconds ;
  5.   unsigned char minutes ;
  6.   unsigned char hours ;
  7.   unsigned char days ;
  8. } ;
  9. struct RTC xdata RTC_chip ; // Create xdata structure
A trick using the linker is required here so the structure creation must be placed in a dedicated module. This module's XDATA segment, containing the RTC structure, is then fixed at the required address at link time.

Using the absolute structure could be:
  1. /* Structure located at base of RTC Chip */
  2. MAIN.C Module
  3. extern xdata struct RTC_chip ;
  4. /* Other XDATA Objects */
  5. xdata unsigned char time_secs, time_mins ;
  6. void main(void)
  7. {
  8.   time_secs = RTC_chip.seconds ;
  9.   time_mins = RTC_chip.minutes;
  10. }
Linker Input File To Locate RTC_chip structure over real RTC Registers is:
  1. l51 main.obj,rtcbytes.obj XDATA(?XD?RTCBYTES(0h))

Pointers To Structures

Pointers can be used to access structures, just as with simple data items. Here is an example:
  1. /* Define pointer to structure */
  2. struct SENSOR_DESC *sensor_database ;
  3. /* Use Pointer To Access Structure Elements */
  4. sensor_database->gain = 0x30 ;
  5. sensor_database->offset = 0x50 ;
  6. sensor_database->temp_coeff = 0x60 ;
  7. sensor_database->span = 0xC4 ;
  8. sensor_database->amp_gain = 0x21 ;
Note that the '*' which normally indicates a pointer has been replaced by appending '->' to the pointer name. Thus '*name' and 'name->' are equivalent.

Passing Structure Pointers To Functions

A common use for structure pointers is to allow them to be passed to functions without huge amounts of parameter passing; a typical structure might contain 20 data bytes and to pass this to a function would require 20 parameters to either be pushed onto the stack or an abnormally large parameter passing area. By using a pointer to the structure, only the two or three bytes that constitute the pointer need be passed. This approach is recommended for C51 as the overhead of passing whole structures can tie the poor old 8051 CPU in knots!

This would be achieved by:
  1. struct SENSOR_DESC *sensor_database ;
  2. sensor_database->gain = 0x30 ;
  3. sensor_database->offset = 0x50 ;
  4. sensor_database->temp_coeff = 0x60 ;
  5. sensor_database->span = 0xC4 ;
  6. sensor_database->amp_gain = 0x21 ;
  7. test_function(*struct_pointer) ;
  8. test_function(struct SENSOR_DESC *received_struct_pointer)
  9. {
  10.   // Write directly into the structure
  11.   received_struct_pointer->gain = 0x20 ;
  12.   received_struct_pointer->temp_coef = 0x40 ;
  13. }
Advanced Note: Using a structure pointer will cause the called function to operate directly on the structure rather than on a copy made during the parameter passing process.

Structure Pointers To Absolute Addresses

It is sometimes necessary to place a structure at an absolute address. This might occur if, for example, a memory-mapped real time clock chip is to be handled as a structure. An alternative approach to that given earlier is to address the clock chip via a structure pointer.

The important difference is that in this case no memory is reserved for the structure - only an "image" of it appears to be at the address.

The template in this instance might be:
  1. /* Define Real Time Clock Structure */
  2. struct RTC
  3. {
  4.     char seconds ;
  5.     char mins ;
  6.     char hours ;
  7.     char days ;
  8. } ;
  10. /* Create A Pointer To Structure */
  11. struct RTC xdata *rtc_ptr ;  // 'xdata' tells C51 that this
  12.                              //is a memory-mapped device.
  13. void main(void)
  14. {
  15.     rtc_ptr = (void xdata *) 0x8000 ;  // Move structure
  16.                             // pointer to address of real-time
  17.                             // clock at 0x8000 in xdata
  18.     rtc_ptr->seconds = 0 ;  // Operate on elements
  19.     rtc_ptr->mins = 0x01 ;
  20. }
This general technique can be used in any situation where a pointer-addressed structure needs to be placed over a specific IO device. However it is the user's responsibility to make sure that the address given is not likely to be allocated by the linker as general variable RAM!

To summarize, the procedure is:
  1. Define template
  2. Declare structure pointer as normal
  3. At run time, force pointer to required absolute address in the normal way.


Unions allow you to define different datatype references for the same physical address. This way you can address a 32-bit word as a "long" OR as 2 different "ints" OR as an array of 4 bytes.

A union is similar in concept to a structure except that rather than creating sequential locations to represent each of the items in the template, it places each item at the same address. A union specifying 4 bytes may still only occupy a single byte. A union may consist of a combination of longs, char and ints all based at the same physical address.

The the number of bytes of RAM used by a union is simply determined by the size of the largest element, so:
  1. union test
  2. {
  3.   char x ;
  4.   int y ;
  5.   char a[3] ;
  6.   long z ;
  7. } ;
requires 4 bytes, this being the size of a long. The physical location of each element is the base address plus the following offsets:
0bytehigh bytea[0]highest byte
+1 low bytea[1]mid byte
+2  a[2]mid byte
+3  a[3]lowest byte

In embedded C the commonest use of a union is to allow fast access to individual bytes of longs or ints. These might be 16 or 32 bit real time counters, as in this example:
  1. /* Declare Union */
  2. union clock
  3. {
  4.     long real_time_count ;     // Reserve four byte
  5.     int real_time_words[2] ;   // Reserve four bytes as
  6.                                // int array
  7.     char real_time_bytes[4] ;  // Reserve four bytes as
  8.                                // char array
  9. } ;
  10. /* Real Time Interrupt */
  11. void timer0_int(void) interrupt 1 using 1
  12. {
  13.     clock.real_time_count++ ;       // Increment clock
  15.     if(clock.real_time_words[1] == 0x8000)
  16.     {    // Check/compare lower word only
  17.     /* Do something! */
  18.     }
  19.     if(clock.real_time_bytes[3] == 0x80)
  20.     {    // Check/compare most significant byte only
  22.     /* Do something! */
  23.     }
  25. }

Generic Pointers

C51 offers two basic types of pointer, the spaced (memory-specific) and the generic.

As has been mentioned, the 8051 has many physically separate memory spaces, each addressed by special assembler instructions. Such characteristics are not peculiar to the 8051 - for example, the 8086 has data instructions which operate on a 16 bit (within segment) and a 20 bit basis.

For the sake of simplicity, and to hide the real structure of the 8051 from the programmer, C51 uses three byte pointers, rather than the single or two bytes that might be expected. The end result is that pointers can be used without regard to the actual location of the data.

For example:
  1. xdata char buffer[10] ;
  2. code char message[] = { "HELLO" } ;
  3. void main(void)
  4. {
  5. char *s ;
  6. char *d ;
  8.     s = message ;
  9.     d = buffer ;
  10.     while(*s != '\0')
  11.     {
  12.         *d++ = *s++ ;
  13.     }
  14. }
Yields the following code:
  1.     RSEG  ?XD?T1
  2. buffer:            DS  10
  3.     RSEG  ?CO?T1
  4. message:
  5.     DB  'H' ,'E' ,'L' ,'L' ,'O' ,000H
  6. ;
  7. ;
  8. ; xdata char buffer[10] ;
  9. ; code char message[] = { "HELLO" } ;
  10. ;
  11. ;    void main(void) {
  12.     RSEG  ?PR?main?T1
  13.     USING    0
  14. main:
  15.             ; SOURCE LINE # 6
  16. ;
  17. ;       char *s ;
  18. ;       char *d ;
  19. ;   
  20. ;       s = message ;
  21.             ; SOURCE LINE # 11
  22.     MOV      s?02,#05H
  23.     MOV      s?02+01H,#HIGH message
  24.     MOV      s?02+02H,#LOW message
  25. ;       d = buffer ;
  26.             ; SOURCE LINE # 12
  27.     MOV      d?02,#02H
  28.     MOV      d?02+01H,#HIGH buffer
  29.     MOV      d?02+02H,#LOW buffer
  30. ?C0001:
  31. ;
  32. ;       while(*s != '\0') {
  33.             ; SOURCE LINE # 14
  34.     MOV      R3,s?02
  35.     MOV      R2,s?02+01H
  36.     MOV      R1,s?02+02H
  37.     LCALL    ?C_CLDPTR
  38.     JZ       ?C0003
  39. ;          *d++ = *s++ ;
  40.             ; SOURCE LINE # 15
  41.     INC      s?02+02H
  42.     MOV      A,s?02+02H
  43.     JNZ      ?C0004
  44.     INC      s?02+01H
  45. ?C0004:
  46.     DEC      A
  47.     MOV      R1,A
  48.     LCALL    ?C_CLDPTR
  49.     MOV      R7,A
  50.     MOV      R3,d?02
  51.     INC      d?02+02H
  52.     MOV      A,d?02+02H
  53.     MOV      R2,d?02+01H
  54.     JNZ      ?C0005
  55.     INC      d?02+01H
  56. ?C0005:
  57.     DEC      A
  58.     MOV      R1,A
  59.     MOV      A,R7
  60.     LCALL    ?C_CSTPTR
  61. ;          }
  62.             ; SOURCE LINE # 16
  63.     SJMP     ?C0001
  64. ;       }
  65.             ; SOURCE LINE # 17
  66. ?C0003:
  67.     RET      
  68. ; END OF main
  69.     END
As can be seen, the pointers '*s' and '*d' are composed of three bytes, not two as might be expected. In making *s point at the message in the code space an '05' is loaded into s ahead of the actual address to be pointed at. In the case of *d '02' is loaded. These additional bytes are how C51 knows which assembler addressing mode to use. The library function C_CLDPTR checks the value of the first byte and loads the data, using the addressing instructions appropriate to the memory space being used.

This means that every access via a generic pointer requires this library function to be called. The memory space codes used by C51 are:
  • CODE - 05
  • XDATA - 02
  • PDATA - 03
  • DATA - 05
  • IDATA - 01

Spaced Pointers In C51

Considerable run time savings are possible by using spaced pointers. By restricting a pointer to only being able to point into one of the 8051's memory spaces, the need for the memory space "code" byte is eliminated, along with the library routines needed to interpret it.

A spaced pointer is created by:
  1. char xdata *ext_ptr ;
to produce an uncommitted pointer into the XDATA space or
  1. char code *const_ptr ;
which gives a pointer solely into the CODE space. Note that in both cases the pointers themselves are located in the memory space given by the current memory model. A pointer to xdata which is to be itself located in PDATA would be declared as:
  1. pdata char     xdata     *ext_ptr ;
pdatachar  = location of pointer, xdata = memory space pointed to.
In this example strings are always copied from the CODE area into an XDATA buffer. By customizing the library function "strcpy()" to use a CODE source pointer and a XDATA destination pointer, the runtime for the string copy was reduced by 50%. The new strcpy has been named strcpy_x_c().

The function prototype is:
  1. extern char xdata *strcpy(char xdata*,char code *) ;
Here is the code produced by the spaced pointer strcpy():
  1. ; char xdata *strcpy_x_c(char xdata *s1, char code *s2) {
  2. _strcpy_x_c:
  3. MOV s2?10,R4
  4. MOV s2?10+01H,R5
  5. ;__ Variable 's1?10' assigned to Register 'R6/R7' __
  6. ; unsigned char i = 0;
  7. ;__ Variable 'i?11' assigned to Register 'R1' __
  8. CLR A
  9. MOV R1,A
  10. ?C0004:
  11. ;
  12. ; while ((s1[i++] = *s2++) != 0);
  13. INC s2?10+01H
  14. MOV A,s2?10+01H
  15. MOV R4,s2?10
  16. JNZ ?C0008
  17. INC s2?10
  18. ?C0008:
  19. DEC A
  20. MOV DPL,A
  21. MOV DPH,R4
  22. CLR A
  23. MOVC A,@A+DPTR
  24. MOV R5,A
  25. MOV R4,AR1
  26. INC R1
  27. MOV A,R7
  28. ADD A,R4
  29. MOV DPL,A
  30. CLR A
  31. ADDC A,R6
  32. MOV DPH,A
  33. MOV A,R5
  34. MOVX @DPTR,A
  35. JNZ ?C0004
  36. ?C0005:
  37. ; return (s1);
  38. ; }
  39. ?C0006:
  40. END
Notice that no library functions are used to determine which memory spaces are intended. The function prototype tells C51 only to look in code for the string and xdata for the RAM buffer.

NOTE: This is an article taken from ES Academy who are well known for their renowned product FLASH MAGIC.

Twitter Delicious Facebook Digg Stumbleupon Favorites More

Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Colgate Coupons