Найти тему
Разумный мир

Микроконтроллеры для начинающих. Часть 39. Использование режимов сна PIC и PIC18

Оглавление

В статье "Микроконтроллеры для начинающих. Часть 37. Управление питанием и режимы работы" мы познакомились с различными режимами работы микроконтроллеров с точки зрения управления питанием. Один из этих режимов, режим сна (точнее, различные режимы сна), для нас наиболее важен. И в предыдущей статье "Микроконтроллеры для начинающих. Часть 38. Использование режимов сна AVR" мы довольно подробно рассмотрели, как использовать режимы сна в микроконтроллерах AVR. Сегодня мы продолжим изучение для микроконтроллеров PIC и PIC18.

В 8 битных микроконтроллерах от Microchip организация режимов сна проще, чем в ранее рассмотренных AVR. Но предоставляемые возможности довольно широкие. Как и в предыдущей статье, сначала мы изучим, как поддержка режимов сна реализована "в железе", а потом рассмотрим примеры программ.

Режимы сна

Микроконтроллеры PIC выпускаются различных семейств, как и AVR. Поэтому и количество режимов сна, и их выбор, различаются. Как и в AVR, переход в режим сна осуществляется командой SLEEP.

При нахождении микроконтроллера в одном из режимов сна состояние его цифровых выводов сохраняются в такими, как были до перехода в сон. Не изменяется и содержимое ОЗУ.

Сон, просто сон (Sleep Mode)

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

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

Сон с малой потребляемой мощностью ( Low-Power Sleep Mode)

Это тот же самый режим сна, но ядро микроконтроллера питается от пониженным напряжение от внутреннего регулятора. Только ядро, все выводы микроконтроллера продолжают работать при полном напряжении питания.

Нужно отметить, что PIC выпускаются в стандартном исполнении (буква F в названии микроконтроллера) и низковольтном (буквы LF в названии). Например, PIC16F1704 это стандартное исполнение, а PIC16LF1704 низковольтное. В стандартном исполнении есть возможность выбирать между Sleep mode и Low-power sleep mode, а в низковольтном нет, так как в них реализован только режим Low-power sleep mode.

Режим сна с сниженным потребление мощности доступен только для микроконтроллеров семейства Enhanced Mid-range.

Не спим но дремлем ( Doze Mode)

Этот режим доступен только для микроконтроллеров семейства Enhanced Mid-range с поддержкой технологии XLP ( eXtreme Low Power).

Обратите внимание, что переход в этот режим выполняется не командой SLEEP, а через специальный управляющий регистр! Строго говоря, это не полноценный режим сна.

В режиме дрёмы все периферийные модули работают на полной тактовой частоте, а вот процессор и память на пониженной. То есть, процессор выполняет команды медленнее, чем в обычном режиме работы. Такое замедление осуществляется простым пропуском циклов (не тактов)

Режим дрёмы микроконтроллера PIC16F18346. Из документации
Режим дрёмы микроконтроллера PIC16F18346. Из документации

Режим ожидания (Idle Mode)

Этот режим доступен для микроконтроллеров семейства Enhanced Mid-range с поддержкой технологии XLP ( eXtreme Low Power) и для PIC18.

Режим ожидания можно рассматривать как режим дрёмы с дополнительными ограничениями. Как в Doze mode, системный тактовый генератор не останавливается. Однако отключается тактирование процессора и памяти. То есть, периферийные модули продолжат работать, но команды выполняться не будут.

Управление выбором режимов сна

Sleep mode или Low-Power Sleep mode

Выбор между этими двумя режимами осуществляется битом VREGPM регистра VREGCON. Собственно говоря, этот регистр и содержит единственный значащий бит.

Если VREGPM=1, то по команде SLEEP микроконтроллер переходит в режим Low-power sleep mode. Если VREGPM=0, то по команде SLEEP микроконтроллер переходит в обычный режим Sleep.

По умолчанию, после сброса, выбран режим Sleep.

Doze mode

За использование режима дрёмы (и режима ожидания тоже) отвечает регистр CPUDOZE.

Регистр CPUDOZE микроконтроллера PIC16F18346. Из документации
Регистр CPUDOZE микроконтроллера PIC16F18346. Из документации

