Аппаратный шим. LaunchPad от TI. Реализация ШИМ на таймере Timer_A. Программная реализация ШИМ

Обновлено 16.12.15. Всем привет. Разобравшись в прошлой записи с памятью EEPROM, сегодня мы поговорим о том что такое ШИМ (PWM)? Расшифруется как широтно-импульсная модуляция (pulse-width modulation), это среднее значение напряжения, которое изменяется скважностью импульса. В свою очередь скважность это длительность импульса с некоторой частотой повторения. Т.е. более простыми словами все это изменение ширины импульса при неизменной их величине. Для чего это нам надо?

ШИМ (PWM) используется в транзисторной схеме для регулирования напряжения без механики, в свою очередь управление мощностью. Например управление яркостью светодиодов, управление яркостью подсветки на LCD-мониторе, управление двигателями и т.д. Если отобразить на рисунке, то выход с микроконтроллера примерно будет следующим, как на картинке ниже. Где видно что скважность это заполнение импульса, если вся ширина импульса это 5 В, то при 30% заполнении импульса, в среднем на выходе мы получим примерно 1,5В. В микроконтроллерах AVR ШИМ управление задается в восьмиразрядных таймерах/счетчиках T0/(T2) и шестнадцатиразрядный T1 (T3 в некоторых моделях). А также есть другие модели где битность ШИМа можно задавать, например ATmega 128. Рассмотрим настройку шестнадцатиразрядного таймера/счетчика Т1. Данные берем соответственно таблицам либо из справочника, либо из даташита (литература — статья №1).

В общем для такого счетчика в мк можно выбрать три режима: Fast PWM, Phase Correct PWM, Phase and Frequency Correct PWM (зависит от модели )

Рассмотрим второй режим - ШИМ с точной фазой . Здесь счетный регистр функционирует как реверсивный счетчик, изменения состояния которого изменяется от $0000 до максимального значения а затем обратно до $0000. Для управления таймером/счетчиком используем три регистра управления TCCR1A, TCCR1B, TCCR1C. В которых для выбора режима таймера/счетчика необходимо установить разряды WGMn1: WGMn0 и WGMn1: WGMn0. В зависимости от их установки максимальное значение счетчика(Разрешение ШИМ сигнала) является либо фиксированным значением, либо определяется содержимым определенных регистров таймера/счетчика. Разрешающая способность определяется выражением:

g = log (TOP+1)/log2, где ТОР – модуль счета, выбирается из таблицы соответственно разрешающей способности.

После того как определились с режимом работы таймера счетчика, необходимо выбрать режим работы блока сравнения COMnA1:COMnA0, COMnB1:COMnB0, COMnC1:COMnC0, который определяет поведение вывода OCnx при наступлении события “Совпадение”.

Ну и последний штрих определимся с частотой. Нам необходимо выставить разряды CSn2…CSn0 регистра TCCR1B, которые отвечают за определение источника тактового сигнала. Вот таким программным образом выглядит настройка ШИМ-управления на выходе OC1A. Например:

/*Настройки ШИМ */
TCCR1A=(1< /*На выводе OC1A единица, когда OCR1A==TCNT1, Сбрасывается в 0 при OCR1A==TCNT1 и устанавливается в 1 при достижении максимального значения восьми битный ШИМ Phase Correct PWM , номер режима 1 . модуль счета ТОР $00FF*/
TCCR1B=(1<OCR1A = 50; /* при модуле счета 255 и при напряжении 5 В на выходе OC1A получим примерно 1 В*/

Из программы видно, что для получения ШИМ используем регистр сравнения OCR1A. При достижении счетчиком максимального значения, в данном случае 255, происходит смена направления счета, но счетчик остается в этом состоянии в течении одного периода сигнала. В этом и заключается более медленная частота работы по сравнению с первым режимом. Но в этом и состоит симметричность изменения счетчика. Что более подходит для управления двигателем. В этом же такте происходит обновления содержимого регистра сравнения. При достижении счетчиком минимального значения также происходит смена направления счета и одновременно устанавливается флаг прерывания TOV1 регистра TIFR. Пр равенстве содержимого счетного регистра и какого-либо регистра сравнения устанавливается соответствующий флаг OCF1A/OCF1B/OCF1C регистра TIFR. Одновременно изменяется состояние выхода блока сравнения OCnx. Частота генерируемого сигнала fOCn= f/(2*N*TOP), где N – коэффициент деления пред делителя, f — частота кварца. Также можно посмотреть еще примеры настройки и использования ШИМ, например .

На этом сегодня все. В следующем посте рассмотрим контроллер любительского станка ЧПУ . Я постараюсь использовать предыдущие посты из этого блога для набора программы, как конструктор. Так будет более понятно когда один раз написали и его использовали в следующем проекте. Всем пока.

Был рассмотрен аппаратный ШИМ генератор микроконтроллера. Всё в нем хорошо, но есть несколько "но":
- аппаратный ШИМ жёстко привязан к определенным выводам МК, его невозможно переназначить на другую ногу
- количество аппаратных ШИМ каналов ограничено, их количество зависит от модели МК
- разрядность аппаратного ШИМ невозможно изменить

В этом случае может пригодиться программный метод получения ШИМ сигнала. Делается он не сложно, но требователен к частоте работы микроконтроллера и занимает достаточно много процессорного времени, в отличие от аппаратного, работающего незаметно для основной программы. Но так как применяется он, как правило, для светодиодных мигалок, то это не столь важно.

Нам необходимо в начале периода ШИМ сигнала выставлять определенную ногу МК в 1 или 0 (в зависимости от того, какой сигнал нам нужен), а потом, по достижении заданной длительности импульса, инвертировать значение ножки. Делать это удобнее всего в прерывании по переполнению. Так мы и поступим, воспользуемся прерыванием по переполнению таймера T0. Управлять будем RGB светодиодом, поэтому и названия переменных и макроопределения для портов сделаем удобочитаемыми.

/*блок дефайнов***************************************************************************************************/ #define RED PORTB.0 #define GREEN PORTB.1 #define BLUE PORTB.2 /*****************************************************************************************************************/ /*объявляем прерменные********************************************************************************************/ unsigned char red=255, green, blue; //переменные, для изменения скважности ШИМ в программе unsigned char red_b, green_b, blue_b; //переменные, для буферизации значений скважности ШИМ unsigned char count; //переменная- счетчик вызовов обработчика прерываний unsigned char temp=1; //переменная для работы алгоритма смены цветов /*****************************************************************************************************************/

Когда наступает прерывание, необходимо увеличить программный счетчик на 1 и проверить, не переполнился ли он. Если таймер переполнен, то нужно на все ножки, на которые выводится ШИМ, вывести логическую 1, а так же сохранить переменные в буфер. Переменные в буфер сохраняются для того, чтобы данные о скважности обновлялись раз в начале каждого периода, это исключает непредсказуемое поведение выхода. Далее сравниваем значение счетчика со значением буфера скважности каждого канала. Если счетчик достиг этого значения- выводим в соответствующую ногу МК логический 0.

/*обработчик прерывания*******************************************************************************************/ interrupt void timer0_ovf_isr(void) { count++; if (count == 0){ //если счетчик переполнился и принял значение 0 red_b = red; //сохранием значения в буфер green_b = green; blue_b = blue; RED =1; //выставляем ноги, отвечающие за ШИМ в логическую 1 GREEN =1; BLUE =1; } if (red_b == count) { RED = 0;} //по достижении заданной скважности выводим логический 0 в ножку МК if (green_b == count) { GREEN = 0;} if (blue_b == count) { BLUE = 0;} } /*****************************************************************************************************************/

Для демонстрации работы будем выводить на светодиод плавную смену цвета по цветам радуги (Каждый Охотник Желает Знать Где Сидит Фазан). Для этого воспользуемся нехитрым алгоритмом, который будем крутить в бесконечном цикле.

/*главная функция*************************************************************************************************/ void main(void) { PORTB=0x08; //конфигурируем порт DDRB=0x07; TCCR0=0x01; //настраиваем таймер TCNT0=0x00; TIMSK=0x01; //разрешаем генерацию прерывания по переполнению таймера T0 #asm("sei") //глобально разрешаем прерывания /*бесконечный цикл************************************************************************************************/ while (1) { if (temp==1) {if (green < 255) green += 1; else temp = 2;} if (temp==2) {if (red > 0) red -= 1; else temp = 3;} if (temp==3) {if (blue < 255) blue += 1; else temp = 4;} if (temp==4) {if (green > 0) green -= 1; else temp = 5;} if (temp==5) {if (red < 255) red += 1; else temp = 6;} if (temp==6) {if (blue > 0) blue -= 1; else temp = 1;} delay_ms(2); }; /*****************************************************************************************************************/ } /*****************************************************************************************************************/

Например);

  • резистор номиналом 190…240 Ом (вот отличный набор резисторов самых распространённых номиналов);
  • персональный компьютер со средой разработки Arduino IDE.
  • Инструкция по использованию ШИМ в Arduino

    1 Общие сведения о широтно-импульсной модуляции

    Цифровые выводы Arduino могут выдавать только два значения: логический 0 (LOW, низкий уровень) и логическую 1 (HIGH, высокий). На то они и цифровые. Но есть у Ардуино «особые» выводы, которые обозначаются PWM . Их иногда обозначают волнистой чертой "~" или обводят кружочками или ещё как-то выделяют среди прочих. PWM расшифровывается как Pulse-width modulation или широтно-импульсная модуляция , ШИМ .

    Широтно-импульсно модулированный сигнал - это импульсный сигнал постоянной частоты, но переменной скважности (соотношение длительности импульса и периода его следования). Из-за того, что большинство физических процессов в природе имеют инерцию, то резкие перепады напряжения от 1 к 0 будут сглаживаться, принимая некоторое среднее значение. С помощью задания скважности можно менять среднее напряжение на выходе ШИМ.

    Если скважность равняется 100%, то всё время на цифровом выходе Arduino будет напряжение логическая "1" или 5 вольт. Если задать скважность 50%, то половину времени на выходе будет логическая "1", а половину - логический "0", и среднее напряжение будет равняться 2,5 вольтам. Ну и так далее.


    В программе скважность задаётся не в процентах, а числом от 0 до 255. Например, команда analogWrite(10, 64) скажет микроконтроллеру подать на цифровой PWM выход №10 сигнал со скважностью 25%.

    Выводы Arduino с функцией широтно-импульсной модуляции работают на частоте около 500 Гц. Значит, период следования импульсов - около 2 миллисекунд, что и отмеряют зелёные вертикальные штрихи на рисунке.

    Получается, что мы можем сымитировать аналоговый сигнал на цифровом выходе! Интересно, правда?!

    Как же мы можем использовать ШИМ? Применений масса! Например, управлять яркостью светодиода, скоростью вращения двигателя, током транзистора, звуком из пьезоизлучателя и т.д.…

    2 Схема для демонстрации широтно-импульсной модуляции в Arduino

    Давайте рассмотрим самый базовый пример - управление яркостью светодиода с помощью ШИМ. Соберём классическую схему.


    3 Пример скетча с ШИМ

    Откроем из примеров скетч "Fade": Файл Образцы 01.Basics Fade .


    Немного изменим его и загрузим в память Arduino.

    Int ledPin = 3; // объявляем пин, управляющий светодиодом int brightness = 0; // переменная для задания яркости int fadeAmount = 5; // шаг изменения яркости void setup() { pinMode(ledPin, OUTPUT); } void loop() { analogWrite(ledPin, brightness); // устанавливаем яркость brightness на выводе ledPin brightness += fadeAmount; // изменяем значение яркости /* при достижении границ 0 или 255 меняем направление изменения яркости */ if (brightness == 0 || brightness == 255) { fadeAmount = -fadeAmount; // изменяем знак шага } delay(30); // задержка для большей видимости эффекта }

    4 Управление яркостью светодиода с помощью PWM и Arduino

    Включаем питание. Светодиод плавно наращивает яркость, а затем плавно уменьшает. Мы сымитировали аналоговый сигнал на цифровом выходе с помощью широтно-импульсной модуляции.


    Посмотрите приложенные видео, где наглядно показано изменение яркости светодиода, на подключённом осциллографе видно, как при этом меняется сигнал с Arduino.

    Рис.1

    Т = Т0+Т1 . Период импульсов

    Т = 1/F

    S = T/T1

    Duty cycle

    Коэффициент заполнения D=1/S или так D = T1/T*100%

    Цифровые устройства, например, микроконтроллер может работать только с двумя уровнями сигнала, т.е. ноль и единица или выключено и включено. Таким образом, вы можете легко использовать его для контроля состояния нагрузки, например включит или выключить светодиод. Так же вы можете использовать его для управления любым электрическим прибором, используя соответствующие драйверы (транзистор, симистор, реле и т.д.).Но иногда нужно больше, чем просто "включить" и "выключить" устройство. Поэтому, если вы хотите контролировать яркость светодиода (или лампы) или скорости двигателя постоянного тока, то цифровые сигналы просто не могу этого сделать. Эта ситуация очень часто встречается в цифровой технике и называется Широтно-Импульсной Модуляцией(PWM).

    Почти все современные микроконтроллеры имеют специализированные аппаратные средства для генерации ШИМ-сигнала. В этом уроке мы будем изучать основы техники ШИМ и в дальнейшем мы увидим, как реализовать ШИМ с помощью микроконтроллеров AVR.

    Цифровые устройства, как микроконтроллер может генерировать только два уровня на выходных линиях, высокий = 5В и низкий = 0В. Но что, если мы хотим получить 2,5 или 3,1 или любое напряжение в пределах 0-5В? Для этого, вместо создания постоянного напряжения постоянного тока на выходе мы будем генерировать меандр, который имеет высокий = 5В и низкий = 0V уровни (см. рисунок 1).

    Рис.1

    Из рисунка видно что сигнал на некоторое время остается поочередно на низком и высоком уровне. Т0 - низкий уровень, Т1 - высокий уровень. Период сигнала будет равен Т = Т0+Т1 . Период импульсов - это промежуток времени, между двумя характерными точками двух соседних импульсов. Обычно период измеряют между двух фронтов или двух спадов соседних импульсов и обозначают заглавной латинской буквой T.

    Период следования импульсов напрямую связан с частотой импульсной последовательности, и его можно вычислить по формуле: Т = 1/F

    Если длина импульса T1 точно равна половине периода T, то такой сигнал часто называют "меандр".

    Скважностью импульсов называется отношение периода следования импульсов к их длительности и обозначается буквой S: S = T/T1

    Скважность - безразмерная величина и не имеет единиц измерения, но может быть выражена в процентах. Часто в англоязычных текстах встречается термин Duty cycle , это так называемый коэффициент заполнения или величина рабочего цикла ШИМ. Коэффициент заполнения D является величиной, обратной скважности.

    Коэффициент заполнения обычно выражается в процентах и вычисляется по формуле: D=1/S или так D = T1/T*100%

    На рисунке выше (рис. 1) можно увидеть, что T1 = T0, это равно половине периода времени. Так величина рабочего цикла ШИМ составляет 50%. Если частота таких импульсов достаточно велика (скажем, 5000 Гц), то мы получаем половину от 5В т.е. 2,5В. Таким образом, если выход контроллера связан с двигателем (с помощью соответствующих драйверов) он будет работать на 50% его полной скорости. Техника ШИМ использует этот факт для создания любого напряжения между двумя уровнями (например, между 0-12В). Весь фокус в том,что при изменении величины рабочего цикла между 0-100% получаем тот же процент входного напряжения на выходе. Ниже приведены некоторые примеры ШИМ сигнала различной скважности.

    Если на выходе поставить R/С фильтр, то можно получить чистый DC уровень сигнала, а не квадратные волны. Но это не требуется для коллекторных двигателей или для управления яркостью светодиодов. Для этого можно подавать ШИМ сигнал непосредственно на драйвер (например, биполярный транзистор, MOSFET и т.д.).

    Под режимом работы 16-разр. таймера понимается его алгоритм счета и поведение связанного с ним выхода формирователя импульсов, что определяется комбинацией бит, задающих режим работы таймера (WGMn3-0) и режим формирования выходного сигнала (COMnx1:0). При этом биты задания режима формирования выходного сигнала не влияют на алгоритм счета, т.к. алгоритм счета зависит только от состояния бит задания режима работы таймера. В режимах с ШИМ биты COMnx1:0 позволяют включить/отключить инверсию на генерируемом ШИМ-выходе (т.е. выбрать ШИМ с инверсией или ШИМ без инверсии). Для режимов без ШИМ биты COMnx1:0 определяют, какое действие необходимо выполнить при возникновении совпадения: сбросить, установить или инвертировать выход (см. также “Блок формирования выходного сигнала” и "Временные диаграммы 16-разр. таймеров-счетчиков").

    Нормальный режим работы

    Самым простым режимом работы является нормальный режим (WGMn3-0 = 0b0000). В данном режиме счетчик работает как суммирующий (инкрементирующий), при этом сброс счетчика не выполняется. Переполнение счетчика происходит при переходе через максимальное 16-разр. значение (0xFFFF) к нижнему пределу счета (0x0000). В нормальном режиме работы флаг переполнения таймера-счетчика TOVn будет установлен на том же такте синхронизации, когда TCNTn примет нулевое значение.

    Фактически, флаг переполнения TOVn является 17-ым битом таймера-счетчика за тем исключением, что он только устанавливается и не сбрасывается. Однако программно это свойство может быть использовано для повышения разрешающей способности таймера, если использовать прерывание по переполнению таймера, при возникновении которого флаг TOVn сбрасывается автоматически. Для нормального режима работы не существует каких-либо особых ситуаций, поэтому запись нового состояния счетчика может быть выполнена в любой момент.

    В нормальном режиме можно использовать блок захвата. Однако при этом следует соблюдать, чтобы максимальный интервал времени между возникновениями внешних событий не превысил периода переполнения счетчика. Если такое условие не соблюдается, необходимо использовать прерывание по переполнению таймера-счетчика или предделитель.

    Блок сравнения может использоваться для генерации прерываний. Не рекомендуется использовать выход OCnx для генерации сигналов в нормальном режиме работы, т.к. в этом случае будет затрачена значительная часть процессорного времени.

    Режим сброса таймера при совпадении (СТС)

    В режиме СТС (WGM01, WGM00 =0b10) регистр OCR0 используется для задания разрешающей способности счетчика. Если задан режим CTC и значение счетчика (TCNT0) совпадает со значением регистра OCR0, то счетчик обнуляется (TCNT0=0). Таким образом, OCR0 задает вершину счета счетчика, а, следовательно, и его разрешающую способность. В данном режиме обеспечивается более широкий диапазон регулировки частоты генерируемых прямоугольных импульсов. Он также упрощает работу счетчика внешних событий.

    В режиме сброса таймера при совпадении (WGMn3-0 = 0b0100 или 0b1100) разрешающая способность таймера задается регистрами OCRnA или ICRn. В режиме СТС происходит сброс счетчика (TCNTn), если его значение совпадает со значением регистра OCRnA (WGMn3-0 = 0b0100) или с ICRn (WGMn3-0 = 0b1100). Значение регистра OCRnA или ICRn определяет верхний предел счета, а, следовательно, и разрешающую способность таймера. В данном режиме обеспечивается более широкий диапазон регулировки частоты генерируемых прямоугольных импульсов. Он также упрощает работу счетчика внешних событий. Временная диаграмма работы таймера в режиме СТС показана на рисунке 1. Счетчик (TCNTn) инкрементирует свое состояние до тех пор, пока не возникнет совпадение со значением OCRnA или ICRn, а затем счетчик (TCNTn) сбрасывается.

    Рисунок 1 – Временная диаграмма для режима СТС

    По достижении верхнего предела счета может генерироваться прерывание с помощью флагов OCFnA или ICFn, соответствующим используемым регистрам для задания верхнего предела счета. Если прерывание разрешено, то процедура обработки прерывания может использоваться для обновления верхнего предела счета. Однако, задание значения вершины счета близкого к значению нижнего предела счета, когда счетчик работает без предделения или с малым значением предделения, необходимо выполнять с особой осторожностью, т.к. в режиме СТС нет двойной буферизации. Если значение, записанное в OCRnA или ICRn, меньше текущего значения TCNTn, то сброс счетчика по условию совпадения наступит, когда он достигнет максимального значения (0xFFFF), затем перейдет в исходное состояние 0x0000 и достигнет нового значения OCRnA или ICRn. Во многих случаях возникновение такой ситуации не желательно. В качестве альтернативы может выступить режим быстрой ШИМ, где регистр OCRnA определяет верхний предел счета (WGMn3-0 = 0b1111), т.к. в этом случае OCRnA имеет двойную буферизацию.

    Для генерации сигнала в режиме CTC выход OCnA может использоваться для изменения логического уровня при каждом совпадении, для чего необходимо задать режим переключения (COMnA1, COMnA0 = 0b01). Значение OCnA будет присутствовать на выводе порта, только если для данного вывода задано выходное направление. Максимальная частота генерируемого сигнала равна fOC0 = fclk_I/O/2, если OCRnA = 0x0000. Для других значений OCRn частоту генерируемого сигнала можно определить по формуле:

    где переменная N задает коэффициент деления предделителя (1, 8, 32, 64, 128, 256 или 1024).

    Также как и для нормального режима работы, флаг TOV0 устанавливается на том же такте таймера, когда его значение изменяется с 0xFFFF на 0x0000.

    Режим быстрой ШИМ (FAST PWM)

    Режим быстрой широтно-импульсной модуляции (ШИМ) (WGMn3-0 = 0b0101, 0b0110, 0b0111, 0b1110, 0b1111) предназначен для генерации ШИМ-импульсов повышенной частоты. В отличие от других режимов работы в этом используется однонаправленная работа счетчика. Счет выполняется в направлении от нижнего к верхнему пределу счета.

    Если задан неинвертирующий режим выхода, то при совпадении TCNTn и OCRnx сигнал OCnx устанавливается, а на верхнем пределе счета сбрасывается. Если задан инвертирующий режим, то выход OCnx сбрасывается при совпадении и устанавливается на верхнем пределе счета. За счет однонаправленности счета, рабочая частота для данного режима в два раза выше по сравнению с режимом ШИМ с фазовой коррекцией, где используется двунаправленный счет. Возможность генерации высокочастотных ШИМ сигналов делает использование данного режима полезным в задачах стабилизации питания, выпрямления и цифро-аналогового преобразования. Высокая частота, при этом, позволяет использовать внешние элементы физически малых размеров (индуктивности, конденсаторы), тем самым снижая общую стоимость системы.

    Разрешающая способность ШИМ может быть фиксированной 8, 9 или 10 разрядов или задаваться регистром ICRn или OCRnA, но не менее 2 разрядов (ICRn или OCRnA = 0x0003) и не более 16 разрядов (ICRn или OCRnA = 0xFFFF). Разрешающая способность ШИМ при заданном значении верхнего предела (ВП) вычисляется следующим образом:

    В режиме быстрой ШИМ счетчик инкрементируется до совпадения его значения с одним из фиксированных значений 0x00FF, 0x01FF или 0x03FF (если WGMn3:0 = 0b0101, 0b0110 или 0b0111, соответственно), значением в ICRn (если WGMn3:0 = 0b1110) или значением в OCRnA (если WGMn3:0 = 0b1111), а затем сбрасывается следующим тактом синхронизации таймера. Временная диаграмма для режима быстрой ШИМ представлена на рисунке 2. На рисунке показан режим быстрой ШИМ, когда для задания верхнего предела используется регистр OCRnA или ICRn. Значение TCNTn на временной диаграмме показано в виде графика функции для иллюстрации однонаправленности счета. На диаграмме показаны как инвертированный, так и неинвертированный ШИМ-выходы. Короткой горизонтальной линией показаны точки на графике TCNTn, где совпадают значения OCRnx и TCNTnx. Флаг прерывания OCnx устанавливается при возникновении совпадении.

    Рисунок 2 – Временная диаграмма для режима быстрой ШИМ

    Флаг переполнения таймера-счетчика (TOVn) устанавливается всякий раз, когда счетчик достигает верхнего предела. Дополнительно тем же тактовым импульсом вместе с флагом TOVn могут установиться флаги OCnA или ICFn, если для задания верхнего предела используется регистр OCRnA или ICRn, соответственно. Если одно из этих прерываний разрешено, то в процедуре обработки прерывания может быть выполнено обновление верхнего предела счета и порогов сравнения.

    Если изменяется значение верхнего предела счета, то необходимо соблюдение условия, чтобы записываемое новое значение верхнего предела было больше или равно значений во всех регистрах порога сравнения. В противном случае совпадение между TCNTn и OCRnx никогда не возникнет. Обратите внимание, что при использовании фиксированных значений верхнего предела во время записи в регистры OCRnx происходит маскирование к 0 неиспользуемых разрядов.

    Механизм модификации регистра ICRn отличается от OCRnA в том случае, если он используется для задания верхнего предела. Регистр ICRn не имеет двойной буферизации. Это означает, что если в ICRn записывается малое значение во время работы счетчика с малым предделением или без него, то имеется опасность записи в регистр ICRn значения, которое окажется меньше текущего значения TCNTn. Как результат, в такой ситуации будет пропущено совпадение на вершине счета. В этом случае счетчик дойдет до максимального значения (0xFFFF), перезапустится со значения 0x0000, а только затем возникнет совпадение. Регистр OCRnA содержит схему двойной буферизации, поэтому, его можно модифицировать в любой момент времени.

    class="eliadunit">

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

    Рекомендуется использовать регистр ICRn для задания верхнего предела, если верхний предел счета является константой. В этом случае также освобождается регистр OCRnA для генерации ШИМ-сигнала на выходе OCnA. Однако, если частота ШИМ динамически изменяется (за счет изменения верхнего предела), то в этом случае выгоднее использовать регистр OCRnA для задания верхнего предела, т.к. он поддерживает двойную буферизацию.

    В режиме быстрой ШИМ блоки сравнения позволяют генерировать ШИМ-сигналы на выводах OCnx. Если COMnx1:0 =0b10, то задается ШИМ без инверсии выхода, а если COMnx1:0 = 0b11, то задается режим ШИМ с инверсией на выходе (см. таблицу 59). Фактическое значение OCnx можно наблюдать на выводе порта, если для него задано выходное направление (DDR_OCnx). ШИМ-сигнал генерируется путем установки (сброса) регистра OCnx при возникновении совпадения между OCRnx и TCNTn, а также путем сброса (установки) регистра OCnx вместе со сбросом счетчика (переход с верхнего предела на нижний предел).

    Частота ШИМ выходного сигнала для заданного значения верхнего предела (ВП) определяется выражением:

    где N – переменная, которая задает значение коэффициента предделения (1, 8, 32, 64, 128, 256 или 1024).

    Запись предельных значений в регистр OCRnx связана с особыми случаями в генерации ШИМ-импульсов. Если OCRnx установить равным нижнему пределу (0x0000), то на выходе будет возникать короткий импульс каждый (ВП+1)-ый такт синхронизации таймера. Запись в OCRnx значения равного верхнему пределу приведет к установке постоянного уровня лог. 1 или 0 на выходе (зависит от выбранной с помощью бит COMnx1:0 полярности выходного сигнала).

    Если требуется генерация меандра (прямоугольные импульсы со скважностью 2 или заполнением 50%) высокой частоты, то необходимо использовать режим быстрой ШИМ с установкой бит COMnA1:0 = 0b01, которая вызывает переключение (инвертирование) логического уровня на выходе OCnA при каждом совпадении. Данное применимо, только если OCRnA используется для задания верхнего предела (WGMn3-0 =0b1111). Максимальная генерируемая частота меандра в этом случае fOCnA = fclk_I/O/2, если OCRnA =0x0000. Данная особенность аналогична переключению OCnA в режиме СТС за исключением двойной буферизации, которая имеется в режиме быстрой ШИМ.

    Режим широтно-импульсной модуляции с фазовой коррекцией (Phase Correct)

    Режим широтно-импульсной модуляции с фазовой коррекцией (ШИМ ФК) (WGMn3-0 = 0b0001, 0b010, 0b0011, 0b1010 или 0b1011) предназначен для генерации ШИМ сигнала с фазовой коррекцией и высокой разрешающей способностью. Режим ШИМ ФК основан на двунаправленной работе таймера-счетчика. Счетчик циклически выполняет счет в направлении от нижнего предела (0x0000) до верхнего предела, а затем обратно от верхнего предела к нижнему пределу. Если задан неинвертирующий режим выхода формирователя импульсов, то выход OCnx сбрасывается/устанавливается при совпадении значений TCNTn и OCRnx во время прямого/обратного счета. Если задан инвертирующий режим выхода, то, наоборот, во время прямого счета происходит установка, а во время обратного – сброс выхода OCnx. При двунаправленной работе максимальная частота ШИМ-сигнала меньше, чем при однонаправленной работе, однако, за счет такой особенности, как симметричность в режимах ШИМ с двунаправленной работой, данные режимы предпочитают использовать при решении задач управления приводами.

    Разрешающая способность ШИМ в данном режиме может быть либо фиксированной (8, 9 или 10 разрядов) либо задаваться с помощью регистра ICRn или OCRnA. Минимальная разрешающая способность равна 2-м разрядам (ICRn или OCRnA = 0x0003), а максимальная -16-ти разрядам (ICRn или OCRnA =0xFFFF). Если задан верхний предел, то разрешающая способность ШИМ в данном режиме определяется следующим образом:

    В режиме ШИМ ФК счетчик инкрементируется пока не достигнет одного из фиксированных значений 0x00FF, 0x01FF или 0x03FF (соответственно для WGMn3-0 = 0b0001, 0b0010 или 0b0011), а также значения равного ICRn (если WGMn3-0 = 0b1010) или OCRnA (если WGMn3:0 = 0b1011). Далее, при достижении верхнего предела, счетчик изменяет направление счета. Значение TCNTn остается равным верхнему пределу в течение одного такта синхронизации таймера. Временная диаграмма для режима ШИМ ФК представлена на рисунке 3. На рисунке показан режим ШИМ ФК с использованием регистра OCRnA или ICRn для задания верхнего предела. Состояние TCNTn представлено в виде графика функции для иллюстрации двунаправленности счета. На рисунке представлены, как неинвертированный, так и инвертированный ШИМ-выход. Короткие горизонтальные линии указывают точки на графике изменения TCNTn, где возникает совпадение со значением OCRnx. Флаг прерывания OCnx устанавливается при возникновении совпадения.

    Рисунок 3 – Временная диаграмма для режима ШИМ ФК

    Флаг переполнения таймера-счетчика (TOVn) устанавливается всякий раз, когда счетчик достигает нижнего предела. Если для задания верхнего предела используется регистр OCRnA или ICRn, то, соответственно устанавливается флаг OCnA или ICFn тем же тактовым импульсом, на котором произошло обновление регистра OCRnx из буферного регистра (на вершине счета). Флаги прерывания могут использоваться для генерации прерывания по достижении счетчиком нижнего или верхнего предела.

    При изменении значения верхнего предела счета необходимо следить, чтобы оно было больше или равно значениям во всех регистрах сравнения. В противном случае совпадение между TCNTn и OCRnx никогда не возникнет. Обратите внимание, что при использовании фиксированных значений верхнего предела счета во время записи в регистры OCRnx неиспользуемые разряды обнуляются. Третий период на рисунке 53 иллюстрирует случай, когда динамическое изменение верхнего предела счета приводит к генерации несимметричного импульса. Данная особенность основывается на времени обновления регистра OCRnx. Поскольку, обновление OCRnx возникает на вершине счета, то и период ШИМ начинается и заканчивается на вершине счета. Это подразумевает, что длительность обратного счета определяется предыдущим значением верхнего предела, а прямого – новым значением верхнего предела. Если два этих значения разные, то и длительность прямого и обратного счета будет также отличаться. Различие в длительности приводит несимметричности выходных импульсов.

    Если стоит задача изменения верхнего предела при работающем счетчике, то вместо этого режима рекомендуется использовать режим ШИМ ФЧК (фазовая и частотная коррекция). Если используется статическое значение верхнего предела, то между данными режимами практически нет отличий.

    В режиме ШИМ ФК блоки сравнения позволяют генерировать ШИМ-сигналы на выводах OCnx. Если установить COMnx1:0 = 0b10, то выход ШИМ будет без инверсии, а если COMnx1:0=0b11, то с инверсией. Фактическое значение OCnx можно наблюдать на выводе порта, если в регистре направления данных для данного вывода порта задано выходное направление (DDR_OCnx). ШИМ-сигнал генерируется путем установки (сброса) регистра OCnx при совпадении значений OCRnx и TCNTn во время прямого счета, а также путем сброса (установки) регистра OCnx при совпадении между OCRnx и TCNTn во время обратного счета. Результирующая частота ШИМ-сигнала в режиме ШИМ ФК при заданном верхнем пределе (ВП) может быть вычислена по следующему выражению:

    Запись предельных значений в регистр OCRnx связано с особыми случаями в генерации ШИМ-сигналов в режиме ШИМ ФК. Если задать режим ШИМ без инверсии и OCRnx установить равным нижнему пределу, то на выходе непрерывно будет установлен лог. 0, а если равным верхнему пределу, то на выходе постоянно присутствует лог. 1. Для ШИМ с инверсией указанные уровни необходимо заменить противоположными.

    Если задать использование OCnA в качестве верхнего предела (WGMn3:0 = 0b1011) и установить COMnA1:0 =0b01, то на выходе OCnA будет генерироваться меандр.

    Режим широтно-импульсной модуляции с фазовой и частотной коррекцией (Phase and Frequency Correct)

    Режим широтно-импульсной модуляции с фазовой и частотной коррекцией (ШИМ ФЧК) (WGMn3-0 = 0b1000 или 0b1001) предназначен для генерации ШИМ-импульсов высокой разрешающей способности с фазовой и частотной коррекцией. Также как и режим ШИМ ФК режим ШИМ ФЧК основан на двунаправленной работе счетчика. Счетчик циклически считает от нижнего предела (0x0000) до верхнего предела, а затем обратно от верхнего предела к нижнему пределу. Если задан неинвертирующий режим ШИМ, то выход OCnx сбрасывается, если возникает совпадение между TCNTn и OCRnx во время прямого счета, и устанавливается, если возникает совпадение во время обратного счета. В инвертирующем режиме работа инверсная. Двунаправленная работа, по сравнению с однонаправленной, связана с генерацией более низких частот. Однако, благодаря симметричности в режимах ШИМ с двунаправленным счетом, их применение предпочтительно в задачах управления приводами.

    Основное отличие между режимами ШИМ ФК и ШИМ ФЧК состоит в моменте обновления регистра OCRnx из буферного регистра OCRnx (см. рисунок 3 и рисунок 4).

    Разрешающая способность ШИМ в этом режиме может задаваться с помощью регистра ICRn или OCRnA. Минимальная разрешающая способность равна 2-ум разрядам (ICRn или OCRnA = 0x0003), а максимальная разрешающая способность - 16-ти разрядам (ICRn или OCRnA = 0xFFFF). Разрешающая способность ШИМ в разрядах может быть вычислена по следующему выражению:

    В режиме ШИМ ФЧК счетчик инкрементируется до совпадения со значением в ICRn (WGMn3:0 = 0b1000) или в OCRnA (WGMn3:0 = 0b1001). Это означает достижение вершины счета, после чего происходит изменение направления счета. Значение TCNTn остается равным вершине счета в течение одного такта синхронизации таймера. Временная диаграмма для режима ШИМ ФЧК показана на рисунке 54. На рисунке показан режим ШИМ ФЧК, когда вершину счета задает регистр OCRnA или ICRn. Значение TCNTn показано в виде графика функции для иллюстрации двунаправленности счета. На диаграмме показан как неинвертирующий, так и инвертирующий ШИМ выходы. Короткие горизонтальные линии указывают на точки график TCNTn, где возникает совпадение между OCRnx и TCNTn. Флаг прерывания OCnx устанавливается после возникновения совпадения.

    Рисунок 4 – Временная диаграмма режима ШИМ с фазовой и частотной коррекцией

    Флаг переполнения таймера-счетчика (TOVn) устанавливается тем же тактом, когда произошло обновление регистров значением из буферного регистра (на нижнем пределе счета). Если для задания верхнего предела используется регистр OCRnA или ICRn, то по достижении счетчиком верхнего предела устанавливается флаг OCnA или ICFn, соответственно. Флаги прерывания могут использоваться для генерации прерывания при достижении счетчиком верхнего или нижнего предела.

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

    На рисунке 4 показано, что в отличие от режима ШИМ ФК, генерируемый выходной сигнал симметричен на всех периодах. Поскольку, регистры OCRnx обновляются на нижнем пределе счета, то длительности прямого и обратного счетов всегда равны. В результате выходные импульсы имеют симметричную форму, а, следовательно, и откорректированную частоту.

    Использование регистра ICRn для задания верхнего предела рекомендуется, если значение верхнего предела является константой. В этом случае также освобождается регистр OCRnA для широтно-импульсной модуляции импульсов на выводе OCnA. Однако если требуется динамическое изменение частоты ШИМ за счет изменения верхнего предела, то для задания верхнего предела рекомендуется использовать регистр OCRnA за счет наличия у него двойной буферизации.

    В режиме ШИМ ФЧК блоки сравнения позволяют генерировать ШИМ-импульсы на выводе OCnx. Если COMnx1:0 = 0b10, то задается неинвертирующий ШИМ выход, а, если COMnx1:0=0b11, то инвертирующий (см. таблицу 60). Значение OCnx будет присутствовать на соответствующем выводе порта только в случае, если для него задано выходное направление. ШИМ сигнал генерируется путем установки (сброса) регистра OCnx при совпадении между OCRnx и TCNTn во время прямого счета и сброса (установки) регистра OCnx при совпадении между OCRnx и TCNTn во время обратного счета. Частота ШИМ в данном режиме при заданном верхнем пределе (ВП) счета определяется следующим образом:

    где N – коэффициент деления предделителя (1, 8, 32, 64, 128, 256 или 1024).

    Запись предельных значений в регистр OCRnx связана с особыми случаями в генерации ШИМ-сигналов в данном режиме. Если задать OCRnx равным нижнему пределу (0x0000), то в неинвертирующем режиме на выходе будет постоянного присутствовать низкий логический уровень, а при записи значения равного верхнему пределу на выходе будет длительно присутствовать высокий логический уровень. В инвертирующем режиме приведенные уровни будут противоположными.

    Если OCRnA используется для задания верхнего предела (WGMn3:0 = 0b1001) и COMnA1:0 = 0b01, то на выходе OCnA будет генерироваться меандр.

    Аппаратная реализация ШИМ дает безусловные преимущества перед программной,так как разгружает процессор как лишним и громоздким кодом, так и временем на его обслуживание, а также дает больше возможностей использования работы с ШИМ. Достаточно провести инициализацию таймер/счетчика (занести необходимые значения в регистры используемые таймер/счетчиком) как таймер/счетчик может работать независимо от процессора, соответственно процессор может заниматься другими задачами,только иногда обращаясь в необходимый момент для корректировки или изменения режима или получения результатов от таймер/счетчика.

    Описание флагов прерываний

    T1 может генерировать прерывание при наступлении:

    1. переполнения счетного регистра TCNT1;
    2. при равенстве счетного регистра TCNT1 и регистра сравнения OCR1A и OCR1B (по отдельности для каждого регистра);
    3. при сохранении счетного регистра в регистре захвата ICR1.

    T2 может генерировать прерывание при наступлении:

    1. переполнения счетного регистра TCNT2;
    2. при равенстве счетного регистра TCNT2 и регистра сравнения OCR2.

    Флаги всех прерываний находится в регистре TIFR,а разрешение/запрещение прерываний в регистре TIMSK.

    Разряды регистра TIMSK
    Регистр 7 6 5 4 3 2 1 0
    TIMSK OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0* TOIE0
    • OCIE2 - Флаг разрешения прерывания по событию "совпадение" таймера/счетчика Т2
    • TOIE2 - Флаг разрешения прерывания по переполнению таймера/счетчика Т2
    • TICIE1 - Флаг разрешения прерывания по событию "захват" таймера/счетчика Т1
    • OCIE1A - Флаг разрешения прерывания по событию "совпадение А" таймера/счетчика Т1
    • OCIE1B - Флаг разрешения прерывания по событию "совпадение В" таймера/счетчика Т1
    • TOIE1 - Флаг разрешения прерывания по переполнению таймера/счетчика Т1
    • OCIE0* - Флаг разрешения прерывания по событию "совпадение" таймера/счетчика Т0 (* - отсутствует в ATmega8)
    • TOIE0 - Флаг разрешения прерывания по переполнению таймера/счетчика Т0
    • OCF2 - Флаг прерывания по событию "совпадение" таймера/счетчика Т2
    • TOV2 - Флаг прерывания по переполнению таймера/счетчика Т2
    • ICF1 - Флаг прерывания по событию "захват" таймера/счетчика Т1
    • OCF1A - Флаг прерывания по событию "совпадение А" таймера/счетчика Т1
    • OCF1B - Флаг прерывания по событию "совпадение В" таймера/счетчика Т1
    • TOV1 - Флаг прерывания по переполнению таймера/счетчика Т1
    • OCF0 - Флаг прерывания по событию "совпадение" таймера/счетчика Т0
    • TOV0 - Флаг прерывания по переполнению таймера/счетчика Т0

    Описание работы тайтер/счетчика Т1 в контроллере ATmega8/16

    Шеснадцатиразрядный таймер/счетчик Т1 может использоватся для формирования временных интервалов, подсчета количества внешних сигналов, и для генерации сигналов с ШИМ разной скважности и длительности на выводах OC1A и OC1B. Кроме того по внешнему сигналу с вывода ICP1 или от аналогового компаратора, Т1 может сохранять свое текущее состояние в отдельном регистре захвата ICR1.

    Разряды регистров TCCR1A:TCC1B:TCNT1:OCR1A:OCR1B:ICR1
    Регистр 7 6 5 4 3 2 1 0
    TCCR1A COM1A1 COM1A0 COM1B1 COM1BO FOC1A FOC1B WGM11 WGM10
    TCCR1B ICNC1 ICES1 * WGM13 WGM12 CS12 CS11 CS10
    TCNT1:H R/W R/W R/W R/W R/W R/W R/W R/W
    TCNT1:L R/W R/W R/W R/W R/W R/W R/W R/W
    OCR1A:H R/W R/W R/W R/W R/W R/W R/W R/W
    OCR1A:L R/W R/W R/W R/W R/W R/W R/W R/W
    OCR1B:H R/W R/W R/W R/W R/W R/W R/W R/W
    OCR1B:L R/W R/W R/W R/W R/W R/W R/W R/W
    ICR1:H R/W R/W R/W R/W R/W R/W R/W R/W
    ICR1:L R/W R/W R/W R/W R/W R/W R/W R/W

    Каждый 16-разрядный регистр физически размещается в двух 8-разрядных регистрах поэтому при чтении записи в них нужно выполнить две операции. При записи первым загружается старший байт потом младший,при чтении наоборот сначала младший прочитывается потом старший.

    TCCR1A:TCCR1B - 8-разрядные регистры управления таймером/счетчиком Т1

    TCNT1 - 16-разрядный счетный регистр таймера/счетчика Т1. Взависимости от режима работы содержимое этого регистра обнуляется,инкрементируется(увеличивается значение на 1) или декрементируется(уменьшается значение на 1) по каждому импульсу тактового сигнала таймера/счетчика.

    OCR1A:OCR1B - 16-разрядные регистры сравнения

    ICR1 - 16-разрядный регистр захвата,сохраняет значение TCNT1 при подаче активного фронта сигнала на вывод ICP1 или по сигналу от компаратора.

    Назначение битов

    COM1A1:COM1A0:COM1B1:COM1B0 - Эти разряды определяют поведение вывода OC1A:OC1B при совпадении значения счетного регистра TCNT1 и регистра сравнения OCR1A:OCR1B

    FOC1A:FOC1B - Эти разряды служат для прнудительного изменения состояния вывода OC1A:OC1B

    ICNC1 - Разряд управления схемой помех,если бит равен "0" захват будет по первому активному фронту, если "1" захват будет после четвертой одинаковой выборки сигнала захвата.

    ICES1 - Разряд выбора активного фронта сигнала,если его значение равно "0", сохранение счетного регистра TCNT1 в регистре захвата OCR1 будет по спадающему фронту сигнала, если "1" по нарастающему.

    WGM13:WGM12:WGM11:WGM10 - Эти разряды определяют режим работы таймера/счетчика Т1

    CS22:CS21:C20 - Разряды, определяющие источник тактового сигнала таймера/счетчика Т1.

    Выбор режима работы таймера/счетчика Т1
    WGM13 WGM12 WGM11 WGM10 Режим работы Модуль счета (TOP)
    0 0 0 0 Normal $FFFF
    0 0 0 1 Phase correct PWM

    8-разрядный

    $00FF
    0 0 1 0 Phase correct PWM

    9-разрядный

    $01FF
    0 0 1 1 Phase correct PWM

    10-разрядный

    $03FF
    0 1 0 0 CTC (сброс при совпадении) OCR1A
    0 1 0 1 Fast PWM

    8-разрядный

    $00FF
    0 1 1 0 Fast PWM

    9-разрядный

    $01FF
    0 1 1 1 Fast PWM

    10-разрядный

    $03FF
    1 0 0 0 ICR1
    1 0 0 1 Phase and Freguensy Correct PWM OCR1A
    1 0 1 0 Phase correct PWM ICR1
    1 0 1 1 Phase correct PWM OCR1A
    1 1 0 0 CTC (сброс при совпадении) ICR1
    1 1 0 1 Зарезервировано *
    1 1 1 0 Fast PWM ICR1
    1 1 1 1 Fast PWM OCR1A

    Выбор источника тактового сигнала

    Режим Normal

    Самый простой режим работы Т1. По каждому импульсу тактового сигнала происходит инкремент счетного регистра TCNT1 (увеличение значения на 1). При переходе через значение $FFFF модуля счета (ТОР) возникает переполнение и вследующем такте начинается счет со значения $0000, в этот же момент устанавливается флаг TOV1=1 в регистре TIFR, и может быть сгенерировано прерывание если установлен флаг TOIE1=1 в регистре TIMSK. Для того, чтобы сгенерировать сигна заданной частоты в этом режиме необходимо записать в разряды COM1A1=0:COM1A0=1 для вывода OC1A или COM1B1=0:COM1B0=1 для вывода OC1B контроллера.

    Кроме того по каждому такту происходит сравнение счетного регистра TCNT1 и регистра сравнения OCR1A:OCR1B, при совпадении устанавливается флаг прерывания OCF1A=1:OCF1B=1 и если разряд OCIE1A=1:OCIE1B=1 регистра TIMSK генерируется прерывание. В тот же момент может быть изменено состояние вывода OC1A:OC1B в зависимости от установок битов COM1A1:COM1A0:COM1B1:COM1B0.

    Режим СТС (сброс при совпадении)

    В этом режиме Т1 работает по такому же принципу как и в режиме Normal. Отличие заключается в том, что максимально возможное значение счетного регистра TCNT1 ограничивается значением регистра сравнения OCR1A или ICR1 (смотрите таблицу выбора режима таймер/счетчика). При достижении TCNT1 значения OCR1A или ICR1, значение TCNT1 обнуляется в TCNT1=$0000 В этот же момент устанавливается флаг TOV1=1 COM1A1:COM1A0:COM1B1:COM1B0 Опрелеляют поведение вывода ОС1A:OC1B при совпадении.

    Режим Fast PWM (быстродействующий ШИМ)

    С помощью этого режима можно генерировать высокочастотный сигал ШИМ. Принцип и порядок работы не отличается от режима Normal, кроме наличия двойной буферизации регистра OCR1A:OCR1B, благодаря которому исключается появление несиметричных импульсов сигнала, а также отличается поведением выводов ОС1A:OC1B (смотрите таблицу).


    Режим Phase Correct PWM (ШИМ с точной фазой)

    Отличие этого режима от предыдущих заключается в том, что счетный регистр работает как реверсивный счетчик. Так как этот режим рекомендуется Atmel как наиболее подходящий для регулировки двигателей, мы его рассмотрим наиболее подробно. При достижении счетным регистром TCNT1 значения модуля счета (ТОР) (или значения регистра ICR1 или значения регистра OCR1A, смотрите таблицу выбора режима таймер/счетчика), происходит изменение направления счета. При достижении счетным регистром TCNT1 минимального значения ($0000) также происходит изменение направления счета и в тот же момент устанавливается флаг прерывания TOV1 регистра TIFR. Так же при равенстве содержимого счетного регистра TCNT1 и регистра сравнения OCR1A:OCR1B ,устанавливается флаг OCF1A:OCF1B регистра TIFR и изменяется состояние вывода OC1A:OC1B,согласно таблице.

    Во избежание несимметричных выбросов во время записи значения в регистр OCR1A:OCR1B, в этом режиме реализована двойная буферизация записи. Благодаря этому действительное изменение значения регистра изменяется в момент достижения счетным регистром TCNT1 значения модуля счета (ТОР) (или значения регистра ICR1 или значения регистра OCR1A смотрите таблицу выбора режима таймер/счетчика). Поэтому в самом начале, при инициализации таймер/счетчика вывод ОС1A:OC1B не изменит свое состояние при совпадении до тех пор, пока регистр не достигнет значения (ТОР).

    Задача: Разработаем программу управления яркостью лампы накаливания на 12 Вольт при помощи ШИМ. При нажатии на кнопку «Больше» яркость лампы увеличивается, при нажатии на кнопку «Меньше» яркость уменьшается. Схема нашего будущего устройства показана на рисунке. Как обычно используем микроконтроллер Atmega8, который будет тактироваться от внутреннего генератора частотой 4MHz. Собственно у нас получится диммер, эти устройства предназначены для регулировки яркости осветительных приборов. Сейчас наибольшее распространение получили светодиодные диммеры.

    Для простоты к нашей схеме можно тоже подключить светодиод, но с лампочкой будет нагляднее. Кнопки подключены к выводам PD0 , PD1 . Нагрузку подключаем к выводу PB1(OC1A) через резистор и полевой транзистор MOSFET, который и будет работать у нас в качестве ключа (в ключевом режиме). Полевой транзистор предпочтительней потому, что его затвор изолирован от силовой схемы и управление производится электрическим полем, а ток управления достигает микроампер. Это позволяет, используя один-два транзистора, управлять нагрузкой огромной мощности (до десятков ампер и десятков-сотен вольт), не нагружая микроконтроллер. Учитывая также тот факт, что полевые транзисторы можно соединять параллельно (в отличие от биполярных), возможно получить еще более мощный каскад на сотни ампер.

    Теперь разберемся, как микроконтроллер реализует ШИМ и напишем программу. Как уже говорилось ранее, в нашем МК есть 3 таймера, и все они могут работать в ШИМ-режиме. Мы будем работать с шестнадцатиразрядным таймером/счетчиком. Битами WGM13-10 настроим наш таймер на работу FastPWM с верхним пределом счета ICR1 . Принцип программы такой, наш таймер считает от 0 до 65535(0xFFFF), в регистр ICR1 впишем число 255, это будет верхний предел счета таймера(TOP), частота ШИМ сигнала у нас будет постоянной. Также наш таймер настроен на то, что при совпадении счетного регистра и регистра сравнения (TCNT1 = OCR1A) будет переключатся вывод контроллера OC1A . Коэффициент заполнения ШИМ можно изменить, записав в регистр сравнения OCR1A определенное число от 0 до 255, чем больше это число тем больше будет коэффициент заполнения, тем ярче будет гореть лампа. В зависимости от того какая кнопка нажата меняется переменная i , а потом она записывается в регистр OCR1A .

    Полный текст программы представлен ниже. В комментариях более подробно описана работа программы.

    /***Занятие №8. Формирование ШИМ сигналов***/ #include #include int main(void) { unsigned int i=0; //определяем переменную i /***Настройка портов ввода-вывода***/ PORTB = 0x00; DDRB |= (1 << PB1); PORTD |= (1 << PD1)|(1 << PD0); // подключаем внутренние нагрузочные резисторы DDRD = 0x00; /***Настройка таймера***/ TCCR1A |= (1 << COM1A1)|(0 << COM1A0) // Установим биты COM1A1-COM1A0:0b10, означает сброс вывода канала A при сравнении |(1 << WGM11)|(0 << WGM10); // Установим биты WGM13-10:0b1110, согласно таблице это TCCR1B |= (1 << WGM13)|(1 << WGM12) // будет режим - FAST PWM, где верхний предел счета задается битом ICR1 |(0 << CS12)|(0 << CS11)|(1 << CS10); // Битами CS12-10:0b001 задаем источник тактового сигнала для таймера МК, включен без делителя TCNT1 = 0x00; // начальная установка счетчика ICR1 = 0xFF; // задаем период ШИМ, здесь у нас число 255, // по формуле fPWM=fclk_I/O/N*(1+ICR1)// вычисляем частоту ШИМ, она будет равна 15625 Hz OCR1A = 0x00; // начальный коэффициент заполнения ШИМ /***Основной цикл программы***/ while(1) { if((PIND&(1 << PD0)) == 0) //если кнопка "больше" нажата { if (i < 254) { // коэффициент заполнения ШИМ изменяется от 0 до 255 i=i+1; // увеличиваем i на единицу OCR1A = i; // записываем переменную в регистр сравнения _delay_ms(30); // задержка 30ms } } if((PIND&(1 << PD1)) == 0) //если кнопка "меньше" нажата { if (i > 0) // коэффициент заполнения ШИМ изменяется от 255 до 0 { i--; // уменьшаем i на единицу(так тоже можно писать) OCR1A = i; // записываем переменную в регистр сравнения _delay_ms(30); // задержка 30ms } } } }

    Внимание! Сперва подаем питание на микроконтроллер, потом нужно убедиться, что транзистор подсоединен к выводу МК, и лишь затем подавать питание в цепь с лампой и полевым транзистором. Иначе можете сжечь транзистор. Дело в том, что в выключенном состоянии "ножки" МК "болтаются в воздухе" - они ни к чему не подключены, и на них возникают наводки. Этих слабеньких наводок достаточно, чтобы частично открыть очень чувствительный полевой транзистор. Тогда его сопротивление между стоком и истоком упадет от нескольких МОм до нескольких Ом или долей Ом и через него потечет большой ток к лампе. Но транзистор не откроется полностью, т. к. для этого нужно подать на затвор не 1-3 В наводки, а стабильные 5 В, и его сопротивление будет намного больше минимального. Это приведет к выделению на нем большого количества тепла, и он задымится, а может и сгореть.

    Мы затронули тему использования счётчика/таймера ATtiny13 в обычном режиме и в режиме подсчёта импульсов (CTC). В этой статье я продолжаю тему таймера, но теперь мы рассмотрим его применение для реализации широтно-импульсной модуляции (ШИМ).

    Все микропроцессоры работают с цифровыми сигналами, т.е. с логическим нулем (0 В), и логической единицей (5 В или 3.3 В). Но что делать, если мы хотим получить на выходе какое-либо промежуточное значение? В таких случаях применяют Широтно-импульсную модуляцию (ШИМ, англ. pulse-width modulation (PWM)) — процесс управления мощностью, подводимой к нагрузке, путём изменения скважности импульсов, при постоянной частоте.
    Широтно-импульсная модуляция представляет собой периодический импульсный сигнал. Существуют цифровые и аналоговые ШИМ, однополярные и двуполярные, и т.д. Но принцип их работы остается одинаковым вне зависимости от исполнения и заключается в сравнении двух видов сигналов: опорного (пилообразные или треугольные импульсы) и входного (постоянного, либо изменяемого нужным образом, в зависимости от конкретной задачи ШИМ). Эти сигналы сравниваются и, при их пересечении, изменяется уровень сигнала на выходе ШИМ. Выходное напряжение ШИМ имеет вид прямоугольных импульсов, изменяя их длительность, мы можем регулировать среднее значение напряжения на выходе ШИМ *.

    * Если на выходе ШИМ использовать интегрирующую RC-цепь , то можно вместо импульсного получить постоянное напряжение нужной величины. Но в нашем примере со светодиодами можно обойтись и без этого, так как человеческий глаз всё равно не сможет разглядеть мерцания светодиода при используемой тактовой частоте.

    Параметры ШИМ

    • T - период тактирования (опорного сигнала);
    • t - длительность импулься;
    • S - скважность;
    • D - коэффициент заполнения.

    Скважность определяется отношением периода к длительности импульса. Коэффициент заполнения - величина, обратная скважности (может выражаться в процентах):

    S=T/t=1/D

    Рассмотрим подробнее, как работает ШИМ в AVR микроконтроллерах, на примере ATtiny13.
    Как уже упоминалось в предыдущем примере , в ATtiny13 реализовано две разновидности ШИМ: так называемые "Быстрая ШИМ" (Fast PWM) и "ШИМ с коррекцией фазы" (Phase correct PWM). Оба варианта основаны на использовании встроенного в МК восьмибитного счётчика/таймера T0. Таймер тут используется вместо опорного сигнала. Тактовая частота таймера задаётся предделителем тактовой частоты процессора, либо от внешнего тактового генератора. Режим тактирования задаётся битами CS02 (2), CS01 (1), CS00 (0) регистра TCCR0B :

    • 000 - таймер/счетчик T0 остановлен
    • 001 - тактовый генератор CLK
    • 010 - CLK/8
    • 011 - CLK/64
    • 100 - CLK/256
    • 101 - CLK/1024
    • 110 - от внешнего источника на выводе T0 (7 ножка, PB2) по спаду сигнала
    • 111 - от внешнего источника на выводе T0 (7 ножка, PB2) по возрастанию сигнала

    Настройка таймера для ШИМ

    Режим работы таймера задаётся битами WGM01 (1) и WGM00 (0) регистра TCCR0A :

    • 00 - обычный режим
    • 01 - режим коррекции фазы ШИМ
    • 10 - режим подсчета импульсов (сброс при совпадении)
    • 11 - режим ШИМ

    Здесь нас интересуют варианты "01" и "11".

    Биты COM0A1 (7) и COM0A0 (6) регистра TCCR0A задают, какой сигнал появится на выводе OC0A (5 ножка, PB0) при совпадении счётчика (регистр TCNT0 ) с регистром сравнения A (OCR0A ).

    В режиме "Быстрая ШИМ":

    • 10 - установка 0 на выводе OC0A при совпадении с A, установка 1 на выводе OC0A при обнулении счётчика (неинверсный режим)
    • 11 - установка 1 на выводе OC0A при совпадении с A, установка 0 на выводе OC0A при обнулении счётчика (инверсный режим)
    • 00 - вывод OC0A не функционирует
    • 01 - если бит WGM02 регистра TCCR0B установлен в 0, вывод OC0A не функционирует
    • 01 - если бит WGM02 регистра TCCR0B установлен в 1, изменение состояния вывода OC0A на противоположное при совпадении с A
    • 10 - установка 0 на выводе OC0A при совпадении с A во время увеличения значения счетчика, установка 1 на выводе OC0A при совпадении с A во время уменьшения значения счетчика (неинверсный режим)
    • 11 - установка 1 на выводе OC0A при совпадении с A во время увеличения значения счетчика, установка 0 на выводе OC0A при совпадении с A во время уменьшения значения счетчика (инверсный режим)

    Биты COM0B1 (5) и COM0B0 (4) регистра TCCR0A задают, какой сигнал появится на выводе OC0B (6 ножка, PB1) при совпадении счётчика (регистр TCNT0 ) с регистром сравнения B (OCR0B ).

    В режиме "Быстрая ШИМ":

    • 01 - резерв
    • 10 - установка 0 на выводе OC0B при совпадении с B, установка 1 на выводе OC0B при обнулении счётчика (неинверсный режим)
    • 11 - установка 1 на выводе OC0B при совпадении с B, установка 0 на выводе OC0B при обнулении счётчика (инверсный режим)

    В режиме "ШИМ с коррекцией фазы":

    • 00 - вывод OC0B не функционирует
    • 01 - резерв
    • 10 - установка 0 на выводе OC0B при совпадении с B во время увеличения значения счетчика, установка 1 на выводе OC0B при совпадении с B во время уменьшения значения счетчика (неинверсный режим)
    • 11 - установка 1 на выводе OC0B при совпадении с B во время увеличения значения счетчика, установка 0 на выводе OC0B при совпадении с B во время уменьшения значения счетчика (инверсный режим)

    Быстрая ШИМ (Fast PWM)

    В этом режиме счётчик считает от нуля до максимума. При установке нулевого значения счётчика - на выходе появляется импульс (устанавливается логическая единица). При совпадении с регистром сравнения - импульс сбрасывается (устанавливается логический ноль). В инверсном режиме, соответственно - наоборот.

    ШИМ с коррекцией фазы (Phase correct PWM)

    В этом режиме счётчик считает от нуля до максимума, а затем в обратном направлении, до нуля. При совпадении с регистром сравнения во время нарастания значения счётчика - импульс сбрасывается (устанавливается логический ноль). При совпадении во время убывания - появляется импульс (устанавливается логическая единица). В инверсном режиме, соответственно - наоборот. Недостатком данного режима является уменьшенная в два раза тактовая частота по сравнению с режимом Fast PWM. Но зато при изменении скважности не смещаются центры импульсов. Основное назначение данного режима - делать многофазные ШИМ сигналы, например трехфазную синусоиду, чтобы при изменении скважности не сбивался угол фазового сдвига между двумя ШИМ сигналами.

    Чтобы увидеть наглядно, как работает ШИМ, напишем небольшую программу (все опыты я провожу на своей отладочной плате , соответственно код привожу применительно к ней):

    /* * tiny13_board_pwm * Демо-прошивка отладочной платы на ATtiny13. * Демонстрация работы ШИМ на двух каналах: * неинверсный сигнал на выходе OC0A, инверсный - на выходе OC0B. */ #define F_CPU 1200000UL #include #include #define LED0 PB0 // OC0A #define LED1 PB1 // OC0B int main(void) { // Светидиоды: DDRB |= (1 << LED0)|(1 << LED1); // выходы = 1 PORTB &= ~((1 << LED0)|(1 << LED1)); // по умолчанию отключены = 0 // Таймер для ШИМ: TCCR0A = 0xB3; // режим ШИМ, неинверсный сигнал на выходе OC0A, инверсный - на выходе OC0B TCCR0B = 0x02; // предделитель тактовой частоты CLK/8 TCNT0=0; // начальное значение счётчика OCR0A=0; // регистр совпадения A OCR0B=0; // регистр совпадения B while(1) { do // Нарастание яркости { OCR0A++; OCR0B = OCR0A; _delay_ms(5); } while(OCR0A!=255); _delay_ms(1000); // Пауза 1 сек. do // Затухание { OCR0A--; OCR0B = OCR0A; _delay_ms(5); } while(OCR0A!=0); _delay_ms(1000); // Пауза 1 сек. } }

    Тут мы видим, что при старте МК в регистры сравнения A и B устанавливается 0, а счётчик запускается в режиме Fast PWM, с генерацией неинверсного ШИМ сигнала на выходе OC0A и инверсного - на выходе OC0B. В основном цикле значения регистров сравнения плавно меняются от 0 до максимума и обратно. В результате, светодиоды, подключенные к выводам OC0A и OC0B, будут поочерёдно плавно загораться и гаснуть, как бы в противофазе.
    Но если приглядеться внимательнее, то видим, что один из светодиодов гаснет не до конца, а продолжает тускло светиться. Эта особенность характерна для Fast PWM режима. Дело в том, что в этом режиме, даже если записать в регистр сравнения 0, при обнулении счётчика на выходе всё равно устанавливается логическая единица, которая сбрасывается в следующем такте (по совпадению с регистром сравнения). Таким образом, в каждом периоде будет проскакивать по одному короткому импульсу длительностью 1 такт, но этого достаточно для засвечивания светодиода. Этот эффект отсутствует в инверсном режиме формирования выходных импульсов, т.к. в данном случае при обнулении счётчика будет происходить не короткий импульс, а наоборот - короткий провал во время максимального заполнения ШИМ. Этот провал можно увидеть на осциллографе, но такое мерцание светодиода человеческое зрение просто не заметит. Поэтому второй светодиод загорается и гаснет полностью. В режиме ШИМ с коррекцией фазы, этот эффект отсутствует независимо, инверсный сигнал формируется на выходе или нет. Поменяем значение бита WGM01 (1) регистра TCCR0A с 1 на 0.