ARDUINO "Hack pinMode"


ARDUINO “แกะฟังก์ชัน pinMode”

ประจิน พลังสันติกุล


                เกิดอะไรขึ้นเมื่อเราเรียกใช้งานคำสั่ง pinMode() ก่อนอื่นเรามาดูฟังก์ชัน pinMode() กันก่อนครับ คำสั่ง pinMode จะอยู่ในโฟลเดอร์ “C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino” ไฟล์ wiring_digital.c

void pinMode(uint8_t pin, uint8_t mode)
{
                uint8_t bit = digitalPinToBitMask(pin);
                uint8_t port = digitalPinToPort(pin);
                volatile uint8_t *reg, *out;

                if (port == NOT_A_PIN) return;

                // JWS: can I let the optimizer do this?
                reg = portModeRegister(port);
                out = portOutputRegister(port);

                if (mode == INPUT) {
                                uint8_t oldSREG = SREG;
                                cli();
                                *reg &= ~bit;
                                *out &= ~bit;
                                SREG = oldSREG;
                } else if (mode == INPUT_PULLUP) {              
                                uint8_t oldSREG = SREG;
                                cli();
                                *reg &= ~bit;
                                *out |= bit;
                                SREG = oldSREG;
                } else {
                                uint8_t oldSREG = SREG;
                                cli();
                                *reg |= bit;
                                SREG = oldSREG;
                }
}

** อ้างอิงกับบอร์ด ARDUINO UNO         


                                       
เมื่อเราเรียกใช้งานฟังก์ชัน pinMode(pin, mode) ดังนี้



void setup()

{

    pinMode(13, OUTPUT);

}



สิ่งที่เกิดขึ้นคือ

ค่า 13                     จะถูกกำหนดไปที่พารามิเตอร์(อาร์กิวเมนต์) pin

OUTPUT               จะถูกกำหนดไปที่พารามิเตอร์(อาร์กิวเมนต์) mode



และเข้าสู่การทำงานของฟังก์ชัน pinMode() โดยมีลำดับขั้นตอนการทำงานดังนี้



เรียกใช้งานฟังก์ชัน digitalPinToBitMask()

bit = digitalPinToBitMask(13);     ผลที่เกิดขึ้นคือ

bit = _BV(5);

bit = (1<<(5));



เรียกใช้งานฟังก์ชัน digitalPinToPort(pin)

port = digitalPinToPort(13);         ผลที่เกิดขึ้นคือ

port = PB;



สรุปแล้ว 2 คำสั่งฟังก์ชัน ที่ผ่านมาคือ PB5 ครับ ซึ่งก็คือขาที่ 19 ของ ATmega328P



ส่วนคำสั่งนี้จะถูกข้ามไปครับ if (port == NOT_A_PIN) return;

เพราะ port ของเราเท่ากับ PB



เรียกใช้งานฟังก์ชัน reg = portModeRegister(port);

reg = portModeRegister(PB);     ผลที่เกิดขึ้น

reg = (uint16_t) &DDRB;              

*** ถ้าได้ศึกษา AVR จะทราบดีว่า DDRB เป็นรีจิสเตอร์ที่ใช้กำหนดทิศทางการทำงานของขาพอร์ต ว่าจะให้เป็นอินพุต (กำหนดค่า 0) หรือเป็นเอาต์พุต (กำหนดค่า 1) ของพอร์ต PORTB



เรียกใช้งานฟังก์ชัน out = portOutputRegister(port);

out = portOutputRegister(PB);  ผลที่เกิดขึ้น

out = (uint16_t) &PORTB;

*** PORTB เป็นรีจิสเตอร์ที่ใช้ในการอินพุตหรือเอาตพุต (รีจิสเตอร์ตัวนี้มีผลเกี่ยวข้องกับรีจิสเตอร์อีก 1 ตัว ไม่ขอกล่าวในที่นี้)



เนื่องจากเรากำหนดให้ mode เป็น OUTPUT คำสั่งที่ทำงานต่อคือ



uint8_t oldSREG = SREG;               // เก็บค่า SREG ไว้

cli();                                                       // ปิดการทำงานของอินเตอรรัปต์ทั้งหมด

*reg |= bit;                                          // DDRB |= (1<<(5));

*** เรารู้มาแล้วว่า *reg ชี้ไปที่ DDRB จากนั้นกำหนดค่า bit ซึ่งเท่ากับ (1<<(5)) ด้วยโอเปอร์เรเตอร์ |= (OR compound assignment) ส่งผลให้รีจิสเตอร์ DDRB บิตที่ 5 เป็น ‘1’ หรือเอาต์พุต โดยไม่ไปยุ่งกับบิตอื่น ๆ

SREG = oldSREG;                              // คืนค่า SREG กลับ

ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

สร้างต้นคริสต์มาสด้วย JAVA

ฟังก์ชัน SerialEvent กับ Arduino

การใช้งาน PIC18Fxxxx กับ MPLAB X + XC8 ด้วย Peripheral Libraries (PLIBS)