Group Blog
 
<<
มีนาคม 2554
 12345
6789101112
13141516171819
20212223242526
2728293031 
 
21 มีนาคม 2554
 
All Blogs
 

structure & union (Basic Programming)

structure และ union ดูเหมือนจะเป็นเรื่องใกล้ตัวของโปรแกรมเมอร์ทั่วไป
แต่จะมีสักกี่คนที่จะใช้สิ่งนี้ในการเขียนโปรแกรมของเขา การไม่ใช้หมายถึง
เขาไม่เห็นประโยชน์ของมัน ใช้ไม่เป็น หรืออะไรกันแน่ อันนี้ตอบยาก เพราะต่างคนย่อมต่างกัน

ส่วนตัวผมเขียนโปรแกรมหลากหลายรูปแบบ ไม่ว่าจะเป็นบนคอมพิวเตอร์
หรือบนไมโครคอนโทรลเลอร์ แนวการเขียนก็จะไม่ค่อยเหมือนชาวบ้าน
เท่าไร่ แต่ก็ยังคงความเป็นมาตรฐานของการเขียนโปรแกรมเอาไว้
(แน่ล่ะสิ ไม่คงมาตรฐานไว้ก็คอมไพล์ไม่ผ่านสินะ)

บทความนี้จะแนะนำการใช้ตัวแปรแบบ structure ไปพร้อมๆ กับการใช้ union
สองตัวนี้ไม่ค่อยมีประโยชน์กับการเขียนโปรแกรมแบบขอไปที หรือใช้เสร็จๆไป
เพราะดูเหมือนเป็นเรื่องเสีจยเวลาโดยใช่เหตุ (สำหรับโปรแกรมเล็กๆ) แต่จะมี
ประโยชน์อย่างมากในการเขียนโปรแกรมอย่างเป็นระบบ การวางโครงสร้างของ
โปรแกรม การประหยัดหน่วยความจำ การเพิ่มความเร็วการประมวลผล รวมไปถึง
ความง่ายของการเขียนโปรแกรม (ใช้โครงสร้างที่คนอื่นวางไว้ให้แล้ว)

เพื่อให้เห็นภาพกันแบบชัด ผมจะขอยกตัวอย่างตัวแปรแบบโครงสร้างขนาด 8-bit
มีรูปร่างหน้าตาแบบนี้



อย่างที่ทราบกัน ตัวแปรแบบ 8-bit ก็คือตัวแปรขนาด 1 byte มาทบทวนกันหน่อย


1 byte = 8 bits
4 bits = 1 nibble
2 nibbles = 1 byte = 8bits
4 bits lower = low-nibble
4 bits higher = high-nibble


เขียนให้ งง เข้าไว้ แต่ความสัมพันธ์และนิยามมันเป็นแบบนั้นจริงๆ และด้วย
ความสัมพันดังกล่าว ชัดเจนว่า คำว่า "byte" มันมีทั้ง "nibble" และ "bits"
ประกอบอยู่เป็นอันหนึ่งอันเดียวกัน ผมก็สามารถจะออกแบบโครงสร้างของ
ตัวแปรตัวนี้ได้ ส่วนคำว่า "union" ก็หมายถึงอะไรสองอย่างขึ้นไปมาไว้ในกล่อง
ใบเดียวกันนั่นเอง ในที่นี้คือนำ nibble กับ Bits ไปไว้ในกล่อง Byte นั่นเอง
สมมุตติว่าผมอ้างถึงบิตที่ 4 (BIT4) ของ Byte นั่นคือการอ้างถึง บิทต่ำสุด
ของ high-nibble (Hi) นั่นเอง อย่าเพิ่ง งง ครับ เดี๋ยวค่อยมาดูตัวอย่างกัน

จากโครงสร้างด้านบน ชื่อของโครงสร้างหรือ structure คือ VAR8 นี่คือกล่องใบใหญ่สุด
ในกล่องใบนี้มีกล่อง อีกใบชื่อ Data ในกล่อง Data ยังมีกล่องใบเล็กๆ อีก 3 ใบคือ
Byte ใน Byte มี Nibble และ Bits มองลึกลงไปในแต่ละกล่อง จะเห็นว่ากล่อง Nibble
มีอีกสองกล่อง คือ Lo และ Hi และที่กล่อง Bits มีของชิ้นเล็กๆ อีก 8 ชิ้น คือ BIT0 ถึง BIT7


แต่อย่าลืมนะครับว่ากล่อง Byte, Nibble และ Bits เกิดจากการ union การกระทำอะไร
บางอย่างกับส่วนใดส่วนหนึ่งจะส่งผลโดยตรงกับสิ่งที่อยู่ในกล่องใบอื่นด้วย มาดูตัวอย่างกัน