Если бит DOZEN=1, то процессор микроконтроллера начинает пропускать машинные циклы снижая скорость своей работы (периферийные модули продолжают работать на полной скорости). Причем это произойдет сразу, а не по команде SLEEP.

Соотношение тактовой частоты и частоты выполнения команд определяется битами DOZE.

-3

Например, если DOZE=011, то из каждых 16 машинных циклов будет пропущено 15 и выполнится одна команда.

Idle Mode

В микроконтроллерах PIC, где этот режим реализован, его использование вместо режима Sleep зависит от бита IDLEN регистра CPUDOZE (показан в предыдущем подразделе).

Если IDLEN=1, то по команде SLEEP микроконтроллер не уснет полностью, а перейдет в режим ожидания. Каких либо дополнительных настроек сделать нельзя.

В PIC18 бит IDLEN находится в регистре OSCCON, который управляет системным тактовым генератором. При этом его работа полностью идентична работе в PIC.

Особенности PIC18

На самом деле, в PIC18 режимы Run и Idle имеют несколько подрежимов, которые выделяются как отдельные в документации. На мой взгляд, это не совсем подрежимы, так вся разница заключается в выборе источника тактового сигнала через биты SCS регистра OSCCON, как показано ниже

Фрагмент описания регистра OSCCON микроконтроллера PIC18F26K22. Из документации
Фрагмент описания регистра OSCCON микроконтроллера PIC18F26K22. Из документации

Выбор внешнего тактового генератора (SOSC) приводит к отключению внутреннего генератора (независимо от его типа). Существенных для нас различий (по крайней мере сейчас) это не несет. Поэтому уделять дополнительное внимание этому вопросу я не буду.

Кроме того, в PIC18 можно дополнительно управлять тактированием периферийных модулей. Для этого предназначены регистры PMDx, количество которых может быть разным в разных микроконтроллерах. Установив соответствующий нужному модулю бит в единичное состояние можно отключить подачу тактовых импульсов на этот модуль. Причем это произойдет независимо от режима работы.

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

Переход в сон (кроме режима Doze)

Как я уже говорил, микроконтроллер засыпает по команде SLEEP. При этом следующая за SLEEP команда уже выбрана из ПЗУ и декодирована. И это необходимо учитывать, так оказывает влияние на пробуждение. В простейшем случае можно просто поставить после SLEEP команду NOP. Кстати, именно этот вариант предлагает документация.

При выполнении команды SLEEP автоматически выполняется сброс сторожевого таймера если его работа разрешена.

Для перехода в режим дрёмы просто нужно установить бит DOZEN.

Пробуждение из режимов сна

Разбудить микроконтроллер можно:

  • Сброс. Разумеется, аппаратный сброс через внешний вывод не только разбудит микроконтроллер, но и вернет его в первоначальное состояние, как при включении питания. Сюда же относятся сброс через WDT и BOD.
  • Через сторожевой таймер (WDT), без сброса
  • Установку флага запроса прерывания периферийными модулями. Внешние прерывания.

После пробуждения в обязательном порядке выполняется следующая за SLEEP команда, так как она уже выбрана и декодирована. Исключением является семейство BaseLine.

Кроме того, автоматически сбрасывается WDT если его работа разрешена.

BaseLine микроконтроллеры, только сброс

Микроконтроллеры не имеющие прерываний (BaseLine семейство) при любом варианте пробуждения выполняют сброс. При этом программа может узнать, что произошло (сброс, пробуждение) и по какой причине анализом специальных бит в регистрах микроконтроллера. Например, бит GPWUF будет установлен, если произошло пробуждения то изменения состояния входов порта. Иначе этот бит будет сброшен.

Такой вариант пробуждения вполне рабочий, но довольно не удобный. Так выводы портов сохраняли свое состояние во время сна, но при пробуждении на короткое время окажутся начальном состоянии (как входы), что может привести к некорректной работе устройства в целом.

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

Пробуждение от сторожевого таймера. Любой режим сна, кроме Doze

Работа сторожевого таймера в режиме сна отличается от работы в обычном режиме. Он не выполняет сброс микроконтроллера, а просто пробуждает его. При этом выполнение программы продолжается со следующей за SLEEP команды. В данном случае нет необходимости помещения команды NOP после SLEEP.

