SAM3X8E (Arduino Due) Pin IO ลงทะเบียน


9

การลงทะเบียน IO ของ Arduino Due ทำงานอย่างไร บน Arduino Uno เพียงแค่ตั้งDDRxแล้วPINxจะอ่านPORTxจะเขียนผมอยากจะทำสิ่งเดียวกันกับ Arduino เนื่องจาก แต่ก็มีการลงทะเบียนอื่น ๆ อีกมากมายเช่นPIO_OWER, PIO_OSER, PIO_CODR, PIO_SODRฯลฯ ผมพบการติดต่อระหว่าง Arduino Uno และไม่มีการ Arduino ลงทะเบียนเนื่องจาก

นอกจากนี้ยังมีฟังก์ชั่นที่มีประโยชน์เช่นpio_clear, pio_set, pio_getและอื่น ๆ ทั้งหมดที่อธิบายที่นี่:

http://asf.atmel.com/docs/3.19.0/sam3x/html/group__sam__drivers__pio__group.html

ตอนนี้ฉันคิดว่าฉันเข้าใจสิ่งที่ทั้งสามฟังก์ชั่นที่กล่าวถึงทำ แต่ไม่ใช่คนอื่น ๆ เช่น:

pio_configure (Pio *p_pio, const pio_type_t ul_type, const uint32_t ul_mask, const uint32_t ul_attribute)

ฉันไม่สามารถคิดออกว่าul_attributeและul_typeมี


นี่คือคลาส GPIO ที่ใช้งานกับ AVR และ SAM อาจให้คำแนะนำเกี่ยวกับวิธีใช้รีจิสเตอร์: github.com/mikaelpatel/Arduino-GPIO/blob/master/src/Hardware/ …
Mikael Patel

คำตอบ:


7

หากคุณได้อ่านหัวข้อ 31 ของแผ่นข้อมูลซึ่งมีให้จากที่นี่สิ่งต่าง ๆ อาจชัดเจนขึ้นสำหรับคุณ

นี่คือบทสรุปของสิ่งที่ฉันรู้:

PIO ย่อมาจาก Parallel Input / Output และมีฟังก์ชั่นในการอ่านและเขียนพอร์ตการลงทะเบียนหลายครั้ง ในกรณีที่แผ่นข้อมูลกล่าวถึงการลงทะเบียนเช่น PIO_OWER ห้องสมุด Arduino มีมาโครสำหรับการเข้าถึงพวกเขาในรูปแบบนี้ REG_PIO? _OWER ที่ไหน เป็น A, B, C หรือ D สำหรับพอร์ตต่าง ๆ ที่มีอยู่

ฉันมักจะยังคงใช้ฟังก์ชั่น Arduino pinMode () ที่ช้าในการตั้งค่าอินพุต / เอาต์พุตบนพินเนื่องจากทำให้โค้ดอ่านได้ง่ายกว่าการลงทะเบียนตัวย่อตามตัวย่อเช่น REG_PIOC_OWER = 0xdeadbeef แต่ใช้รีจิสเตอร์โดยตรงเพื่อตั้งพินสำหรับ ผลการดำเนินงาน / ประสาน ในตอนนี้ฉันยังไม่ได้ทำอะไรเลยกับอินพุตดังนั้นตัวอย่างของฉันจึงเป็นแบบเอาต์พุตทั้งหมด

สำหรับการใช้งานขั้นพื้นฐานคุณจะใช้ REG_PIO? _SODR เพื่อตั้งค่าบรรทัดเอาต์พุตให้สูงและ REG_PIO? _CODR เพื่อตั้งค่าให้ต่ำ ตัวอย่างเช่น REG_PIOC_SODR = 0x00000002 จะตั้งค่าบิต 1 (ตัวเลขจากศูนย์) บน PORTC (นี่คือพินแบบดิจิตอลเนื่องจาก 33) หมุดอื่น ๆ ทั้งหมดบน PORTC ยังคงไม่เปลี่ยนแปลง REG_POIC_CODR = 0x00000002 จะกำหนดบิตที่ 1 ในระดับต่ำ PORTC หมุดอื่น ๆ ทั้งหมดจะไม่เปลี่ยนแปลงอีก

เนื่องจากนี่ยังไม่เหมาะสมหรือซิงโครไนซ์ถ้าคุณทำงานกับข้อมูลแบบขนานมีการลงทะเบียนที่ให้คุณเขียนพอร์ต 32 บิตทั้งหมดด้วยการโทรเพียงครั้งเดียว นี่คือ REG_PIO? _ODSR ดังนั้น REG_PIOC_ODSR = 0x00000002 ตอนนี้จะตั้งค่าบิตที่ 1 ในระดับสูง PORTC และบิตอื่น ๆ ทั้งหมดใน PORTC จะถูกตั้งค่าต่ำทันทีในคำสั่ง CPU เดียว

เนื่องจากไม่น่าเป็นไปได้ที่คุณจะอยู่ในสถานการณ์ที่คุณจำเป็นต้องตั้งค่าพอร์ต 32 บิตทั้งหมดในเวลาเดียวกันคุณจะต้องเก็บค่าปัจจุบันของหมุดทำการดำเนินการและเพื่อปกปิดสิ่งที่คุณทำ ต้องการแก้ไขดำเนินการ OR เพื่อตั้งค่าที่คุณต้องการตั้งค่าสูงจากนั้นทำการเขียนและอีกครั้งและสิ่งนี้ไม่เหมาะสม เพื่อเอาชนะสิ่งนี้ซีพียูจะทำการปิดบังตัวคุณ มีรีจิสเตอร์ที่เรียกว่า OWSR (ลงทะเบียนสถานะการเขียนเอาต์พุต) ที่จะปกปิดบิตใด ๆ ที่คุณเขียนไปยัง ODSR ที่ไม่ตรงกับบิตที่ตั้งค่าไว้ใน OWSR

