ประเภท: วงจรไมโครคอนโทรลเลอร์
จำนวนการดู: 41940
ความเห็นเกี่ยวกับบทความ: 5
วิธีการสำหรับการอ่านและการจัดการพอร์ต Arduino I / O
ในการโต้ตอบกับโลกภายนอกคุณต้องกำหนดค่าเอาต์พุตของไมโครคอนโทรลเลอร์เพื่อรับหรือส่งสัญญาณ ดังนั้นแต่ละขาจะทำงานในโหมดอินพุตและเอาต์พุต มีสองวิธีในการทำเช่นนี้ในทุกบอร์ด Arduino ที่คุณรักวิธีที่คุณเรียนรู้จากบทความนี้

วิธีที่หนึ่ง - ภาษามาตรฐานสำหรับ Arduino IDE
ทุกคนรู้ดีว่า Arduino มันถูกตั้งโปรแกรมใน C ++ พร้อมการปรับแต่งและการทำให้เรียบง่ายสำหรับผู้เริ่มต้น มันเรียกว่าการเดินสาย เริ่มแรกพอร์ต arduino ทั้งหมดจะถูกกำหนดเป็นอินพุตและไม่จำเป็นต้องระบุในรหัส
พอร์ตมักจะเขียนในฟังก์ชั่นการเริ่มต้นตัวแปร:
การตั้งค่าเป็นโมฆะ ()
{
// รหัส
}
คำสั่ง pinMode ใช้สำหรับสิ่งนี้มันมีไวยากรณ์ที่ค่อนข้างง่ายก่อนอื่นหมายเลขพอร์ตจะถูกระบุจากนั้นบทบาทจะถูกคั่นด้วยเครื่องหมายจุลภาค
pinMode (nomer_porta, naznachenie)
ด้วยคำสั่งนี้วงจรภายในของไมโครคอนโทรลเลอร์จะถูกกำหนดค่าด้วยวิธีเฉพาะ
มีสามโหมดที่พอร์ตสามารถทำงานได้: อินพุต - อินพุตในโหมดนี้เกิดขึ้น อ่านข้อมูลจากเซ็นเซอร์สถานะปุ่มสัญญาณอะนาล็อกและดิจิตอล พอร์ตตั้งอยู่ในสิ่งที่เรียกว่า สภาวะที่มีความต้านทานสูงในคำง่ายๆ - อินพุตมีความต้านทานสูง ค่านี้ถูกตั้งค่าไว้เช่น 13 pin ของบอร์ดหากจำเป็นดังต่อไปนี้:
pinMode (13, INPUT);
OUTPUT - เอาต์พุตขึ้นอยู่กับคำสั่งที่กำหนดไว้ในรหัสพอร์ตใช้ค่าหนึ่งหรือศูนย์ เอาต์พุตกลายเป็นแหล่งพลังงานที่ควบคุมได้และสร้างกระแสสูงสุด (ในกรณีของเราคือ 20 mA และ 40 mA ที่จุดสูงสุด) ที่เชื่อมต่อกับโหลด ในการกำหนดพอร์ตเป็นเอาต์พุตไปยัง Arduino คุณต้องป้อน:
pinMode (13, OUTPUT);
INPUT_PULLUP - พอร์ตทำงานเป็นอินพุต แต่สิ่งที่เรียกว่าเชื่อมต่อกับมัน ตัวต้านทานแบบดึงขึ้น 20 kΩ
วงจรภายในแบบมีเงื่อนไขของพอร์ตในสถานะนี้แสดงอยู่ด้านล่าง คุณลักษณะของอินพุตนี้คือสัญญาณอินพุตถูกรับรู้เป็นฤvertedษี (“ หน่วย” ที่อินพุตถูกรับรู้โดยไมโครคอนโทรลเลอร์ว่า“ ศูนย์”) ในโหมดนี้คุณไม่สามารถใช้ตัวต้านทานแบบดึงขึ้นภายนอกได้ เมื่อทำงานกับปุ่มต่างๆ.
pinMode (13, INPUT_PULLUP);

