Микроконтроллеры

Микроконтроллер Attiny13A в реальном мире

Оценка скорости процессов переключения и запуска
В даташите написано, что частота максимально 9.6MHz, притом установлен fuse-bit CKDIV8 в 0. В этом случае тактовая частота делится в 8 раз. Значит, 1.2MHz. Повысить частоту можно установкой данного fuse-bit в 1. Однако, могут быть проблемы в будущем. Об этом — позже.
Так что же из него можно в итоге «выжать».

1. Скорость и точность исполнения вызовов функций
Напишем простую программу

#include <avr/io.h>
int main(void)
{
  DDRB = 0xff;
  while(1)
  {
    PORTB= 0xff;
    PORTB= 0x00;
    PORTB= 0xff;
    PORTB= 0x00;
  }
}

Подключаем к щупам X/Y осциллографа порты PB0 и PB4 микроконтроллера Attiny13A. Настраиваем триггер осциллографа на срабатывание по восходящему фронту или включаем ждущий режим (single), чтобы регистрация началась с момента подачи сигнала. Здесь и далее предполагается делитель пробника, установленный в положение 1:10. Т.е. все показания по oY (Вольты) надо умножить в 10 раз.

Итак:

  • Время запуска и начала исполнения первой инструкции переключения ~ 6,5 мкс.
  • Время переключения из лог. 1 в лог. 0 ~ 1 мкс. Что соответствует одному такту.
  • Время перехода из лог. 0 (конец цикла) в начало исполнения цикла и установки лог. 1 ~ 2.7 мкс. То есть 3 такта! Стоит указать, что при выходе из цикла происходит выход из области видимости, что может повлечь дополнительные такты на работу с переменными (редко).
  • Смещение срабатывания портов (на рисунке видно, что PB4 срабатывает позже) ~ 100нс (~10MHz). То есть подключать его к логике, работающей не менее чем на f/2 = 5MHz надо внимательно, иначе может возникнуть ситуация, когда один выход уже установлен, а другой должен быть установлен, но пока еще не переключился. Вообщем на стороне приемника надо ждать минимум 100-200нс для точного детектирования.
  • Частота устоявшегося цикла ~ 275kHz (Фьюз CKDIV8=0, Int. RC OSC 9.6 MHz 14CK + 64 ms).

Если важна скважность импульсов, то частота переключения с помощью вызова функций в идеальном беспроблемном варианте не превысит 360kHz.

Так что данный микроконтроллер подходит для решения простейших задач. К примеру, максимально удовлетворительным результатом был вывод результатов на семисегментный индикатор через программный SPI. Отправка данных на 7-ми знаковый индикатор происходит менее чем за 1 секунду.
А управление, к примеру, драйвером MAX7219 светодиодной матрицы для организации бегущей строки работает крайне медленно. Удовлетворительно — при CKDIV8=1 (соответственно, тактовая частота в 8 раз больше). Данный бит установлен в 0 производителем не просто так. Ведь не логично сознательно понижать тактовую частоту. К примеру, в Atmega88 данный бит установлен по умолчанию в 1.
Так вот в случае с Attiny13 практически все SPI-программаторы перестают «видеть» Attiny13 при установке данного fuse-bit в 1. Нужен либо параллельный высоковольтный программатор либо Fusebit doctor.

2. Скорость и точность исполнения по таймеру/прерываниям
Открываем даташит на Attiny13 и смотрим раздел №9 (Interrupts). В микроконтроллере одно внешнее настраиваемое прерывание INT0 (вывод PB1) и общее ненастраиваемое прерывание для порта PCINT[0:5]. Настроим INT0.
Для этого нам нужно установить биты ISC01, ISC00 регистра MCUCR.

Далее — в регистре GIMSK установить бит INT0, чтобы разрешить прерывания.


Далее необходимо разрешить использование прерываний макросом sei().
В регистре GIFR можно читать бит INTF0, чтобы детектировать было ли прерывание. Или писать 1, чтобы сбросить данный бит.

Пишем код
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sfr_defs.h>

//Обработчик прерывания INT0
ISR(INT0_vect)
{
   PORTB = 0b00000001;
   PORTB = 0b00000000;
}

Инициализация прерываний
void InitINT0()
{
   MCUCR =_BV(ISC01) | _BV(ISC00);
   GIMSK = _BV(INT0);
   sei();
}

int main(void)
{
   DDRB  = 0b00000001;
   PORTB= 0b00000000;
   InitINT0();

    while(1){
   }
}

Это несколько нестандартный метод и применять его не рекомендуется. Однако, его полезно изучить, Так как прерывание в данном примере может произойти из-за помехи.
Для срабатывания прерывания в данном случае нужно сначала подать на порт PB1 сиганл низкого уровня (замкнуть с общим выводом), а потом разомкнуть. Данный порт никуда не подключен и на нем не установлены push/pull резисторы. Следовательно, на нем присутсвует некоторое напряжение (неопределенное сосояние Z). И прерывание произойдет, когда лог. 0 сменит Z на восходящем фронте. Процесс иллюстрируют два рисунка ниже. PB1 — желтый цвет. PB0 — голубой цвет.

Всего, судя по графику, около 17 тактов от восходящего фронта до срабатывания прерывания.


На последнем рисунке видно, что помеха от переключения порта PB1 перешла в порт PB0. Хотя мы и настроили срабатывание прерывания по восходящему фронту, это не означает, что оно сработает при переходе из лог. 0 в лог. 1. Оно срабатывает при переходе из лог. 0 в неопределенное состояние Z.

Время переключения всего порта PB (когда указываются все пины без применения булевых функций) в обработчике прерывания INT0 стандартно — 1 такт.

Изменим код таким образом, чтобы состояние вызывающего прерывание пина менялось автоматически.

#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sfr_defs.h>

ISR(INT0_vect)
{
   PORTB |= _BV(PB0);
   PORTB &= ~_BV(PB0);
}

void InitINT0()
{
   MCUCR =_BV(ISC01) | _BV(ISC00);
   GIMSK = _BV(INT0);
   sei();
}

int main(void)
{
   DDRB = 0b00000011;
   InitINT0();
    while(1){
   PORTB |= _BV(PB1);
   PORTB &= ~_BV(PB1);
   }
}

Вот примерное быстродействие срабатывания прерывания Attiny13 — 15.3 мкс. Добавим время на вычисление лог. И и присвоение значения лог. 0 пину PB0 в обработчике прерывания (2 такта) ~ 1.8 мкс. В итоге получается «боевая» рабочая частота не более 58 kHz.

На всех графиках заметны помехи. Рассмотрим их ближе:

Помеха переключения пина достигает 0.2 Вольт на соседнем пине. Также есть периодическая помеха амплитудой 20 мВ и частотой 2.4МГц.

Показать больше

1 Комментарий для “Микроконтроллер Attiny13A в реальном мире”

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Закрыть