ดังนั้นตอนนี้ถ้าเราเรียก REG_PIOC_OWER = 0x00000002 (ชุดนี้เป็นบิตที่ 1 ของ OWSR สูง) และ REG_PIOC_OWDR = 0xfffffffd (ซึ่งจะทำการล้างบิตทั้งหมดยกเว้นบิต 1 ของ OWSR) แล้วจึงเรียก REG_PIOC_ODSR = 0x00000002 อีกครั้งคราวนี้มันจะเปลี่ยนบิตเพียงเล็กน้อย 1 ของ PORTC และบิตอื่น ๆ ทั้งหมดยังคงไม่เปลี่ยนแปลง เอาใจใส่ข้อเท็จจริงที่ว่าOWER เปิดใช้งานบิตใด ๆที่ตั้งค่าเป็น 1ในค่าที่คุณเขียนและOWDR จะปิดใช้งานบิตใด ๆที่ตั้งค่าเป็น 1ในค่าที่คุณเขียน แม้ว่าฉันจะเข้าใจสิ่งนี้เมื่อฉันอ่านมันฉันยังคงพยายามที่จะทำรหัสผิดพลาดเมื่อเขียนรหัสทดสอบครั้งแรกของฉันโดยคิดว่า OWDR ปิดใช้งานบิตที่ไม่ได้ตั้งค่าเป็น 1 ในค่าที่ฉันเขียน

ฉันหวังว่าสิ่งนี้จะช่วยให้คุณเริ่มเข้าใจ PIO ของ Due CPU มีการอ่านและการเล่นและหากคุณมีคำถามเพิ่มเติมฉันจะพยายามตอบคำถามเหล่านั้น

แก้ไข: อีกหนึ่งสิ่ง ...

คุณจะรู้ได้อย่างไรว่าบิตของ PORT ใดที่สอดคล้องกับสายดิจิตอลของ Due? ลองดูสิ: Pinout ที่ครบกำหนด


3

มีความเท่าเทียมกันค่อนข้างง่ายสำหรับการเข้าถึงพินพื้นฐานโดยตรง ด้านล่างนี้คือตัวอย่างรหัสบางส่วนที่แสดงวิธีตั้งค่าพินดิจิตอลให้สูงและต่ำ สิ่งแรกคือสำหรับ Arduino Due ส่วนที่สองสำหรับ Arduino Uno / Mega / etc

const unsigned int imThePin = 10; //e.g. digital Pin 10

#ifdef _LIB_SAM_

    //First lets get the pin and bit mask - this can be done once at the start and then used later in the code (as long as the variables are in scope
    Pio* imThePort = g_APinDescription[imThePin].pPort; 
    unsigned int imTheMask = g_APinDescription[imThePin].ulPin; 

    //Lets set the pin high
    imThePort->PIO_SODR = imTheMask;
    //And then low
    imThePort->PIO_CODR = imTheMask;

#else

    //First lets get the pin and bit mask - this can be done once at the start and then used later in the code (as long as the variables are in scope
    volatile unsigned char* imThePort = portOutputRegister(digitalPinToPort(imThePin)); 
    unsigned char imTheMask = digitalPinToBitMask(imThePin);

    //Lets set the pin high
    *imThePort |= imTheMask;
    //Now low
    *imThePort &= ~imTheMask;

#endif

ทุกสิ่งที่จำเป็นในการทำเช่นนั้นควรรวมไว้เป็นค่าเริ่มต้น - และหากไม่#include <Arduino.h>ควรเพียงพอที่จะไปถึงที่นั่น

มีฟังก์ชั่นที่ใช้งานได้จริงซึ่งสามารถเรียกใช้งานได้เมื่อคุณมีPioตัวชี้เพื่อทำการตั้งค่า / ล้าง / ดึงตัวต้านทาน / ฯลฯ ใช้ฟังก์ชั่นการโทรที่ดูดีขึ้น รายการทั้งหมดสามารถพบได้ใน ไฟล์ส่วนหัว


0

นี่คือตัวอย่างรหัสที่กะพริบนำบนขา 33 รหัสที่ยืมมาจากข้างบน - ขอบคุณมากสำหรับคำอธิบายที่เป็นประโยชน์มาก :) นี่คือจุดเริ่มต้นของโครงการที่จะพูดคุยกับจอแสดงผลแบบสัมผัสหน้าจอสัมผัส TFT ด้วยการทิ้งข้อมูลพิกเซลสีขนาด 16 บิต เข้าถึงพอร์ตได้อย่างรวดเร็ว ฉันคิดว่าฉันมีรหัสที่ถูกต้อง - โดยเฉพาะอย่างยิ่งสายที่กำหนดพินต่ำ ไฟ LED กะพริบอย่างมีความสุข

void setup() 
{
  pinMode(33, OUTPUT); 
  REG_PIOC_OWER = 0x00000002; 
  REG_PIOC_OWDR = 0xfffffffd; 
}

void loop() 
{
  REG_PIOC_ODSR = 0x00000002; 
  delay(1000);             
  REG_PIOC_ODSR = 0x00000000;    
  delay(1000);   
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.