นี่ไม่ใช่รูปลักษณ์แปลก ๆ มันเป็นรหัส MCU ธรรมดาที่ดูเหมือนจริง
สิ่งที่คุณได้ที่นี่เป็นตัวอย่างของแนวคิดของการที่อุปกรณ์หน่วยความจำแมป โดยทั่วไปฮาร์ดแวร์ MCU มีที่ตั้งพิเศษในพื้นที่ที่อยู่ SRAM ของ MCU ที่กำหนดให้ ถ้าคุณเขียนไปยังที่อยู่เหล่านี้บิตไบต์ที่เขียนไปยังที่อยู่nควบคุมการทำงานของอุปกรณ์ต่อพ่วงเมตร
โดยทั่วไปหน่วยความจำของธนาคารบางแห่งจะมีสายเล็ก ๆ ที่ทำงานจากเซลล์ SRAM ไปยังฮาร์ดแวร์ หากคุณเขียน "1" ไปยังบิตนี้ในไบต์นั้นจะตั้งเซลล์ SRAM นี้เป็นลอจิคัลสูงซึ่งจะเปิดบางส่วนของฮาร์ดแวร์
หากคุณมองหาส่วนหัวของ MCU จะมีการแมปคำหลัก <-> ที่อยู่จำนวนมาก นี่คือวิธีที่สิ่งต่าง ๆ เช่นTCCR1B
ฯลฯ ... ได้รับการแก้ไขในเวลารวบรวม
กลไกการแมปหน่วยความจำนี้ถูกใช้อย่างกว้างขวางใน MCU ATmega MCU ใน Arduino นั้นใช้เช่นเดียวกับ PIC, ARM, MSP430, STM32 และ STM8 MCU ซีรีส์รวมถึง MCU จำนวนมากที่ฉันไม่คุ้นเคยในทันที
รหัสArduinoเป็นของแปลก ๆ ที่มีฟังก์ชั่นที่เข้าถึงการควบคุม MCU ลงทะเบียนทางอ้อม แม้ว่านี่จะดู "ดีกว่า" แต่ก็ช้ากว่ามากและใช้พื้นที่โปรแกรมมากขึ้น
ค่าคงที่ลึกลับนั้นถูกอธิบายไว้ในรายละเอียดที่ดีเยี่ยมในแผ่นข้อมูล ATmega328Pซึ่งคุณควรอ่านหากคุณสนใจที่จะทำอะไรมากกว่านี้แล้วสลับเป็นหมุดบน Arduino
เลือกข้อความที่ตัดตอนมาจากแผ่นข้อมูลที่ลิงค์ด้านบน:
ดังนั้นสำหรับตัวอย่างเช่นTIMSK1 |= (1 << TOIE1);
ชุดบิตในTOIE1
TIMSK1
นี่คือความสำเร็จโดยการขยับไบนารี 1 ( 0b00000001
) ไปทางซ้ายทีละTOIE1
บิตโดยมีTOIE1
การกำหนดไว้ในไฟล์ส่วนหัวเป็น 0 จากนั้นค่าบิต ORed จะเป็นค่าปัจจุบันของTIMSK1
ซึ่งตั้งค่าสูงหนึ่งบิตได้อย่างมีประสิทธิภาพ
ดูที่เอกสารสำหรับบิต 0 ของTIMSK1
เราจะเห็นว่ามันถูกอธิบายว่า
เมื่อบิตนี้ถูกเขียนไปยังหนึ่งและตั้งค่าสถานะ I ในการลงทะเบียนสถานะ (ขัดจังหวะเปิดใช้งานทั่วโลก) การขัดจังหวะ Timer / Counter1 ล้นเปิดใช้งาน เวกเตอร์ขัดจังหวะที่เกี่ยวข้อง (ดู” การขัดจังหวะ” ในหน้า 57) จะถูกดำเนินการเมื่อตั้งค่าสถานะ TOV1 ซึ่งอยู่ใน TIFR1
บรรทัดอื่น ๆ ทั้งหมดควรตีความในลักษณะเดียวกัน
หมายเหตุบางส่วน:
TIMSK1 |= _BV(TOIE1);
นอกจากนี้คุณยังอาจเห็นสิ่งที่ชอบ _BV()
เป็นมาโครที่ใช้กันทั่วไปมีพื้นเพมาจากAVR libc การดำเนินงาน _BV(TOIE1)
มีคุณสมบัติเหมือนกัน(1 << TOIE1)
กับประโยชน์ของการอ่านที่ดีขึ้น
นอกจากนี้คุณยังอาจเห็นเส้นเช่น: หรือTIMSK1 &= ~(1 << TOIE1);
TIMSK1 &= ~_BV(TOIE1);
นี้มีฟังก์ชั่นตรงข้ามTIMSK1 |= _BV(TOIE1);
ในการที่จะunsetsบิตในTOIE1
TIMSK1
สิ่งนี้สามารถทำได้โดยการใช้ bit-mask ที่สร้างขึ้นโดย_BV(TOIE1)
ดำเนินการกับ bitwise NOT operation บนมัน ( ~
) จากนั้นTIMSK1
ANDING ด้วยค่า NOTed นี้ (ซึ่งคือ 0b11111110)
โปรดทราบว่าในกรณีเหล่านี้ทั้งหมดคุณค่าของสิ่งที่ชอบ(1 << TOIE1)
หรือ_BV(TOIE1)
ได้รับการแก้ไขอย่างสมบูรณ์ในเวลารวบรวมดังนั้นพวกเขาจึงลดลงเป็นค่าคงที่ที่ใช้งานได้ง่ายและดังนั้นจึงไม่ต้องใช้เวลาดำเนินการในการคำนวณที่รันไทม์
โดยทั่วไปแล้วรหัสที่เขียนอย่างถูกต้องจะมีความคิดเห็นสอดคล้องกับรหัสซึ่งระบุรายละเอียดสิ่งที่ลงทะเบียนที่ได้รับมอบหมายให้ทำ นี่เป็นรูทีน soft-SPI ที่ค่อนข้างง่ายที่ฉันเพิ่งเขียน:
uint8_t transactByteADC(uint8_t outByte)
{
// Transfers one byte to the ADC, and receives one byte at the same time
// does nothing with the chip-select
// MSB first, data clocked on the rising edge
uint8_t loopCnt;
uint8_t retDat = 0;
for (loopCnt = 0; loopCnt < 8; loopCnt++)
{
if (outByte & 0x80) // if current bit is high
PORTC |= _BV(ADC_MOSI); // set data line
else
PORTC &= ~(_BV(ADC_MOSI)); // else unset it
outByte <<= 1; // and shift the output data over for the next iteration
retDat <<= 1; // shift over the data read back
PORTC |= _BV(ADC_SCK); // Set the clock high
if (PINC & _BV(ADC_MISO)) // sample the input line
retDat |= 0x01; // and set the bit in the retval if the input is high
PORTC &= ~(_BV(ADC_SCK)); // set clock low
}
return retDat;
}
PORTC
คือรีจิสเตอร์ที่ควบคุมค่าพินเอาต์พุตภายในPORTC
ATmega328P PINC
คือรีจิสเตอร์ซึ่งค่าอินพุตของPORTC
พร้อมใช้งาน โดยพื้นฐานแล้วสิ่งต่างๆเช่นนี้เป็นสิ่งที่เกิดขึ้นภายในเมื่อคุณใช้งานdigitalWrite
หรือdigitalRead
ฟังก์ชั่น อย่างไรก็ตามมีการดำเนินการค้นหาที่แปลง arduino "หมายเลขพิน" เป็นหมายเลขพินฮาร์ดแวร์ที่เกิดขึ้นจริงซึ่งใช้เวลาที่ไหนสักแห่งในอาณาจักรของรอบ 50 นาฬิกา ในขณะที่คุณสามารถเดาได้ว่าถ้าคุณกำลังพยายามที่จะไปอย่างรวดเร็วเสียเวลา 50 รอบในการดำเนินการที่ควรเพียงแค่ 1 เป็นบิตที่ไร้สาระ
ฟังก์ชั่นด้านบนอาจใช้เวลาสักครู่ในอาณาจักรของรอบนาฬิกา 100-200 รอบเพื่อถ่ายโอน 8 บิต สิ่งนี้มีผลต่อ 24 การเขียนพินและ 8 การอ่าน นี่คือเร็วขึ้นหลายเท่าแล้วใช้digital{stuff}
ฟังก์ชั่น