Открыть Электронные книги
Категории
Открыть Аудиокниги
Категории
Открыть Журналы
Категории
Открыть Документы
Категории
Программирование
микроконтроллеров AVR во
встраиваемых системах
Тема 2. 1 Управление включением
светодиодов
ПОДРОБНОЕ ОПИСАНИЕ ПОРЯДКА СОСТАВЛЕНИЯ
ИСХОДНОГО КОДА ПРОГРАММЫ ДЛЯ ЛАБОРАТОРНОЙ
РАБОТЫ № 1
while (1){};
"бесконечный" потому, что в скобках, где стоит
условие его выполнения, написана константа -
число 1 - это "не ноль" значит "истина" в Си.
Поэтому цикл будет выполняться, пока есть
питание в МК и нет "сброса" (RESET). Можно
написать любое число отличное от 0 - не ноль это
"истина" .
Строчка программы :
PORTB++; //добавить 1 к значению в PORTB после паузы,
вызванной переполнением.
Строчка программы :
while (!(TIFR&0x02)); // ждем установки флага переполнения
timer0
это условный цикл, где while (условие){}; , но без тела цикла,
поэтому скобки {} опущены. Без тела - т.е. он ничего не
выполняет, а лишь проверяет условие в скобках на
"истинность" так часто насколько возможно по скорости
МК и до тех пор, пока не обнаружит, что условие в скобках
"ложно" - тогда программа закончит этот цикл и пойдет
ниже, на следующую строчку кода.
Условие в скобках !(TIFR&0x02) включает знак !
что означает логическое отрицание - меняет "ложь"
на "истину" и наоборот.
Значит цикл будет продолжаться, пока
таймер/счетчик 0 будет накапливать счетные
импульсы до переполнения и будет проверяться
содержимое регистра TIFR – регистра флагов
прерывания таймеров. Результат вычисления
выражения
TIFR&0x02 (0х02 = 0b00000010)
будет равен 0 что значит в Си "ложно" до тех пор,
пока не произойдет переполнение и бит_1 в регистре
TIFR установится в 1. При том же (!(TIFR&0x02))
будет «истина».
& - это побитное (поразрядное) логическое "И" -
означает, что только 1 и 1 в каждом бите дают 1.
В числе 0x02 все биты равны 0 кроме бит_1 -
значит, когда бит_1 в регистре TIFR станет "1" то
результат TIFR&0x02 станет 1 или "истина", тогда (!
(TIFR&0x02)) станет «ложь», и программа покинет
цикл.
Из ДШ известно, что бит_1 регистра TIFR имеет
обозначение TOV0 - это "флаг" события:
"переполнение таймера_0". Значит мы выполнили
пункт д) алгоритма. Рассмотрим подробнее
информацию об этом бите, начнем с цитирования
ДШ на английском:
• Bit 1 – TOV0: Timer/Counter0 Overflow Flag
The bit TOVO is set when an overflow occurs in Timer/Counter0. TOVO
is cleared by hardware when executing the corresponding interrupt
handling vector. Alternatively, TOVO is cleared by writing a logic one to
the flag. When the SREG l-bit, TOIE0 (Timer/CounterO Overflow
Interrupt Enable), and TOVO are set, the Timer/CounterO Overflow
interrupt is executed.
Перевод:
• Бит 1 - TOV0: флаг переполнения таймера/счетчика 0
Бит TOV0 устанавливается ( т.е. становится «1»), когда происходит
переполнение в таймере/счетчике 0. TOV0 очищается ( т.е.
становится «0») аппаратно при выполнении соответствующего
вектора обработки прерываний т.е. TOV0 сам очищается
(становится "0") если происходит вызов обработчика прерывания
связанного с событием, устанавливающим данный флаг.
Альтернативно, TOV0 очищается путем записи логической единицы
во флаг.
Обработчик прерывания вызывается программно,
если ранее в программе мы
- разрешили прерывания глобально ("установив"
бит 1 в регистре SREG ) и
- разрешили данное прерывание "установив"
бит TOIE0.
Заметим, что эти условия мы не обеспечивали.
Следующий пункт алгоритма :
е) очистить признак переполнения таймера.
нужно выполнить для того чтобы и в следующий раз
определить момент переполнение таймера_0. Для
этого нужно очистить бит TOV0. Мы отметили выше,
что не планировали использовать прерывание от
таймера_0 и не разрешали его и не разрешили
прерывания вообще.
Поэтому мы используем альтернативный метод
очистки флага, и строка программы:
TIFR = 0x02; // очистить флаг переполнения timer0
помещает число 2 в регистр TIFR т.е. именно
вписывает логическую "1" в бит_1 - тем самым
очищает флаг и выполняет пункт алгоритма е).
Именно такой метод используется для очистки
флага только в микроконтроллерах AVR. В других
типах МК используется запись логического «0» во
флаг. Причем даже в микроконтроллерах AVR флаг
переполнения может располагаться в разных битах
регистра TIFR. Необходимо внимательно изучать
полную ДШ для каждого конкретного МК.
Внимание ! Строка: TIFR = 0x02; вписывает в другие
биты регистра (кроме бит_1) нули ! В нашем случае
это допустимо. Если вам нужно записать "1" только в
один бит_n регистра, не трогая другие биты,
используйте манипулирование отдельными битами,
будет такой код:
REGISTER |= 1<<n; // здесь 1 сдвинута на n разрядов
влево, при побитном сравнении с любым числом в
разряде n даст 1.
Если вам нужно записать "0" только в один
бит_n регистра, не трогая другие биты, используйте
такой код:
REGISTER &= ~(1<<n);
В бит_n появится нужное вам число не зависимо от
того что там было!
Последний пункт нашего алгоритма
ж) перейти к пункту г)
не требует написания специального кода - он
выполняется автоматически,
так как программа выполнила все "тело" цикла и
сама перейдет опять в начало цикла, т.е. к пункту
алгоритма - г)
Полный текст программы:
#include <io.h> //включает файл с объявлениями
всех типов
// микроконтроллеров Atmel
#include <tiny2313.h> // включает файл с
объявлениями битов
//и регистров используемого
микроконтроллера
#define PB_OUT DDRB = 0xFF // определяет макрос
PB_OUT,
//который объявляет порт B выходом
void initialization (void) // функция инициализации
{
PB_OUT; //вызываем макрос PB_OUT
TCCR0B = 0x05; //запускаем таймер 0 с
коэффициентом деления 1024
PORTB = 0; // обнуляем биты порта B
}
void main(void) //главная программа
{
initialization ();//начинаем с инициализации
while (1) // непрерывный цикл
{
PORTB++; //прибавляем к значению переменной
PORTB единицу
while (!(TIFR&0x02)); // ждем появления флага
переполнения таймера 0
TIFR = 0x02; // очищаем флаг переполнения
таймера
} // закрывающая скобка непрерывного цикла,
возврат к началу цикла
} // закрывающая скобка главной программы
Использованы материалы сайта:
http://www.123avr.com/z1.htm
Посещено 25.12.2015 14-35