SAM3X8E (Arduino Due) Pin IO register

9

Bagaimana cara kerja IO register dari Arduino Due? Pada Arduino Uno hanya mengatur DDRx, kemudian PINxmembaca, PORTxmenulis, saya ingin melakukan hal yang sama dengan Arduino Karena, tetapi memiliki lebih banyak register, seperti PIO_OWER, PIO_OSER, PIO_CODR, PIO_SODR, dll saya menemukan ada korespondensi antara Arduino Uno dan Register Arduino Karena.

Ada juga beberapa fungsi yang berguna seperti pio_clear, pio_set, pio_get, dan lain-lain, semua dijelaskan di sini:

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

Sekarang, saya pikir saya sudah mengerti apa yang dilakukan tiga fungsi yang disebutkan, tetapi tidak yang lain, misalnya:

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

Saya tidak tahu apa ul_attributedan apa ul_type.

Alex
sumber
Ini adalah kelas GPIO yang diterapkan untuk AVR dan SAM. Mungkin memberi petunjuk tentang cara menggunakan register: github.com/mikaelpatel/Arduino-GPIO/blob/master/src/Hardware/…
Mikael Patel

Jawaban:

7

Jika Anda membaca bagian 31 dari Lembar Data, tersedia dari sini , segala sesuatunya mungkin menjadi lebih jelas bagi Anda.

Berikut ringkasan dari apa yang saya ketahui:

PIO adalah singkatan dari Input / Output Paralel dan menawarkan fungsionalitas untuk membaca dan menulis beberapa port register sekaligus. Di mana lembar data menyebutkan register, misalnya PIO_OWER, perpustakaan Arduino memiliki makro untuk mengaksesnya dalam format ini REG_PIO? _OWER di mana? adalah A, B, C atau D untuk berbagai port yang tersedia.

Saya cenderung masih menggunakan pinMode () fungsi Arduino lambat untuk mengatur input / output pada pin karena membuat kode lebih mudah dibaca daripada panggilan register berbasis akronim seperti REG_PIOC_OWER = 0xdeadbeef, tapi kemudian gunakan register langsung untuk mengatur pin untuk kinerja / sinkronisasi. Sampai sekarang, saya belum melakukan apa pun dengan input, jadi contoh saya semuanya berbasis output.

Untuk penggunaan dasar, Anda akan menggunakan REG_PIO? _SODR untuk mengatur jalur output tinggi dan REG_PIO? _CODR untuk mengaturnya rendah. Misalnya REG_PIOC_SODR = 0x00000002 akan mengatur bit 1 (dinomori dari nol) pada PORTC (ini karena pin digital 33) tinggi. Semua pin lain di PORTC tetap tidak berubah. REG_POIC_CODR = 0x00000002 akan menetapkan bit 1 pada PORTC rendah. Sekali lagi semua pin lainnya tidak akan berubah.

Karena ini masih belum optimal, atau disinkronkan jika Anda bekerja dengan data paralel, ada register yang memungkinkan Anda untuk menulis semua 32 bit port dengan satu panggilan. Ini adalah REG_PIO? _ODSR, jadi REG_PIOC_ODSR = 0x00000002 sekarang akan menetapkan bit 1 pada PORTC tinggi dan semua bit lain pada PORTC akan ditetapkan rendah langsung dalam satu instruksi CPU.

Karena tidak mungkin Anda akan berada dalam situasi di mana Anda perlu mengatur semua 32 bit port pada saat yang sama, Anda perlu menyimpan nilai pin saat ini, melakukan operasi DAN untuk menutupi yang Anda ingin mengubah, melakukan operasi ATAU untuk mengatur yang ingin Anda atur tinggi kemudian melakukan penulisan Anda dan lagi, dan ini tidak optimal. Untuk mengatasinya, CPU itu sendiri akan melakukan masking untuk Anda. Ada register yang disebut OWSR (register status penulisan output) yang akan menutupi bit yang Anda tulis ke ODSR yang tidak cocok dengan bit yang ditetapkan dalam OWSR.

Jadi, sekarang jika kita memanggil REG_PIOC_OWER = 0x00000002 (ini menetapkan bit 1 dari OWSR tinggi) dan REG_PIOC_OWDR = 0xfffffffd (ini menghapus semua bit kecuali bit 1 dari OWSR) dan kemudian memanggil REG_PIOC_ODSR = 0x00000002 lagi, kali ini hanya akan mengubah bit 1 PORTC dan semua bit lainnya tetap tidak berubah. Perhatikan fakta bahwa OWER mengaktifkan bit apa pun yang ditetapkan ke 1 pada nilai yang Anda tulis dan OWDR menonaktifkan bit apa pun yang diatur ke 1 pada nilai yang Anda tulis. Meskipun saya mengerti ini ketika saya membacanya, saya masih berhasil membuat kesalahan kode ketika menulis kode pengujian pertama saya berpikir bahwa OWDR menonaktifkan bit yang tidak diatur ke 1 pada nilai yang saya tulis.

Saya harap ini setidaknya memberi Anda sedikit permulaan dalam memahami PIO CPU Karena. Baca dan mainkan dan jika Anda memiliki pertanyaan lebih lanjut, saya akan mencoba menjawabnya.

Edit: Satu hal lagi ...

Bagaimana Anda tahu bit PORT mana yang sesuai dengan garis digital Due? Lihat ini: Karena Pinout

Mick Waites
sumber
3

Ada kesetaraan yang cukup sederhana untuk akses pin langsung dasar. Di bawah ini adalah beberapa kode contoh yang menunjukkan cara mengatur pin digital tinggi dan rendah. Yang pertama adalah untuk Arduino Due, yang kedua adalah untuk 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

Semua yang diperlukan untuk melakukan itu harus dimasukkan secara default - dan jika tidak #include <Arduino.h>cukup untuk mendapatkannya di sana.

Sebenarnya ada fungsi yang tersedia yang dapat dipanggil setelah Anda memiliki Piopointer untuk melakukan pengaturan / kliring / resistor pullup / dll. menggunakan panggilan fungsi yang tampak lebih bersih. Daftar lengkap dapat ditemukan di file header.

Tom Carpenter
sumber
0

Ini adalah contoh kode yang menampilkan led pada pin 33. Kode yang dipinjam dari atas - terima kasih banyak atas penjelasannya yang sangat membantu :) Ini adalah awal dari proyek untuk berbicara dengan tampilan layar sentuh TFT dengan membuang data piksel warna 16bit yang membutuhkan akses cepat ke porta. Saya pikir saya memiliki kode yang benar - terutama garis yang menetapkan pin rendah. Memimpin dengan senang hati berkedip.

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);   
}
James Moxham
sumber