О системе событий ATmega32

avr events

Из моего чтения в Интернете я обнаружил, что система событий позволяет периферийным устройствам запускать друг друга без участия ЦП... система событий является программной или аппаратной? Также поддерживает ли ее ATmega32? также может ли кто-нибудь дать мне реальное приложение для системы событий?

, 👍1

Обсуждение

Где ты это прочитал? Можете дать ссылку?, @Nick Gammon

@NickGammon https://www.microchip.com/design-centers/8-bit/peripherals/core-independent/event-system, @Mohamed Mohamed

Atmega32 не указан в списке устройств для системы событий, которая находится на этом сайте., @chrisl

@chrisl, не могли бы вы привести пример системы событий?, @Mohamed Mohamed

Какой Ардуино вы используете? Этот вопрос лучше задать на веб-сайте [AVR Freaks](https://www.avrfreaks.net/), поскольку он, похоже, напрямую не связан с какой-либо Arduino как таковой., @Nick Gammon

@NickGammon Я не использую Arduino. Я использую Atmega32, @Mohamed Mohamed


2 ответа


0

У ATmega32 есть два типа связи между периферийными устройствами. функции, которые чем-то похожи на систему событий:

  • Вы можете использовать аналоговый компаратор для запуска захвата Таймер 1.
  • Вы можете использовать аналоговый компаратор, внешнее прерывание 0, таймер 0 или Таймер 1 для запуска преобразования на АЦП.

Это единственные, о которых я знаю. Как видите, это очень ограниченный функционал. Из того, что я читал, система событий выглядит как обобщение этой идеи. У вас есть много периферийных устройств, которые могут запускать события (эмиттеры событий), многие из которых могут быть вызваны такими событиями (приемники событий), и вы можете подключить любой генератор событий к любому событию получатель. Таким образом, у вас гораздо больше гибкости, чем у очень ограниченного средства связи между периферийными устройствами, предоставляемые ATmega32.

Конфигурация системы событий (подключения излучателя к приемнику) выполняется вашим программным обеспечением. Однако, как только соединение установлен, связь между периферийными устройствами полностью аппаратно и не зависит от процессора.

,

Спасибо, сэр.... Я очень благодарен..., @Mohamed Mohamed


2

"Старые" 8-битные микроконтроллеры ATmega не имеют периферийного устройства системы обработки событий. В новой «серии megaAVR 0» есть система событий. Atmega 4809 на Arduino Uno WiFi Rev2 и Nano Every — это «megaAVR 0-серии». Система событий новых ATmegas похожа на известную мне систему событий S AMD.

Микроконтроллеры ARM, например, SAMD от Atmel/Microchip, используемые в Arduino Zero и MKR, имеют систему событий. Система событий является периферией MCU. Это обеспечивает прямую связь между периферийными устройствами без участия ЦП MCU.

Периферийные устройства MCU — это то, что делает MCU MCU. Примерами периферийных устройств являются выводы GPIO, внешние прерывания, таймеры, SERCOM, сторожевой таймер...

Чтобы дать вам пример использования системы событий. Чтобы выполнить отсечку фазы переменного тока с помощью симистора, симистор должен подавать импульс в нужное время после пересечения нуля. (Он отключается при следующем пересечении нуля.) Чтобы добиться этого с помощью MCU, MCU должен воспринимать входной сигнал от схемы обнаружения пересечения нуля, затем начинать отсчитывать запрошенное время выключения, затем запускать импульс на затвор симистора, а затем останавливать импульс. .

Это может быть реализовано с помощью внешней функции прерывания для пересечения нуля, которая запускает таймер для генерации импульса на выводе волны.

В ARM MCU можно настроить систему событий для запуска таймера при внешнем прерывании по событию без функции прерывания. Тогда ЦП MCU не участвует в нарезке фаз после первоначальной настройки периферии.

После настройки входного контакта детектора пересечения нуля для внешнего прерывания без функции прерывания и настройки таймера для выполнения однократного импульса система событий повторно запускает таймер по внешнему прерыванию.

простая библиотека Arduino SAMD для модуля Triac/ZC (в разработке):

#ifndef _TRIAC_LIB_
#define _TRIAC_LIB_

namespace Triac {

const unsigned long AC_WAVE_MICROS = 10000; // при 50 Гц
const int TIMER_PRESCALER = 8;
const unsigned long PULSE_PERIOD = ((F_CPU / 1000000) * 200) / TIMER_PRESCALER;

Tcc* TCC;

void syncTCC() {
  while (TCC->SYNCBUSY.reg & TCC_SYNCBUSY_MASK);
}

void zeroCrossing() {
}


void setup(byte zcPin, byte triacPin) {

  // устанавливаем внешнее прерывание
  attachInterrupt(zcPin, zeroCrossing, RISING);
  uint8_t ulExtInt = g_APinDescription[zcPin].ulExtInt;
  EIC->EVCTRL.reg |= (1 << ulExtInt);// включить событие
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(1 << ulExtInt); // отключаем прерывание

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

  // устанавливаем пин как выходной пин TCC
  PORT->Group[pinDesc.ulPort].PINCFG[pinDesc.ulPin].bit.PMUXEN = 1;
  PORT->Group[pinDesc.ulPort].PMUX[pinDesc.ulPin >> 1].reg |= PORT_PMUX_PMUXE_F;

  // устанавливаем таймер

  REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TCC0_TCC1)); // назначаем часы
  while ( GCLK->STATUS.bit.SYNCBUSY == 1 );

  TCC->CTRLA.bit.SWRST = 1; // сброс таймера
  syncTCC();
  TCC->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; // обычный ШИМ в качестве режима вывода волны
  syncTCC();
  TCC->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT | TCC_CTRLBSET_DIR; //один выстрел и обратный отсчёт
  syncTCC();

  TCC->PER.reg = ((F_CPU / 1000000) * AC_WAVE_MICROS) / TIMER_PRESCALER; // начальное значение периода (триак выключен)
  syncTCC();
  TCC->CC[tcChannel].reg = PULSE_PERIOD; // закрепить при совпадении сравнения и выключить при 0 (таймер отсчитывает)
  syncTCC();

  TCC->EVCTRL.reg |= TCC_EVCTRL_TCEI0 | TCC_EVCTRL_EVACT0_RETRIGGER; // перезапустить по событию
  syncTCC();
  TCC->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV8 | TCC_CTRLA_ENABLE; // устанавливаем прескалер и включаем
  syncTCC();

  // система событий
  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS; // включаем его
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(EVSYS_GCLK_ID_0) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0); // назначаем часы
  while (GCLK->STATUS.bit.SYNCBUSY);

  EVSYS->CTRL.bit.SWRST = 1; // перезагрузить
  while(EVSYS->CTRL.bit.SWRST);

  EVSYS->USER.reg = EVSYS_ID_USER_TCC0_EV_0 | EVSYS_USER_CHANNEL(1); // установить пользовательское событие TCC0 0 на канале 0
  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(0) | EVSYS_CHANNEL_PATH_ASYNCHRONOUS | // канал 0 асинхронный
      EVSYS_CHANNEL_EDGSEL_FALLING_EDGE | EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_0 + ulExtInt); // источник - ext.interrupt
  while (!EVSYS->CHSTATUS.bit.USRRDY0);
}

/*
 * r is from interval <0.0, 1.0>
 */
void setPeriod(float r) {
  unsigned long period = ((F_CPU / 1000000) * ((1.0 - r) * AC_WAVE_MICROS)) / TIMER_PRESCALER;
  TCC->PER.reg = period + PULSE_PERIOD;
  syncTCC();
}

}
#endif

другой пример SAMD

,

Спасибо, сэр... Ваш ответ очень полезен..., @Mohamed Mohamed