Подсчёт количества импульсов может применяться для решения множества разных практических задач (например приём сигнала для управления чем либо (реле например) или определение показаний датчика). Для подсчёта количества импульсов и использования результатов, этого подсчёта, можно использовать микроконтроллер. Для начала можно попробовать сделать систему для подсчёта нажатий кнопки а в случае её работоспособности на её основе делать более сложные устройства. Схема простого счётчика нажатий кнопки приведена на рисунке 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 порт и программатор на резисторах.
Результат работы схемы можно посмотреть на видео:
Целый байт почему то не выводится.
#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 порт и программатор на резисторах.
Результат работы схемы можно посмотреть на видео: