วันอังคารที่ 27 พฤษภาคม พ.ศ. 2557

Arduino : การเข้าถึงข้อมูลระดับบิตด้วย struct union

Standard
      พอดีมีโอกาสได้เขียน Arduino (รวมถึงภาษา C โดยทั่วไป) แล้วจะต้องจัดการข้อมูลในระดับบิต ซึ่งปกติก็ใช้การ shift bit แล้ว AND กับ 1 เพื่อดูว่าบิตในตำแหน่งที่สนใจเป็นค่าอะไร
(data >> BIT_INDEX) & 1 == ?

    จาก code ตัวอย่างข้อบนตัวแปร data แล้ว shift ไป BIT_INDEX ตัว จากนั้นนำข้อมูลที่ได้มา AND กับ 1 เพื่อให้ bit ที่ 7-1 (กำหนดให้นับ 8 ตัวคือ index ที่ 0 - 7) มีค่าเป็น 0  เช่น
0xA5 แล้วอยากดูว่า บิตที่ตำแหน่งที่ 3 มีค่าเป็นอะไร ตำแหน่งที่ 3 ต้อง shift ไปทางขวา 2 บิต 1010 0101 >> 2  = 0010 1001 จากนั้น AND ด้วย 1 เพื่อให้ค่าในตำแหน่งอื่นมีค่าเป็น 0 กรณีที่ต้องการนำค่าไปใส่ในตัวแปร 0010 1001 & 1 = 1 
     วิธีดังกล่าวข้างต้นเป็นวิธีที่มีการใช้กันโดยทั่วไป แต่ผมจะมาเสนออีกวิธีในการเข้าถึงข้อมูลแบบบิตด้วยการใช้ structure และ union ในภาษาซี
typedef union {
struct {
uint8_t bit_0: 1;
uint8_t bit_1: 1;
uint8_t bit_2: 1;
uint8_t bit_3: 1;
uint8_t bit_4: 1;
uint8_t bit_5: 1;
uint8_t bit_6: 1;
uint8_t bit_7: 1;
};
uint8_t byte_0;
}st_data;
view raw st_union.c hosted with ❤ by GitHub

จาก struct ข้างต้นเป็นการ union ของ data structure 2 ตัวด้วยกันคือ struct { bit_7...bit_0 }  และ uint8_t byte_0 ซึ่งสามารถเข้าถึงข้อมูลด้วย . หรือ -> ถ้าเป็น pointer เหมือน struct ทั่วไป

ตารางเทียบข้อมูลใน Memory
#include "stdint.h"
typedef union {
struct{
uint8_t bit_0: 1;
uint8_t bit_1: 1;
uint8_t bit_2: 1;
uint8_t bit_3: 1;
uint8_t bit_4: 1;
uint8_t bit_5: 1;
uint8_t bit_6: 1;
uint8_t bit_7: 1;
};
uint8_t byte_0;
}st_data;
void setup()
{
Serial.begin(9600);
st_data my_data;
my_data.byte_0 = 0xA5; //1010 0101
Serial.println("");Serial.println("Using union to access bit value");
Serial.print("byte = ");Serial.println(my_data.byte_0,HEX);
Serial.println("");
Serial.print("Bit 7 = ");Serial.println(my_data.bit_7);
Serial.print("Bit 6 = ");Serial.println(my_data.bit_6);
Serial.print("Bit 5 = ");Serial.println(my_data.bit_5);
Serial.print("Bit 4 = ");Serial.println(my_data.bit_4);
Serial.print("Bit 3 = ");Serial.println(my_data.bit_3);
Serial.print("Bit 2 = ");Serial.println(my_data.bit_2);
Serial.print("Bit 1 = ");Serial.println(my_data.bit_1);
Serial.print("Bit 0 = ");Serial.println(my_data.bit_0);
}
void loop()
{
}
#include "stdint.h"
typedef union {
struct{
uint8_t bit_0: 1;
uint8_t bit_1: 1;
uint8_t bit_2: 1;
uint8_t bit_3: 1;
uint8_t bit_4: 1;
uint8_t bit_5: 1;
uint8_t bit_6: 1;
uint8_t bit_7: 1;
};
uint8_t byte_0;
}st_data;
void main()
{
st_data mydata;
mydata.byte_0 = 0xA5;
printf("byte_0 = 0x%02X\r\n",mydata.byte_0);
printf("bit_7 = %d\r\n",mydata.bit_7);
printf("bit_6 = %d\r\n",mydata.bit_6);
printf("bit_5 = %d\r\n",mydata.bit_5);
printf("bit_4 = %d\r\n",mydata.bit_4);
printf("bit_3 = %d\r\n",mydata.bit_3);
printf("bit_2 = %d\r\n",mydata.bit_2);
printf("bit_1 = %d\r\n",mydata.bit_1);
printf("bit_0 = %d\r\n",mydata.bit_0);
}

source code ทดสอบว่าเราคิดถูก :)


ผลการรันโปรแกรม








Related Posts:

0 ความคิดเห็น:

แสดงความคิดเห็น