OSBoy notes.

Записки обо всём...

ATtiny13 - мигаем светодиодом

В этом примере мы напишем нашу первую программу на Си для микроконтроллера ATtiny13. Предполагается, что у нас уже подготовлено к работе всё необходимое: среда разработки, компилятор и т.д. Подопытным у меня будет самодельная отладочная плата, соответственно весь код буду приводить применительно к ней.
В качестве тестовой программы напишем классический, простейший пример "blink", который будет мигать светодиодом с определённой частотой.

Итак, создаём новый проект и приступаем. Приведу сразу полный код программы, а затем поясню всё более подробно:

/*
 * tiny13_board_blink
 * Демо-прошивка отладочной платы на ATtiny13
 * с целью проверки работоспособности МК.
 * Мигаем светодиодом.
 */ 

#define F_CPU 1200000UL // Указываем тактовую частоту МК
#define LED PB2         // Используем светодиод, подключенный к PB2 (7 пин)
#include <avr/io.h>     // Подключаем определения ввода/вывода
#include <util/delay.h> // Подключаем библиотеку функций задержки

int main(void)
{
  // Светодиод
  DDRB |= (1<<LED);     // конфигурируем пин как выход
  PORTB &= ~(1<<LED);   // по умолчанию светодиод выключен
  // Основной цикл
  while (1) 
  {
    _delay_ms (500);    // задержка 500 мс
    PORTB ^= (1<<LED);  // инвертируем состояние пина
  }
}

В самом начале задаём значения констант и подключаем заголовочные файлы и библиотеки.
Файл avr/io.h подключает определения ввода/вывода для конкретного типа микроконтроллера (тип МК указывается в виде опции для компилятора).
Библиотеку util/delay.h подключаем для использования функций задержки, в нашем случае: _delay_ms(). Для работы функций задержки мы должны указать тактовую частоту процессора. Поэтому ДО подключения util/delay.h определяем константу F_CPU (в данном случае - 1,2МГц).

Затем у нас идёт основная функция main - это, собственно, тело нашей программы. Здесь мы должны, сначала, описать все действия, которые будут происходить при старте микроконтроллера, а затем, в бесконечном цикле запустить выполнение основной программы:

while (1) { ... }

Для начала, мы должны сконфигурировать порт ввода/вывода. В МК AVR старших моделей портов в/в может быть несколько (A, B, C, D). К каждому порту может быть подключено до восьми ножек. Каждая из ножек может быть настроена как на вход, так и на выход. ATtiny13 имеет только один порт (B), к которому подключены шесть ножек (PB0-PB5, см. datasheet). По умолчанию все ножки настроены на вход, а чтобы управлять светодиодом, мы должны использовать соответствующую ножку как выход. В микроконтроллерах AVR вся аппаратная часть настраивается посредством восьмибитных регистров. Направление (вход-выход) устанавливается битами регистров DDRx (где x - буква порта, в нашем случае B). Значение бита "0" - соответствует входу, "1" - выходу. Таким образом, чтобы использовать ножку PB2, как выход, мы должны установить второй бит регистра DDRB в единицу:

DDRB |= (1<<PB2);

Для управления состоянием выхода предназначены регистры PORTx. Например, чтобы выключить светодиод, подключенный к ножке PB2 (подать низкий уровень сигнала), мы должны записать ноль во второй бит регистра PORTB:

PORTB &= ~(1<<PB2);

Чтобы включить (подать высокий уровень сигнала) - соответственно, записываем единицу:

PORTB |= (1<<PB2);

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

Полезные ссылки:
ATtiny13 Datasheet (официальный)
ATtiny13 Datasheet (урезанный вариант)
Доступ к портам I/O AVR на языке C (GCC, WinAVR)
Операторы управления битами

Теги : attiny13, AVR, микроконтроллеры, программирование, blink, си, C, светодиод

Комментариев: 4

Александр
#Ответить
У меня вопрос:после отпускания кнопок и,соответственно,изменении состояния входа(входов) происходит еще одно прерывание и если кнопок не нажимать,то контроллер так и будет находиться в "прерванном" состоянии ожидания очередного нажатия?
OSBoy
#Ответить
Вы, должно быть, с вопросом статьей ошиблись... тут про кнопки и прерывания речь не идёт. А вообще - всё зависит от конкретной настройки прерываний (установки конфигурационных битов в соответствующих регистрах) и кода обработчика самого прерывания... То есть, как запрограммируете - так и будет работать, вариантов настройки может быть множество. Тут у меня в соседних статьях есть более конкретный пример. А, как Вы выразились, "прерванное состояние" сбрасывается сразу после того, как будет выполнена подпрограмма-обработчик этого прерывания.
Игорь
#Ответить
Столько много вопросов
А вот сразу почему не DDRB |= (1<<PB2); без #define LED PB2
Или почему не DDRB |=(1<<3) и etc
Но это лучший блинк который мне удалось увидеть и повторить на Atmel studio и впихнуть его потом в протеус
Спасибо за то что поделились знаниями !
запилил строб на тиньке :)
OSBoy
#Ответить
Можно и без #define. Просто, если нам нужно будет адаптировать код под другое железо, в котором светодиод будет подключен к другому выводу, достаточно будет сменить значение #define LED, а без #define - придётся менять во всём коде. Кроме того, так код становится более удобно читаемым и редактируемым - например, мы сразу видим, что имеем дело со светодиодом (LED) кнопкой (BUTTON) и т.д., а не нужно вспоминать каждый раз, к какому пину что подключено.

Добавить комментарий

Отменить