วิธีการเรียนรู้ที่เข้าใจง่าย คือ การลงมือสร้างตัวอย่างขึ้นเพื่อให้เกิดความเข้าใจอย่างถ่องแท้
การเรียนรู้ที่ง่ายที่สุดก็เริ่มจาก LED โดยจะต่อ LED 8 ดวง เข้ากับขา I/O ให้ครบ 8bit คือ ต่อตั้งแต่ PINx0 - PINx7 ในบทความนี้ใช้ LED แบบแพ็ก 10 แต่ใช้เพียง 8 ดวงเท่านั้น และอย่าลืมต่อ R ค่า 220 หรือ 330 โอห์มพ่วงไว้สักนิดจะได้ช่วยปกป้องทั้ง IC และ LED
อุปกรณ์เรียนรู้การทำงานระดับบิต |
การต่ออุปกรณ์
- ต่อขา LED 1-8 เข้าขา PB0-7
- ต่อขาอีกข้าของ LED เข้ากับ R ค่า 330 โอห์ม และต่อลง GND
โปรแกรมคำสั่ง
- #define F_CPU 8000000L
- #include <avr/io.h>
- #include <util/delay.h>
- int main(void){
- int i = 0;
- DDRB = 0b11111111;
- PORTB = 0b00000000;
- while (1){
- for (i = 0; i<8; i++){
- PORTB |= (1<<i);
- _delay_ms(300);
- }
- PORTB = 0;
- }
- }
บรรทัดที่ 6 เริ่มกำหนดให้ i มีค่าตั้งแต่ 0 เพื่อทำงานกับบิต 0
บรรทัดที่ 7 กำหนดให้ขา I/O ชุด B เป็นเอาท์พุททั้งหมด เพื่อเขียนคำสั่งออกไปยัง I/O
บรรทัดที่ 8 กำหนดให้ขา I/O เป็น 0 หรือกำหนดให้เป็น LOW เพื่อปิด LED ทุกตัว
บรรทัดที่ 10 คำสั่ง while (1) จะวนรอบไปเรื่อยๆ ไม่สิ้นสุดจนกว่าจะปิดเครื่อง
บรรทัดที่ 11 คำสั่ง for จะเริ่มตั้งแต่ 0 ไปจนถึง 7 ตามเงื่อนไข i < 8
บรรทัดที่ 12 กำหนดให้ PORTB เป็น 1 เริ่มจากบิต 0 ไปเรื่อยๆ จนถึงบิตที่ 7
บรรทัดที่ 13 ให้หยุดรอ 300ms
บรรทัดที่ 15 กำหนดให้ PORTB ทุกขามีค่าเป็น 0 หรือ LOW แล้วกลับไปวนรอบใหม่
*** ดูจากคลิปวีดีโอแล้วจะเห็นว่าจังหวะสุดท้ายที่ LED ดวงที่ 8 ดับลง ดวงที่ 1 ยังติดค้างอยู่ ในโปรแกรมจึงต้องเพิ่มคำสั่ง _delay_ms(300) ไว้บรรทัดล่างของ PORTB = 0;
อธิบายเพิ่มเติม
PORTB |= (1<<i);
คำสั่งในบรรทัดที่ 12 จะเป็นตัวกำหนดค่าให้กับขาแต่ละขาของ PORTB โดยจะเริ่มจาก 0 ตามค่า i โดยจะจำลองสถานการณ์ของ PORTB ดังนี้
เริ่มต้น PORTB = 0b00000000
เมื่อค่า i = 0 บรรทัดที่ 12 จะเป็น
PORTB |= (1<<0); ให้ PORTB ทำบิตออร์กับ 0b00000001 โดยจะเขียนใหม่เป็น
PORTB = PORTB | 0b00000001; เขียนแทนค่า PORTB อีกครั้งหนึ่งเป็น
PORTB = 0b00000000
|
0b00000001
PORTB = 0b00000001
ดังนั้นคำสั่ง PORTB |= (1<<0) จึงเป็นการสั่งให้บิต 0 มีค่าเป็น 1 หรือ HIGH ส่งผลให้ไฟ LED ติดสว่าง
เมื่อค่า i = 1 บรรทัด 12 จะเป็น
PORTB |= (1<<1); กำหนดให้ PORTB บิตออร์กับ 0b00000010 โดยเขียนใหม่เป็น
PORTB = PORTB | 0b00000010; ตอนนี้ค่า PORTB เดิมเป็น 0b00000001 จึงเขียนได้ว่า
PORTB = 0b00000001
|
0b00000010
PORTB = 0b00000011
ถึงตอนนี้เมื่อ i มีค่าเป็น 1 ส่งผลให้ไฟ LED ติดสองดวง เพราะ บิต 0 และ บิต 1 ต่างก็เป็น HIGH ทั้งคู่
เมื่อ i = 7 บรรทัดที่ 12 จะเป็น
PORTB |= (1<<7); กำหนดให้ PORTB บิตออร์กับ 0b10000000 โดยเขียนใหม่เป็น
PORTB = PORTB | 0b10000000; ตอนนี้ค่า PORTB เป็น 0b01111111 จึงเขียนใหม่ได้ว่า
PORTB = 0b01111111
|
0b10000000
PORTB = 0b11111111
เมื่อ i = 7 บรรทัดที่ 12 จะเป็น
PORTB |= (1<<7); กำหนดให้ PORTB บิตออร์กับ 0b10000000 โดยเขียนใหม่เป็น
PORTB = PORTB | 0b10000000; ตอนนี้ค่า PORTB เป็น 0b01111111 จึงเขียนใหม่ได้ว่า
PORTB = 0b01111111
|
0b10000000
PORTB = 0b11111111
การทำงานจะวนไปเรื่อยๆ ถึงบิต 7 ไฟ LED จะติดสว่างทุกดวง และ i มีค่า เท่ากับ 8 โปรแกรมจึงไม่ทำงาน โดยจะออกจากลูป for ไปทำคำสั่ง
PORTB = 0;
คือสั่งให้ทุกขา I/O ของ PORTB เป็น 0 หรือ LOW เพื่อปิดไฟ LED ซึ่งการเขียนสามารถเขียนแบบอื่นได้ เช่น
PORTB = 0x00; หรือ
PORTB = 0b00000000;
ซึ่งทั้ง 3 แบบก็มีค่าเท่ากัน เมื่อ LED ดับหมดทุุุกดวงแล้วโปรแกรมก็จะเริ่มที่บรรทัด 12 ใหม่อีกครั้งหนึ่ง วนไปเรื่อยๆ ไม่รู้จบ
ตัวอย่างนี้เราจึงเห็นหลอด LED ติดสว่างจากหลอดที่ 1 ถึงหลอดที่ 8 (bit 0 ถึง bit 7) เมื่อติดครบแล้วก็เริ่มใหม่ ก่อนจะเริ่มใหม่ LED ทุกดวงจะดับก่อน
สุดท้ายเราสามารถเขียนโปรแกรมโดยใช้เลขฐานสิบหกเป็นค่าของ PORTB ได้เช่นกัน คือ
int main(void){
int i = 0;
DDRB = 0xFF;
while (1){
PORTB = 0x00;
for (i = 0; i<8; i++){
PORTB |= (1<<i);
_delay_ms(300);
}
_delay_ms(300);
}
}
สุดท้ายเราสามารถเขียนโปรแกรมโดยใช้เลขฐานสิบหกเป็นค่าของ PORTB ได้เช่นกัน คือ
int main(void){
int i = 0;
DDRB = 0xFF;
while (1){
PORTB = 0x00;
for (i = 0; i<8; i++){
PORTB |= (1<<i);
_delay_ms(300);
}
_delay_ms(300);
}
}
นี่เป็นเพียงการเริ่มต้น ต่อไปจะนำเรื่องอื่นๆ ที่เกี่ยวข้องกับ Bitwise Operator มานำเสนอต่อนะครับ... สวัสดีครับ
ไม่มีความคิดเห็น:
แสดงความคิดเห็น