SAM3X8E (Arduino Do) đăng ký Pin IO


9

Làm thế nào để các thanh ghi IO của Arduino Do hoạt động? Trên Arduino Uno chỉ cần đặt DDRx, sau đó PINxđể đọc, PORTxviết, tôi muốn làm điều tương tự với một Arduino Duệ, nhưng nó có nhiều thanh ghi hơn, chẳng hạn như PIO_OWER, PIO_OSER, PIO_CODR, PIO_SODR, vv Tôi tìm thấy không có sự tương ứng giữa Arduino Uno và Thanh ghi Arduino Do.

Ngoài ra còn có một số chức năng hữu ích như pio_clear, pio_set, pio_get, và những người khác, tất cả các giải thích ở đây:

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

Bây giờ, tôi nghĩ rằng tôi đã hiểu ba chức năng được đề cập làm gì, nhưng không phải là các chức năng khác, ví dụ:

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

Tôi không thể tìm ra những gì ul_attributeul_typeđang có.


Đây là một lớp GPIO được triển khai cho AVR và SAM. Có thể đưa ra gợi ý về cách sử dụng các thanh ghi: github.com/mikaelpatel/Arduino-GPIO/blob/master/src/Hardware/ Lỗi
Mikael Patel

Câu trả lời:


7

Nếu bạn đã đọc phần 31 của Bảng dữ liệu, có sẵn từ đây , mọi thứ có thể rõ ràng hơn một chút cho bạn.

Dưới đây là tóm tắt về những gì tôi biết:

PIO là viết tắt của Parallel Input / Output và cung cấp chức năng đọc và ghi nhiều cổng đăng ký cùng một lúc. Trường hợp biểu dữ liệu đề cập đến một thanh ghi, ví dụ PIO_OWER, thư viện Arduino có các macro để truy cập chúng theo định dạng này REG_PIO? _OWER ở đâu? là A, B, C hoặc D cho các cổng khác nhau có sẵn.

Tôi có xu hướng vẫn sử dụng hàm Arduino pinMode () chậm để đặt đầu vào / đầu ra trên các chân vì nó làm cho mã dễ đọc hơn các lệnh gọi đăng ký dựa trên từ viết tắt như REG_PIOC_OWER = 0xdeadbeef, nhưng sau đó sử dụng các thanh ghi trực tiếp để đặt các chân cho hiệu suất / đồng bộ hóa. Tuy nhiên, tôi chưa làm gì với đầu vào, vì vậy các ví dụ của tôi đều dựa trên đầu ra.

Đối với việc sử dụng cơ bản, bạn sẽ sử dụng REG_PIO? _SODR để đặt các dòng đầu ra ở mức cao và REG_PIO? _CODR để đặt chúng ở mức thấp. Ví dụ: REG_PIOC_SODR = 0x00000002 sẽ đặt bit 1 (được đánh số từ 0) trên PORTC (đây là pin kỹ thuật số 33) cao. Tất cả các chân khác trên PORTC vẫn không thay đổi. REG_POIC_CODR = 0x00000002 sẽ đặt bit 1 ở mức PORTC thấp. Một lần nữa tất cả các chân khác sẽ không thay đổi.

Vì điều này vẫn chưa tối ưu hoặc được đồng bộ hóa nếu bạn đang làm việc với dữ liệu song song, có một thanh ghi cho phép bạn ghi tất cả 32 bit của một cổng với một cuộc gọi. Đây là REG_PIO? _ODSR, vì vậy REG_PIOC_ODSR = 0x00000002 bây giờ sẽ đặt bit 1 trên mức cao PORTC và tất cả các bit khác trên PORTC sẽ được đặt ở mức thấp ngay lập tức trong một lệnh CPU.

Bởi vì không chắc là bạn đã từng ở trong tình huống cần thiết lập tất cả 32 bit của một cổng, bạn sẽ cần lưu trữ giá trị hiện tại của các chân, thực hiện thao tác AND để che giấu những cái bạn muốn thay đổi, thực hiện thao tác OR để đặt mức bạn muốn đặt lên cao, sau đó thực hiện ghi và viết lại, và điều này không tối ưu. Để khắc phục điều này, CPU sẽ tự thực hiện mặt nạ cho bạn. Có một thanh ghi được gọi là OWSR (thanh ghi trạng thái ghi đầu ra) sẽ che giấu bất kỳ bit nào bạn ghi vào ODSR không khớp với các bit được đặt trong OWSR.

Vì vậy, bây giờ nếu chúng ta gọi REG_PIOC_OWER = 0x00000002 (điều này đặt bit 1 của OWSR cao) và REG_PIOC_OWDR = 0xfffffffd (điều này sẽ xóa tất cả các bit ngoại trừ bit 1 của OWSR) 1 của PORTC và tất cả các bit khác không thay đổi. Hãy chú ý đến thực tế là OWER cho phép bất kỳ bit nào được đặt thành 1 trong giá trị bạn viết và OWDR sẽ vô hiệu hóa bất kỳ bit nào được đặt thành 1 trong giá trị bạn viết. Mặc dù tôi đã hiểu điều này khi đọc nó, tôi vẫn cố gắng mắc lỗi mã khi viết mã kiểm tra đầu tiên của mình với suy nghĩ rằng các bit bị vô hiệu hóa OWDR không được đặt thành 1 trong giá trị tôi đã viết.

Tôi hy vọng điều này ít nhất đã cho bạn một chút khởi đầu trong việc tìm hiểu PIO của CPU do. Hãy đọc và chơi và nếu bạn có thêm câu hỏi nào, tôi sẽ cố gắng trả lời chúng.

Chỉnh sửa: Một điều nữa ...

Làm thế nào để bạn biết bit nào của PORT tương ứng với dòng kỹ thuật số nào của Hạn? Kiểm tra này: Do Pinout


3

Có một sự tương đương khá đơn giản cho việc truy cập pin trực tiếp cơ bản. Dưới đây là một số mã mẫu cho biết cách đặt pin kỹ thuật số cao rồi thấp. Đầu tiên là cho Arduino Do, thứ hai là cho Arduino Uno / Mega / vv.

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

Tất cả mọi thứ cần thiết để làm điều đó nên được bao gồm theo mặc định - và nếu không #include <Arduino.h>đủ để có được nó ở đó.

Có những hàm thực sự có sẵn có thể được gọi khi bạn có Piocon trỏ để thực hiện cài đặt / xóa / điện trở pullup / v.v. sử dụng các cuộc gọi chức năng tìm kiếm hơi sạch hơn. Một danh sách đầy đủ có thể được tìm thấy trong tập tin tiêu đề.


0

Đây là một ví dụ mã nhấp nháy đèn led ở chân 33. Mã được mượn từ phía trên - cảm ơn rất nhiều vì những lời giải thích rất hữu ích :) Đây là khởi đầu của một dự án để nói chuyện với màn hình cảm ứng TFT với việc đổ dữ liệu pixel màu 16 bit cần truy cập nhanh vào các cổng. Tôi nghĩ rằng tôi có mã đúng - đặc biệt là dòng đặt pin thấp. Đèn led đang vui vẻ nhấp nháy.

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);   
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.