ข้อมูลที่ได้รับจากพอร์ตและส่งไปยังพวกเขาโดยคำสั่ง:
-
digitalWrite (พินค่า) - แปลงพินเอาต์พุตเป็นโลจิคัล 1 หรือ 0 ตามลำดับแรงดัน 5V จะปรากฏขึ้นหรือหายไปที่เอาต์พุตเช่น digitalWrite (13, HIGH) - จ่าย 5 โวลต์ (โลจิคัลยูนิต) เป็น 13 พินและ digitalWrite (13, ต่ำ ) - แปล 13 พินให้อยู่ในสถานะศูนย์ตรรกะ (0 โวลต์)
-
digitalRead (พิน) - อ่านค่าจากอินพุตเช่น digitalRead (10) อ่านสัญญาณจาก 10 พิน
-
analogRead (พิน) - อ่านสัญญาณอะนาล็อกจากพอร์ตอะนาล็อกคุณจะได้รับค่าอยู่ในช่วงตั้งแต่ 0 ถึง 1023 (ภายใน ADC 10 บิต) ตัวอย่างคือ analogRead (3)
วิธีที่สอง - จัดการพอร์ตผ่าน Atmega register และเร่งความเร็วโค้ด
แน่นอนว่าการควบคุมดังกล่าวเป็นเรื่องง่าย แต่ในกรณีนี้มีสองข้อเสียคือการใช้หน่วยความจำที่มากขึ้นและประสิทธิภาพที่ต่ำเมื่อทำงานกับพอร์ต แต่จำไว้ว่า Arduino คืออะไรโดยไม่คำนึงถึงบอร์ดตัวเลือก (uno, micro, nano)? ก่อนอื่นนี้ ไมโครคอนโทรลเลอร์ตระกูล AVR ATMEGAเพิ่งใช้ MK atmega328
ใน Arduino IDE คุณสามารถตั้งโปรแกรมภาษา C AVR ให้กับตระกูลนี้ราวกับว่าคุณกำลังทำงานกับไมโครคอนโทรลเลอร์แยกต่างหาก แต่สิ่งแรกก่อน ในการจัดการพอร์ต Arduino ด้วยวิธีนี้อันดับแรกคุณต้องพิจารณาภาพประกอบต่อไปนี้อย่างรอบคอบ
อาจมีบางคนที่จะตรวจสอบพอร์ตในรูปแบบนี้อย่างชัดเจนมากขึ้น (เหมือนกันในรูป แต่ในรูปแบบที่แตกต่างกัน):

ที่นี่คุณจะเห็นการโต้ตอบของข้อสรุปของ Arduino และชื่อของพอร์ตของ Atmega ดังนั้นเรามี 3 พอร์ต:
-
PORTB;
-
PORTC;
-
PORTD
จากภาพที่แสดงฉันได้รวบรวมตารางการติดต่อระหว่างพอร์ตของ Arduino และ Atmega มันจะมีประโยชน์สำหรับคุณในอนาคต

Atmega มีรีจิสเตอร์ 8 บิตสามตัวที่ควบคุมสถานะของพอร์ตตัวอย่างเช่นพอร์ต B จะคิดออกวัตถุประสงค์ของพวกเขาโดยการวาดคล้ายคลึงกับเครื่องมือการเดินสายมาตรฐานที่อธิบายไว้ที่จุดเริ่มต้นของบทความนี้:
-
PORTB - จัดการสถานะเอาต์พุต หากพินอยู่ในโหมด“ เอาต์พุต” ดังนั้น 1 และ 0 จะกำหนดว่ามีสัญญาณเดียวกันที่เอาต์พุตหรือไม่ หากพินอยู่ในโหมด“ อินพุต” ดังนั้น 1 จะเชื่อมต่อตัวต้านทานแบบดึงขึ้น (เช่นเดียวกับ INPUT_PULLUP ที่กล่าวถึงด้านบน) ถ้า 0 เป็นสถานะความต้านทานสูง (อนาล็อกของอินพุต)
-
PINB เป็นทะเบียนอ่าน ดังนั้นจึงมีข้อมูลเกี่ยวกับสถานะปัจจุบันของพินพอร์ต (หน่วยโลจิคัลหรือศูนย์)
-
DDRB - การลงทะเบียนทิศทางพอร์ต ด้วยคุณระบุไมโครคอนโทรลเลอร์ว่าพอร์ตเป็นอินพุตหรือเอาต์พุตโดยมี“ 1” เอาต์พุตและ“ 0” อินพุต
แทนที่จะใช้ตัวอักษร“ B” สามารถมีชื่ออื่นตามชื่อพอร์ตตัวอย่างเช่นคำสั่งอื่น ๆ ของ PORTD หรือ PORTC ก็ทำงานในทำนองเดียวกัน
เรากระพริบไฟ LED แทนฟังก์ชั่น digitalWrite () มาตรฐาน ก่อนอื่นเรามาดูกันว่าตัวอย่างต้นฉบับจากห้องสมุด Arduino IDE มีหน้าตาเป็นอย่างไร

นี่คือรหัสของ“ การกะพริบ” ที่รู้จักกันดีซึ่งแสดงการกะพริบของ LED ที่ติดตั้งไว้ในบอร์ด