บรรทัดที่ 1 คือการประกาศขอใช้ตัวแปรชนิด VAR8 ชื่อ MyVar
บรรทัดที่ 2 ทำให้ Byte มีค่า 15 จะส่งผลให้ Lo มีค่าเม่ากับ 15 และ BIT0 ถึง BIT3 มีค่าเป็น 1 ทุกบิต (ตอนนี้ค่าสะสมของ Byte มีค่าเป็น 0x0F)
บรรทัดที่ 3 ทำให้ BIT7 มีค่าเป็น 1 จะส่งผลให้ บิตที่ 8 ของ Byte เป็น 1 และ บิตที่ 4 ของ Hi มีค่าเป็น 1 ด้วย (ตอนนี้ค่าสะสมของ Byte มีค่าเป็น 0x8F)
บรรทัดที่ 4 ทำให้ Hi มีค่า 15 จะส่งผลให้  BIT4 ถึง BIT7 เป็น 1 และบิตที่ 4-7 ของ Byte เป็น 1 ด้วย (ตอนนี้ค่าสะสมของ Byte มีค่าเป็น 0xFF)
บรรทัดที่ 5 ทำให้ Lo มีค่า เป็น 0  จะส่งผลให้  BIT4 ถึง BIT7 เป็น 0 และบิตที่ 4-7 ของ Byte เป็น 0 ด้วย (ตอนนี้ค่าสะสมของ Byte มีค่าเป็น 0xF0)



เห็นหรือยังครับว่า การเปลี่ยนข้อมูลส่วนใดส่วนหนึ่ง จะส่งผลกับข้อมูลในส่วนอื่นๆ ด้วย

การทำความเข้าใจอาจจะลำบากหากเรื่องนี้ไม่เคยผ่านหูผ่านตา ควรอ่านไปเขียนไป เพื่อเพิ่มความเข้าใจสิ่งที่ผมอธิบาย

แล้วจะมีประโยชน์อะไร? ทำไมไม่ประกาศเป็น char หรือ unsigned char ไปเลยล่ะ 8 bits เหมือนกัน ใช้งานง่ายกว่าด้วย

นั่นน่ะสิ.... เพื่อให้เข้าใจมากขึ้น ขอยกตัวอย่างในโลกของไมโครคอนโทรลเลอร์ก็แล้วกัน
ในโลกของไมโครคอนโทรลเลอร์ คือการเขียน/อ่านค่าต่างๆ กับรีจิสเตอร์ ซึ่งรีจิสเตอร์
ยกตัวอย่างเช่น รีจิสเตอร์ที่ทำหน้าที่ควบคุมการทำงานของ Timer/Counter ในไมโครคอน
โทรลเลอร์แบบ 8-bit รีจิสเตอร์ก็จะมีขนาด 8-bit หรือ 1 byte ในแต่ละ bit ถูกใช้ในการ
กำหนดการทำงานรูปแบบต่างๆ ยกตัวอย่างเช่น บิค 0-3 ใช้กำหนดการทำงานของ Pre-scaler
บิตที่ 7 เปิดปิดการทำงานของ  Timer/Counter การเขียนโปรแกรมก็เพียงแค่อ้างโดยการใช้
REGISTER.DATA.PRESCALER หรือ REGISTER.DATA.BIT7 เพื่ออ้างถึง Pre-scaler และ
เปิดปิดการทำงานของ  Timer/Counter โดยไม่ต้องทราบเลยว่ามันอยู่บิตไหน และไม่ต้องกลัว
ว่าจะเป็นเปลี่ยนข้อมูลในส่วนที่ไม่ได้ตั้งใจ ที่สำคัญช่วยให้เขียนโปรแกรมได้โดยไม่ต้องเปิด
datasheet เพียงแค่จำชื่อของสิ่งที่สนใจก็เพียงพอ




typedef struct{
union{
BYTE Byte;
struct{
BYTE Lo : 4;
BYTE Hi : 4;
}Nibble;
struct{
BYTE BIT0 : 1;
BYTE BIT1 : 1;
BYTE BIT2 : 1;
BYTE BIT3 : 1;
BYTE BIT4 : 1;
BYTE BIT5 : 1;
BYTE BIT6 : 1;
BYTE BIT7 : 1;
}Bits;
}Data;
}VAR8;

VAR8 MyVar;

void main(void){
MyVar.Data.Byte = 15;
MyVar.Data.Bits.BIT7 = 1;
MyVar.Data.Nibble.Hi = 15;
MyVar.Data.Nibble.Lo = 0;
}





By: Santi @ //www.shadowwares.com/forum




 

Create Date : 21 มีนาคม 2554
0 comments
Last Update : 21 มีนาคม 2554 11:09:34 น.
Counter : 1578 Pageviews.


TheInsight
Location :


[ดู Profile ทั้งหมด]

ฝากข้อความหลังไมค์
Rss Feed
Smember
ผู้ติดตามบล็อก : 3 คน [?]




Links
 

 Pantip.com | PantipMarket.com | Pantown.com | © 2004 BlogGang.com allrights reserved.