Несколько записей variant.cpp для одного и того же физического контакта

Некоторые файлы variant.cpp содержат несколько записей, указывающих на один и тот же физический контакт. Например (из файла Arduino Zero):

// 14..19 - Аналоговые пины
// --------------------
{ PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]

...

// 43..45 - Альтернативное использование A0 (выход ЦАП), 44 SWCLK, 45, SWDIO
{ PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT

Первая запись настраивает контакт как обычный аналоговый входной контакт на A0. Вторая запись настраивает его как ЦАП на контакте IDE 43.

Соответствующий файл variant.h определяет вывод ЦАП и A0 как запись 14, а не 43. Я также видел в Интернете множество примеров, в которых ЦАП используется через A0 при работе с Arduino Zero. .

/*
 * Analog pins
 */
#define PIN_A0               (14ul)
#define PIN_A1               (15ul)
#define PIN_A2               (16ul)
#define PIN_A3               (17ul)
#define PIN_A4               (18ul)
#define PIN_A5               (19ul)
#define PIN_DAC0             (14ul)

Наконец, я вижу другие варианты, такие как этот даже не утруждайте себя созданием записи для DAC. То есть, наверное, это не имеет значения? Если нет, то почему он вообще находится в файле variant.cpp Arduino Zero?

Смежный вопрос: как работает вывод для нескольких целей? Например, если бы у меня был вывод, который я настроил для SPI MOSI (в variant.cpp), и я хотел бы также использовать его для PWM (учитывая, что в техническом описании указано, что вывод находится на SERCOM и таймер), действительно ли мне нужны две записи в variant.cpp и, следовательно, два разных контакта IDE для использования в моих скетчах (один с типом контакта PIO_SERCOM, а другой с PIO_PWM)? Я могу вспомнить множество случаев работы с Arduino UNO, например, когда я просто использовал один и тот же номер контакта IDE для общего ввода-вывода, а также для SPI (MOSI).

, 👍1


1 ответ


Лучший ответ:

1

Функция analogWrite проверяет атрибут PIN_ATTR_ANALOG из описания вывода в variant.cpp, чтобы определить, поддерживает ли вывод функцию DAC. Затем он проверяет, является ли вывод ADC_Channel0 или DAC_Channel0. Это ненужно и избыточно. Для DAC_Channel0 нет другого применения.

В ядре Arduino SAMD и производных ядрах «карта» выводов в variant.cpp определяет возможности выводов, используемые ядром Arduino. Это не полная копия таблицы мультиплексирования из таблицы данных. В некоторых файлах variant.cpp комментарии содержат дополнительные параметры мультиплексирования вывода.

Для ШИМ функция AnalogWrite настраивает контакт, а для SPI библиотека SPI настраивает контакт.

Если вы хотите использовать вывод для другой функции SERCOM, для настройки вывода используется функция pinPeripheral. Вот руководство.

Ядро Arduino не поддерживает конфигурацию выходного сигнала, отличного от аналоговой записи. Для настройки другого вывода волны или захвата необходима сторонняя библиотека или конфигурация прямых регистров.

Функция Arduino pinPeripheral(pin, периферийное устройство) использует отображение variant.cpp и возможные параметры:

PIO_EXTINT=0,     /* The pin is controlled by the associated signal of peripheral A. */
PIO_ANALOG,       /* The pin is controlled by the associated signal of peripheral B. */
PIO_SERCOM,       /* The pin is controlled by the associated signal of peripheral C. */
PIO_SERCOM_ALT,   /* The pin is controlled by the associated signal of peripheral D. */
PIO_TIMER,        /* The pin is controlled by the associated signal of peripheral E. */
PIO_TIMER_ALT,    /* The pin is controlled by the associated signal of peripheral F. */
PIO_COM,          /* The pin is controlled by the associated signal of peripheral G. */
PIO_AC_CLK,       /* The pin is controlled by the associated signal of peripheral H. */
PIO_DIGITAL,      /* The pin is controlled by PORT. */

Если вы хорошо разбираетесь в конфигурации Arduino variant.cpp, то для конфигурации прямого доступа к регистрам «карта» выводов из variant.cpp и функция pinPeripheral могут помочь, если вывод не должен быть жестко запрограммированным. Пример настройки периферийных устройств для «фазовой резки» с Triac в моем проекте:

const PinDescription& pinDesc = g_APinDescription[triacPin]; // Описание контакта Arduino
TCC = (Tcc*) GetTC(pinDesc.ulPWMChannel);
uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel);
bool periF = (pinDesc.ulPinAttribute & PIN_ATTR_TIMER_ALT);

// устанавливаем пин как выходной пин TCC
pinPeripheral(triacPin, periF ? PIO_TIMER_ALT : PIO_TIMER);

TCC->CC[tcChannel].reg = PULSE_PERIOD;
,

Спасибо за ваш ответ. Однако это не совсем отвечает на вопрос о том, как вариант может обойтись без указания альтернативы DAC для A0 (PA02). Например , запись A0 даже не определяет канал DAC, как это делает альтернативная запись. Если бы значение A0 было передано какой-либо функции , которая в конечном счете просматривает конфигурацию канала, оно не имело бы правильного значения., @Andrew M.

извините, я пропустил разницу ADC_Channel0/DAC_Channel0. Я расширил ответ новым первым абзацем, @Juraj

Спасибо! Небольшой побочный вопрос: каковы последствия наличия двух разных контактов на одном и том же таймере и канале? Например, на SAMD21E и PA06, и PA30 (SWCLK) имеют TCC1/WO[0] в качестве единственной опции таймера в таблице мультиплексирования SERCOM., @Andrew M.

SERCOM - это SERialCOMunication, поэтому UART, SPI, I2C. вы не можете установить два разных контакта на один и тот же таймер и канал. вы можете сопоставить их с одним и тем же таймером и каналом, но тогда их нельзя будет использовать одновременно для ШИМ, @Juraj