How to Achieve Byte Endian Conversion in Embedded Programming?

Recently, I encountered a problem with byte endian conversion in a protocol, so I lazily went online to check it out and came across a similar issue, learning a new term called butterfly swapping.

The Problem Is As Follows

The protocol requires that the low byte is on the left and the high byte is on the right, and each byte needs to be converted by swapping its high and low bits. For example,<span>11010001</span>, after swapping bits according to<span>0->7, 1->6, 2->5, 3->4</span>, it becomes<span>10001011</span>.

Here, knowledge of bit manipulation is required. Let’s take an 8-bit data endian conversion as an example:

#include <stdio.h>

unsigned char highAndLowShiftHEX(unsigned char data);
void printBin(int n);

int main () {

    highAndLowShiftHEX(209);
    return 0;
}

unsigned char highAndLowShiftHEX(unsigned char data)  
{  
   unsigned char i;  
   unsigned char tmp=0x00;  
   for(i=0;i<8;i++)  
   {  
       tmp=((data>>i)&0x01)|tmp;  
       //printBin(tmp);
       if(i<7)  
           tmp=tmp<<1;  
   }  
   printf("\nafter shift data:");  
   printBin(tmp);
   return tmp;    
}

// Since binary is intuitive, I wrote a function to print binary
void printBin(int n) {
    int len = sizeof(n)*8; // total bits.
    int i;
    if(i == 0) {
         printf("0");
         return;
    }
    for(i = len-1; i >= 0; i --) // skip leading 0s.
    {
        if(n&(1<<i)) break;
    }

    for(;i>=0; i --)
        printf("%d", (n&(1<<i)) != 0);
}

If you are familiar with bit manipulation, the above code is relatively simple to implement. In embedded development, this kind of problem is usually solved using the butterfly swapping method and lookup table method.

Higher Level Implementation?

The lookup table method involves storing some values in memory and looking them up when needed, but this method consumes additional storage space.
So here we mainly introduce the butterfly swapping method, taking 8-bit data conversion as an example.
  • Assuming the original sequence is:1 2 3 4 5 6 7 8
  • The target sequence is:8 7 6 5 4 3 2 1
The flowchart is as follows:
How to Achieve Byte Endian Conversion in Embedded Programming?

This completes the entire bitwise reverse conversion. Similarly, taking<span>11010001</span> as an example, here is the specific implementation code:

#include <stdio.h>

unsigned char highAndLowShiftHEX(unsigned char );
void printBin(int );

int main () {

    highAndLowShiftHEX(209);
    return 0;
}

unsigned char highAndLowShiftHEX(unsigned char data)  
{  
   data=(data<<4)|(data>>4);  
   data=((data<<2)&0xcc)|((data>>2)&0x33);  
   data=((data<<1)&0xaa)|((data>>1)&0x55);  
   printf("  after shift data=%x \n",data);  
   printBin(data);
   return data;  
}

// Since binary is intuitive, I wrote a function to print binary
void printBin(int n) {
    int len = sizeof(n)*8; // total bits.
    int i;
    if(i == 0) {
         printf("0");
         return;
    }
    for(i = len-1; i >= 0; i --) // skip leading 0s.
    {
        if(n&(1<<i)) break;
    }

    for(;i>=0; i --)
        printf("%d", (n&(1<<i)) != 0);
}

Exchanging the high and low bits of a byte is not a very common problem. When encountering this issue, careful analysis is required, along with a proficient grasp of bit manipulation in C language to effectively solve such problems.

Extension

Now we will extend this to high and low bit conversion of 16-bit half-word data.

The principle is the same as with 8 bits, using simple shifting methods to convert the high and low bits of the data. If you are familiar with bit manipulation, the code becomes relatively simple.

Below is the specific implementation of this idea.

#include <stdio.h>

void expandPrintBin(int val2);
unsigned short HighAndLowSwitchHEX(unsigned short data);

int main () {

    HighAndLowSwitchHEX(38491);
    return 0;
}

// Since binary is intuitive, I wrote an extended function to print binary
void expandPrintBin(int val2) {
    int i,k;
    unsigned char *p = (unsigned char*)&val2 + 3; // from low to high, low-end byte computer
    for( k = 0; k <= 3; k++) {
        int val2 = *(p-k);
        for (i = 7; i >= 0; i--) {
            if(val2 & (1 << i))
                printf("1");
            else
                printf("0");
        }
        printf(" ");
    }
}

unsigned short HighAndLowSwitchHEX(unsigned short data) {
    unsigned char i = 0;
    unsigned short temp = 0x0000;

    for(i = 0; i < 16; i++) {
        temp = ((data >> i) & 0x0001) | temp;
        if(i < 15) {
            temp = temp << 1;
        }
    }
    printf("temp:%x\n\n",temp);
    expandPrintBin(temp);
    return temp;
}
Similarly, the so-called butterfly swapping method, I referenced the byte swapping method example, we can calculate:
  • Assuming the original sequence is:<span>a b c d e f g h i j k l m n o p</span>
  • The target sequence is:<span>p o n m l k j i h g f e d c b a</span>
The flowchart is as follows:
How to Achieve Byte Endian Conversion in Embedded Programming?

This completes the entire bitwise reverse conversion, completing the algorithm extension. Taking<span>1001011001011011</span> as an example, here is the specific implementation code:

#include <stdio.h>

unsigned short highAndLowShiftHEX(unsigned short data);
void expandPrintBin(int val2);

int main () {

    highAndLowShiftHEX(38491);
    return 0;
}

unsigned short highAndLowShiftHEX(unsigned short data) {
    data = (data << 8) | (data >> 8);   //0101101110010110
    data = ((data << 4) & 0xF0FF) | ((data >> 4) & 0xFF0F); //1011010101101001
    data = ((data << 2) & 0xCCCC) | ((data >> 2) & 0x3333); //1110010110010110
    data = ((data << 1) & 0xAAAA) | ((data >>1 ) & 0x5555); //1101101001101001
    printf("  after shift data=%x \n",data);  
    expandPrintBin(data);
    return data;  
}

// Since binary is intuitive, I wrote an extended function to print binary
void expandPrintBin(int val2) {
    int i,k;
    unsigned char *p = (unsigned char*)&val2 + 3; // from low to high, low-end byte computer
    for( k = 0; k <= 3; k++) {
        int val2 = *(p-k);
        for (i = 7; i >= 0; i--) {
            if(val2 & (1 << i))
                printf("1");
            else
                printf("0");
        }
        printf(" ");
    }
}
For such bit swapping problems, they are frequently encountered in embedded development. It is important to be familiar with bit manipulation and debugging methods. Proficient use of C language shifting operations can quickly solve such problems.

Conclusion

The key to the above problem is the flexible use of bit manipulation. Additionally, two functions for printing binary were written for convenience, and the code can be directly used. Debugging is not easy, so likes, views, and shares are appreciated. See you next time!

Author: Li Xiaoyao, Source: Technology Makes Dreams Greater

This article is reprinted with permission from the “Technology Makes Dreams Greater” public account. Reprinting is for learning reference only and does not represent this account’s agreement with its views. This account is not responsible for any infringement of its content, text, or images.

END
Click 👇 the name card to follow me
Previous Recommendations
1. Why Are Design Patterns Rarely Used in Embedded Development?
2. Several Very Useful Macro Techniques in C Language and Embedded Systems
3. Sharing Several Practical Techniques in Embedded C

Leave a Comment