MPLAB C18 Tutorial - How to change the bit order of a byte

Preface

I am not a C18 pro, nor am I a pro in C at all. What I have learned has been based on C18 and my needs to write more complex structured applications more easily than I could in assembly. I am not saying that C is better than Swordfish, or any of the other languages/compilers out there. I'm sure they all have their features and benefits. I do know however that C is widely accepted and supported and it doesn't hurt to learn a thing or two about the language.

With that said, my tutorials work albeit maybe not the most efficient solution. As I learn more I will update my tutorials to include fresher approaches and ideas. I'm always open to suggestions and will include valid input in my tutorials.

This first tutorial is very detailed at the moment but will change as I post other tutorials describing variable declarations, data types, templates, etc.

 

Also, please bare with me as I try to find a format that is appealing. I'm pretty new at this sort of thing, and digital-diy has put an amazing amount of support formatting tools at our disposal so I'm trying to get a feel for all of it.

- Hop

How to change the bit order of a byte using a simple loop in a function

I found it necessary to write a function to reverse a byte of data bit order when I found out that sampled data I received from a infrared remote control project was offering data in the reverse order that I needed. Reversing the bit order means that if you have a byte of data, it's bit ZERO should be bit SEVEN, bit ONE should be bit SIX, etc. In assembly, this is pretty easy to do since the bit shifted out goes into the carry flag and that carry flag can be shifted into another byte. Since we are dealing with C, not assembly, here is how it is done simply in that C environment.

The code that follows effectively reverses the bit order of a byte of data, and returns that result. The commented code is included and is there to allow for RS232 output showing the stages of the function one bit shift at a time. Below the code is a line-by-line description of what is happening.

If you are NOT using a RS232 structure to communicate with the chip via a serial connection, leave the commented lines as they are. If you ARE using a RS232 structure to communicate with the chip, these functions will output data to your RS232 terminal showing the variable changes through each iteration of the FOR loop. Of course, it is assumed that if you are using the aforementioned RS232 scheme, you have included the library usart.h as in #include .

Also, please note that this function, or any other you write in C18 requires a prototype. It's pretty simple. After your includes you declare a prototype that looks almost exactly like the function definition.

unsigned char bitorder_reverse(unsigned char data); // Notice the semicolon instead 
 // of the opening bracket

 

 

unsigned char bitorder_reverse(unsigned char data){
 unsigned char newdata=0;
 unsigned char x=0;
 for(x=0;x<=7;x++){
 //fprintf (_H_USART, "%02X ",newdata);
 //fprintf (_H_USART, "%02X\n\r",data);
 newdata<<=1;
 newdata|=(data&1);
 data>>=1;
 }
 //fprintf (_H_USART, "%02X ",newdata);
 //fprintf (_H_USART, "%02X\n\r",data);
 return newdata;
}

 

The first line is the function definition;

unsigned char bitorder_reverse(unsigned char data)

 

Here is where we define what type of data is to be returned and define what variables we will use with the data that is passed to the function when it is called. For this function we are manipulating an 8 bit (byte) value so we are using unsigned char for the data type definition. It is unsigned because we are working with positive values 0-255 or 0x00-0xFF in hexadecimal. Since the data we wish to pass to the function is also an unsigned byte value, we define that using unsigned char data which also declares variable 'data' which will contain that data. This declaration is much the same as doing it inside the function except it is assigned the argument data being passed to the function.

 

The next two lines are more variable declarations.

unsigned char newdata=0;
unsigned char x=0;

 

When this is done inside a function, the variable scope is restricted to the function. In standard C, memory is allocated for the local variables and then they are initialized. When the function exits, the memory is deallocated for the local variables. Whether or not that is the case with C18 is something I can't confirm.

 

Now we have our for loop so we can iterate through the bits of the byte of data.

for(x=0;x<=7;x++){

 

For loops in C are similar to some other languages. The loop has three parameters. The first is the initial value for the variable used in the loop. The second is the test condition to allow the loop to continue, and the third is how the variable is affected after every loop. In this case, x is used, starts at 0, continues until x is greater than 7, and increments by one each iteration. The code that runs in the loop is enclosed in brackets { }.

 

Inside the loop there are only three lines of code that do all the work on the data.

newdata<<=1;
newdata|=(data&1);
data>>=1;

 

The first line above shifts the data in newdata to the left by one bit, by pushing a zero on the end at the right and discarding the value of bit 7 (basically pushing off the edge so to speak). This sets up bit 0 to take the value we are shifting out of the data variable.

The next line puts the value of bit 0 of the data variable into bit 0 of the newdata variable using a bitwise OR operator by assignment |= which means the value of newdata is OR'd with the value of data and the result is stored in newdata. Since we don't want the whole value of data to be OR'd with the new data, a mask is used using the AND operator &, as in (data&1).

The last line shifts the value in data to the RIGHT by one bit with the same results as in the first line, but in the opposite direction.

Now the closing brackets are encountered, the loop iterates based on the conditions of the loop, and the process repeats until all the bits of the byte are processed.

return newdata;

 

Finally, the value is returned in reverse bit order.

 

NOTES:

I haven't found the need to do this on a larger scale, meaning with 2 byte words, etc. since the function could be used on multiple bytes individually. There are better ways to do this also, using a pointer to reference the passed variable. That is for another tutorial.

Hop

Forum Activity

Member Access