воскресенье, 28 апреля 2013 г.

Счётчик на ATmega16.


Подсчёт количества импульсов может применяться для решения множества разных практических задач (например приём сигнала для управления чем либо (реле например) или определение показаний датчика). Для подсчёта количества импульсов и использования результатов, этого подсчёта, можно использовать микроконтроллер. Для начала можно попробовать сделать систему для подсчёта нажатий кнопки а в случае её работоспособности на её основе делать более сложные устройства. Схема простого счётчика нажатий кнопки приведена на рисунке 1:
Рисунок 1 - Счётчик на ATmega16

Резистор R1 и конденсатор C1 предназначены для сглаживания пульсаций напряжения возникающих в результате дребезга контактов при нажатии и отпускании кнопки SB1. Резистор R2 предназначен для ограничения вытекающего из микроконтроллера тока. На светодиоды VD1-VD8 должно выводиться двоичное число (светодиод горит это 1, светодиод не горит это 0).

В микроконтроллер записывалась программа:



#include <avr/io.h>//порты ввода-вывода
   #include <avr/interrupt.h>//прерывания
   #define F_CPU 8000000UL  // 8 MHz тактовая частота
 
   int i=0x00;

   ISR(INT0_vect)//вызывается при возникновении прерывания по фронту int0
   {
i++;
if(i>0xff)
{
i=0x00;
}
PORTA=i;
   }
 
   int main(void)              // начало основой программы
   {
//конфигурация портов ввода/вывода
DDRA = 0xff;//0xff = 0b11111111  все выводы порта A сконфигурировать как выходы
DDRD = 0x00;//0x00 = 0b00000000  все выводы порта D сконфигурировать как входы
PORTD = 0xff;//включить подтягивающие резисторы на все выводы порта D
//инициализация прерывания
GICR |= 0x40;//0x40 = 0b01000000 разрешить прерывания на int0
MCUCR |= 0x3;//0x3 = 0b00000011 прерывания по фронту int0
sei();//разрешить все прерывания, cli()- запретить

while (1)//основной цикл
{

}

    }


Для подсчёта количества импульсов используется прерывание по фронту импульса напряжения на выводе INT0 для этого в регистр MCUCR записано шестнадцатеричное число являющееся результатом операции логического сложения числа 0x3 (3 - само число 0x - приставка обозначающая то что это число шестнадцатеричное) и числа которое там до этой записи было, а там, скорее всего, был ноль по умолчанию. В MCUCR можно было бы записать это число в двоичном виде (т.е. логического сложения) так: MCUCR = 0b00000011, это было было бы проще и нагляднее но так не принято делать. Так как прерывание возникает при приходе фронта импульса (т.е. при переходе из низкого (0) уровня напряжения в высокое (1)) а нажатие кнопки делает ноль на выводе INT0 то прерывание будет возникать при отпускании кнопки и в момент подачи питания на микроконтроллер (но это на данном этапе не очень важно), при возникновении этого прерывания вызывается функция ISR с параметром INT0_vect и выполняется код в её теле.
Для того чтобы прерывание возникало при нажатии на кнопку можно в регистр MCUCR записать число 0b00000010 вот так:
MCUCR = 0b00000010;
или в шестнадцатеричном виде:
MCUCR = 0x2;
для реакции на любое изменение (по фронту и по спаду):
MCUCR = 0x1;
Можно использовать вывод INT1, при этом будет вызываться ISR с параметром INT1_vect, в этом случае:

для реакции на любое изменение (по фронту и по спаду (нажатие и отпускание)):
MCUCR = 0x4;

по спаду (нажатие кнопки):
MCUCR = 0x8;

по фронту (отпускание кнопки):
MCUCR = 0xс;
Если записать MCUCR = 0x0; то INT0 и INT1 будут реагировать на низкий уровень напряжения.
При использовании INT2 (ISR вызывается с параметром INT2_vect)
по спаду:
MCUCSR = 0x0;
по фронту:
MCUCSR = 0x40;
Можно настроить прерывания и на INT0 и на INT1 например для обоих по фронту:
MCUCR = 0x0;
MCUCR |= 0x3;
MCUCR |= 0xc;

INT0 по спаду, INT1 по фронту и спаду:
MCUCR = 0x0;
MCUCR |= 0x2;
MCUCR |= 0x4;
Регистр GICR для разрешения внешних прерываний или их запрещения.
Разрешить на INT0:
GICR = 0x40;
Разрешить на INT1:
GICR = 0x80;

Разрешить на INT2:
GICR = 0x20;

hex файл создавался программой WinAVR, записывался в микроконтроллер он программой PonyProg через LPT порт и программатор на резисторах.

Результат работы схемы можно посмотреть на видео:
Целый байт почему то не выводится.






1 комментарий: