SAM3X8E (Arduino Due) регистры ввода-вывода Pin

9

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

Есть также некоторые полезные функции , такие как 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как.

Alex
источник
Вот класс GPIO, который реализован для AVR и SAM. Может дать подсказку о том, как использовать регистры: github.com/mikaelpatel/Arduino-GPIO/blob/master/src/Hardware/…
Микаэль Патель

Ответы:

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 бита порта одновременно, вам нужно будет сохранить текущее значение выводов, выполнить операцию И, чтобы замаскировать те, которые вы Вы хотите изменить, выполнить операцию ИЛИ, чтобы установить те, которые вы хотите установить высоко, затем выполнить запись и снова, и это не оптимально. Чтобы преодолеть это, сам процессор выполнит маскировку за вас. Существует регистр 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. Прочитайте и поиграйте, и если у вас возникнут дополнительные вопросы, я постараюсь на них ответить.

Редактировать: еще одна вещь ...

Как вы узнаете, какие биты PORT соответствуют каким цифровым линиям Due? Проверьте это: из- за распиновки

Мик Уэйтс
источник
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-битных цветных пиксельных данных, которые нуждаются в быстрый доступ к портам. Я думаю, что у меня есть правильный код - особенно строка, которая устанавливает низкий уровень булавки. Светодиод счастливо мигает.

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);   
}
Джеймс Моксхэм
источник