Таким образом, WDT совместно с командой SLEEP можно использовать для экономного по потреблению формирования временных интервалов.

Пробуждение через прерывания. Любой режим сна, кроме Doze

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

Фрагмент схемы контроллера прерываний PIC. Из документации
Фрагмент схемы контроллера прерываний PIC. Из документации

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

То есть, можно использовать запросы прерываний без необходимости собственно обрабатывать прерывания. При этом выбранный источник прерываний должен быть разрешен.

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

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

Поэтому при использовании прерываний (событий) для пробуждения микроконтроллера после SLEEP рекомендуется размещать команду NOP.

Выход из дрёмы. Все легко и просто

Для выхода в обычный режим из Doze mode достаточно просто сбросить бит DOZEN.

Использование режимов сна с программах на С

В качестве компилятора для примеров я буду использовать CC5X (CC8E для PIC18), так как его возможности отличаются от стандарта. Если же вы будете использовать XC8 от Microchip, то можете использовать обычные описания регистров как битовых полей. Точно так же, как я показывал это для AVR.

Для перехода в стандартный режим сна достаточно просто выполнить команду SLEEP для вставки которой в программу CC5X использует внутреннюю функцию sleep(). Так что тут даже никакого примера не требуется. Если после SLEEP нужна команда NOP, то это можно сделать внутренней функцией nop().

sleep(); // засыпаем

nop();

Вот так все просто.

Не менее просто осуществляется переход в режим Low-power sleep mode. Проиллюстрирую это на примере PIC16F18346. Нужный нам бит в файле 16f18346.h описан так

char VREGCON @ 0x197;

bit VREGPM @ VREGCON.1;

Регистр VREGCON расположен в 3 банке и имеет полный адрес 0х197, а бит VREGPM располагает в бите 1 этого регистра. Как задать адрес размещения переменной я уже показывал ранее в статьях "Микроконтроллеры для начинающих. Часть 34. Мост к Си. Описываем регистры аппаратуры" и "Микроконтроллеры для начинающих. Часть 28. Мост к Си. Размещение в памяти. Секции, сегменты, особенности". И переход в режим Low-power sleep mode выполняется так

VREGPM=1;

sleep();

nop();

Так же все очень просто.

Переход в режим Doze требует немного больше усилий, но и здесь нет ничего сложного. Описание регистра уже есть

char CPUDOZE @ 0x918;

а вот его биты не описаны. Исправим это упущение и опишем их сами. И попутно перейдем в режим дремы с с соотношением 1:16

bit DOZEN @ CPUDOZE.6; // бит перехода в режим дрёмы

#define DOZE_MASK 0b11111000 // маска для битов DOZE

#define DOZE_RATIO_16 0b00000011 // соотношение 1:16

CPUDOZE &= DOZE_MASK;

CPUDOZE |=DOZE_RATIO_16;

DOZEN=1;

На самом деле, не менее эффективным по объему кода было бы и описание поля DOZE в виде 3 отдельных бит и их прямая установка/сброс. Но я выбрал способ использования логических операций. Выйти из режима дрёмы очень легко

DOZEN=0;

А теперь пример для PIC18F26K22. Перейдем в режим Idle, причем одновременно переключимся на внешний тактовый генератор SOSC. Нужные нам описания есть в файле 18f26k22.h

char OSCCON @ 0xFD3;

bit IDLEN @ OSCCON.7;

bit SCS0 @ OSCCON.0;

bit SCS1 @ OSCCON.1;

Ничего дополнительно описывать не придется.

SCS1=0; SCS0=1; // Переключение на SOSC

IDLEN=1;

sleep();

И опять все легко и просто.

Заключение

Мы рассмотрели реализацию режимов сна в микроконтроллерах PIC и их использование в программах на С. Не смотря на то, эти микроконтроллеры часто вызывают критику из-за не слишком удобного деления памяти на банки и страницы, режимы сна реализованы очень просто. Причем для PIC18 и Enhanced Mid-range не менее гибко, чем для других микроконтроллеров (того же AVR).

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

До новых встреч!