ความคิดเห็นอธิบายรหัส ตรรกะของงานนี้มีดังนี้
คำสั่ง PORTB B00100000 ทำให้ PB5 อยู่ในสถานะของหน่วยโลจิคัลรูปลักษณ์และรูปภาพเหล่านั้นและตารางที่อยู่ด้านล่างและดูว่า PB5 นั้นสอดคล้องกับ Arduina 13 พิน
ตัวอักษร "B" ด้านหน้าตัวเลขแสดงว่าเรากำลังเขียนค่าในรูปแบบไบนารี การระบุตัวเลขเป็นเลขฐานสองจากขวาไปซ้ายคือเช่น ที่นี่หน่วยอยู่ในบิตที่หกจากขอบด้านขวาของบิตซึ่งบอกไมโครคอนโทรลเลอร์เกี่ยวกับการโต้ตอบกับสถานะของบิตที่หกของพอร์ต B register (PB5) ตารางด้านล่างแสดงโครงสร้างของพอร์ต D มันคล้ายกันและได้รับเป็นตัวอย่าง

คุณสามารถตั้งค่าไม่ได้อยู่ในไบนารี แต่ในรูปแบบเลขฐานสิบหกเช่นนี้เราเปิดเครื่องคิดเลข windows และในโหมด“ ดู” ให้เลือกตัวเลือก“ โปรแกรมเมอร์”

ป้อนหมายเลขที่ต้องการ:

และคลิกที่ HEX:

ในกรณีนี้เราถ่ายโอนทั้งหมดนี้ไปยัง Arduino IDE แต่แทนที่จะเป็นคำนำหน้า "B" มันจะเป็น "0x"

แต่ด้วยอินพุตนี้มีปัญหา หากคุณมีสิ่งใดเชื่อมต่อกับพินอื่นให้ป้อนคำสั่งเช่น B00010000 - คุณจะรีเซ็ตพินทั้งหมดยกเว้น 13 (PB5) คุณสามารถป้อนข้อมูลสำหรับแต่ละพินได้ทีละรายการ มันจะมีลักษณะเช่นนี้:

เร็กคอร์ดดังกล่าวอาจดูเข้าใจไม่ได้ลองหากัน

นี่เป็นการดำเนินการเพิ่มเติมเชิงตรรกะ | = หมายถึงการเพิ่มบางสิ่งลงในเนื้อหาของพอร์ต

ซึ่งหมายความว่าคุณต้องเพิ่มคำว่า 8 บิตในรีจิสเตอร์โดยที่หน่วยเลื่อนไป 5 บิต - ถ้า 11000010 เปลี่ยนเป็น 110,110,010 ในตัวอย่างนี้จะเห็นได้ว่ามีการเปลี่ยนแปลงเพียง PB5 เท่านั้นส่วนที่เหลือของเรจิสเตอร์นี้ยังคงไม่เปลี่ยนแปลง สถานะของหมุดไมโครคอนโทรลเลอร์ยังคงไม่เปลี่ยนแปลง
แต่ด้วยการเพิ่มเชิงตรรกะปัญหาเกิดขึ้น - คุณไม่สามารถเปลี่ยนหน่วยเป็นศูนย์ได้เนื่องจาก:
0+0=1
1+0=1
0+1=1
การคูณเชิงตรรกะและการผกผันจะช่วยเราได้:

& = หมายถึงการคูณเนื้อหาของพอร์ตด้วยตัวเลขเฉพาะ

และนี่คือจำนวนที่เราคูณ เครื่องหมาย“ ~” หมายถึงการกลับด้าน ในกรณีของเราหน่วยกลับเป็นศูนย์ นั่นคือเราคูณเนื้อหาของพอร์ตเป็นศูนย์เลื่อนเป็น 5 บิต ตัวอย่างเช่นมันคือ 10110001 มันกลายเป็น 10100001 บิตที่เหลือยังคงไม่เปลี่ยนแปลง

สามารถทำได้โดยใช้การดำเนินการกลับหัว (^):
การอ่านจากพอร์ตอะนาล็อกของ digitalRead () ดำเนินการโดยใช้การลงทะเบียน PIN ในทางปฏิบัติดูเหมือนว่า:

ที่นี่เราตรวจสอบว่าการแสดงออกในวงเล็บเท่ากับรัฐจริงของพอร์ตคือ ในทำนองเดียวกันถ้าเราเขียนว่า (digitalRead (12) == 1)
ข้อสรุป
ทำไมถึงมีปัญหาดังกล่าวกับการจัดการพอร์ตหากคุณสามารถใช้ฟังก์ชั่นที่สะดวกสบายมาตรฐาน ทุกอย่างเกี่ยวกับความเร็วและขนาดโค้ด เมื่อใช้วิธีที่สองที่กล่าวถึงในบทความขนาดของรหัสจะลดลงอย่างมากและความเร็วจะเพิ่มขึ้นตามลำดับความสำคัญหลายประการ DigitalWrite มาตรฐาน () ถูกดำเนินการใน 1800 μsและบันทึกโดยตรงไปยังพอร์ตใน 0.2 μsและ digitalRead () ใน 1900 μsและยังกลายเป็น 0.2 μs วิธีการควบคุมนี้พบในพื้นที่เปิดโล่งของเครือข่ายและมักจะพบในรหัส โครงการที่แล้วเสร็จ.
ดูได้ที่ e.imadeself.com
: