Регістри SAM IXXE (Arduino Due) Pin IO


9

Як працюють IO-регістри Arduino Due? На Arduino Uno просто встановити DDRx, а потім PINxчитати, PORTxписати, я хотів би зробити те ж саме з Arduino Due, але вона має багато більше регістрів, таких як PIO_OWER, PIO_OSER, PIO_CODR, PIO_SODRі т.д. я не знаходжу відповідності між Arduino Uno і Реєстри Arduino Due.

Є також деякі корисні функції , такі як 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. Може підказати,
Mikael Patel

Відповіді:


7

Якщо ви ознайомилися з розділом 31 Таблиці даних, доступним звідси , тут вам можуть стати дещо зрозумілішими.

Ось підсумок того, що я знаю:

PIO розшифровується як паралельний вхід / вихід та пропонує функцію зчитування та запису декількох портів реєстрації одночасно. Там, де у таблиці даних згадується реєстр, наприклад 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 були б встановлені низькими миттєво в одній інструкції процесора.

Оскільки навряд чи ви потрапляли б у ситуацію, коли вам потрібно одночасно встановити всі 32 біти порту, вам потрібно буде зберегти поточне значення штифтів, виконати операцію AND, щоб замаскувати ті, які ви Якщо ви хочете змінити, виконайте операцію АБО, щоб встановити ті, які ви хочете встановити, то виконайте запис і ще раз, і це не є оптимальним. Щоб подолати це, процесор сам виконає маскування за вас. Існує регістр під назвою 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 Pinout


3

Існує досить проста еквівалентність основного прямого доступу. Нижче наведено зразок коду, який показує, як встановити цифровий контакт високим, а потім низьким. Перший - для Arduino Due, другий - для Arduino Uno / Mega / тощо.

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-бітових кольорових піксельних даних, які потребують швидкий доступ до портів. Я думаю, що у мене є правильний код - особливо рядок, який встановлює штифт низьким. Світло радісно блимає.

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);   
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.