Прерывания в Xmega

Posted by Reason89 | Posted in , ,


     В семейсте Xmega добавлена разветвленная система прерываний. Дл каждого прерывания может быть задано 4 уровня приоритета прерываний(High (высокий), Medium (средний),Low (низкий) и Off (выключенный). Плюс есть несколько не маскируемых прерываний, на вроде отказа внешней частоты.
     При поступлении запроса на обслуживание прерывания с более высоким уровнем приоритета процесс обработки прерывания с более низким уровнем приостанавливается, и процессор начинает обрабатывать более значимый запрос. Запросы на прерывание, которым присвоен статус High, обслуживаются немедленно после поступления, даже если центральный процессор сильно загружен. Чтобы не пропал ни один из запросов, и все они были обслужены, пусть даже и с задержкой есть специальная процедура Round Robin , этакий своеобразный циклический алгоритм диспетчеризации.
    Общая команда для включения всех прерываний осталась неизменной:
sei();
    Далее необходимо включить все три уровня прерываний:
PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
    Соответственно если нужно включить только низкий уровень прерываний, то код упрощается:
PMIC.CTRL |= PMIC_LOLVLEN_bm
    О более конкретной настройке PMIC.CTRL можно прочесть в мануале.
    Для всех переферийных прерываний уровень приоритета выставляется отдельно, в соответствующем регистре. В качестве примера назначи прерыванию по таймеру TCC0, самый высокий уровень прерываний:
TCC0.INTCTRLA = 0x03;
    а для внешнего прерывания на порт ввода-вывода поставим самый низкий уровень прерываний:
PORTA.INTCTRL = 0x01;
    Для каждого порта может быть объявленно только 2 прерывания, int0 и int1:
PORTA.DIR = 0x00;
PORTA.INT0MASK = 0x01;
PORTA.INT1MASK = 0x02;
    Далее для корректной работы прерываний, необходимо подтянуть вывод порта:
PORTA.PIN1CTRL= PORT_OPC_WIREDANDPULL_gc;
PORTA.PIN2CTRL= PORT_OPC_WIREDANDPULL_gc;
    Так же можно настроить по какому из фронтов будет срабатывать прерывание, в качестве примера приведем срабатывание по заднему фронту:
PORTA.PIN1CTRL = PORT_ISC_FALLING_gc;
PORTA.PIN2CTRL = PORT_ISC_FALLING_gc;
     После того, как правильно настроили работу прерываний, необходимо написать обработчки этого прерывания:
ISR(PORTA_INT0_vect)
{
   //Code
}
    В Xmega огромное количество всевозможных прерываний, как по приему и передаче данных по всевозможным протоколам, так и по переполнению и совпаднию таймеров. Гибкая настройка позволяет реализовать практически любые свои потребности.

ЦАП в XMEGA(DAC)

Posted by Reason89 | Posted in , ,

    В микроконтроллерах есть высокоскоростные 12-разрядные аналоговые модули. В дополнении к АЦП и аналоговым компараторам, есть еще и высокопроизводительные цифроаналогвые преобразователи.
    Разрядность ЦАПа XMEGA 12 бит, скорость преобразования — до 1 Мбит/с. ЦАП получает частоту с периферийной тактовой частоты, запуск на преобразование могут осуществлять различные периферийные модули, подключенные к системе событий(Event System). Есть функция формирования нулевого выходного напряжения. Обычно все ЦАПы не отличаются линейностью, когда выходное напряжение в районе нуля. Для этого в  XMEGA есть два регистра, в которые можно записывать 7-битные калибровочные данные, для более точного выставления напряжения.
     Преобразования ЦАП инициируется либо записью значения во входные регистры ЦАП, либо поступлением события от Event System. Данные для преобразования во входные регистры можно записывать как из программы, так и через DMA. Выход с ЦАП может быть выполнен двумя способами. В одном случае один линейный выход на выводе микроконтроллера. В другом два независимых выхода на двух выводах микроконтроллера. В результате два канала ЦАП могут работать независимо друг от друга и выдавать два аналоговых сигнала, различающихся как по амплитуде, так и по частоте.
    В XMEGA отдельные регистры для записи входных данных на выдачу в оба канала. Выход ЦАП можно подключать внутри кристалла к другим узлам, таким как АЦП или к компаратору.
    Привожу самый простой пример работы ЦАПа, программа для микроконтроллера atxmega32a4. Пример просто выводит на вывод микроконтроллера половину питания AVCC.
volatile int Voltage = 0x7F;

void dac_init()
{
    DACB.CTRLC = ( DACB.CTRLC & ~DAC_REFSEL_gm) | DAC_REFSEL_AVCC_gc; // Используем AVCC
    DACB.CTRLB = ( DACB.CTRLB & ~DAC_CHSEL_gm ) | DAC_CHSEL_SINGLE_gc; // Используем один канал ЦАП
    DACB.CTRLA = DAC_CH0EN_bm | DAC_ENABLE_bm;
}

void DACB_out(int Voltage)
{
   //DACB.CH0DATA = Voltage;  // Можно выводить значение из этой переменной
   DACB.CH0DATAH = 0x0F;    // А можно в ручную заполнять значения регистров
   DACB.CH0DATAL = 0xFF;
   while (!DACB.STATUS & DAC_CH0DRE_bm);
}

void dac_init();
void DACB_out(int Voltage);

int main(void)
{
    PORTB.DIR = 0xFF;//0x08;
    PORTB.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc;
    dac_init();
    
   while(1)
   {
      DACB_out(Voltage);
   }
}

    В регистре CTRLC настраивается источник опорного напряжения:
DACB.CTRLC = ( DACB.CTRLC & ~DAC_REFSEL_gm) | DAC_REFSEL_AVCC_gc;

    В регистре CTRLA необходимо разрешить канал или каналы, который мы будем использовать, и включить сам ЦАП
DACB.CTRLA = DAC_CH0EN_bm | DAC_ENABLE_bm;
     В регистре CTRLB выбирается режим, в котором будет работать ЦАП, т.е. однолинейный или двухлинейный.
DACB.CTRLB = ( DACB.CTRLB & ~DAC_CHSEL_gm ) | DAC_CHSEL_SINGLE_gc;
     Соответственно регистры в которые заносится значение. Не стоит забывать, что ЦАП 12 разрядный.
DACB.CH0DATAH = 0x0F; 
DACB.CH0DATAL = 0xFF;
     И в завершении не стоит забывать отключать от порта цифровой вывод.
PORTB.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc;

Пропадает звук в Windows при перезагрузке с Ubuntu

Posted by Reason89 | Posted in



     Держу на своем компьютере по старинке две операционки. Одна Ubuntu другая Windows, не так давно перешел с семерки на десятку.
    При перезагрузке с Ubuntu в Windows пропадает звук в наушниках. Долго рылся в настройках и параметрах, но так ничего и не нашел. Realtek корректно определяет, что наушники подключены, но звука никакого нет. При отключении наушников, встроенные колонки свободно воспроизводят звук. Откат драйверов так же не принес результатов.
    На форумах натыкался на записи, что при перезагрузке, нужно вытаскивать наушники из гнезда, и тогда при загрузке Windows звук появляется. Но у меня такая фишка не прокатила)
    Проблема кстати давольно часто появляется на ноутбуках Asus, Aser, Toshiba и.т.д.
    В итоге решение было найдено. Вроде как драйвер snd_hda_intel в Ubuntu не совсем корректно останавливают звуковую карту, и при загрузке Windows звуковая карта включается некорректно.
    Для того чтобы звук появился необходимо немного иначе перезагружать компьютер, нежели он делает это по умолчанию.
    Для этого, с правами root, редактируем файл /etc/init.d/reboot
    Находим там функцию "do_stop ()", и заменяем строчку "reboot -d -f -i", на последовательность команд:
 sync 
 echo u > /proc/sysrq-trigger 
 sleep 1s 
 echo b > /proc/sysrq-trigger 


    И собственно все, можно наслаждаться любимыми композициями.
    Небольшая подобная проблема есть и при перезагрузке с Ubuntu в Windows. Проблема в том, что при выключении Windows в версиях выше Windows 7, windows не выключается, а переходит в нечто подобное спящему режиму. А жесткие диски в таком режиме не отключаются. В результате чего, доступ к жестким дискам под Ubuntu не возможен. Нужно в настройках электропитания поставить именно выключение компьютера. А не переход в режим гибернации или еще чего.