1) Реакция микроконтроллера на внешнее воздействие (нажатие кнопки):
• Возьмём микроконтроллер ATmega8515. К 7 пину порта D (четвёртый снизу, слева) подсоединим кнопку, замыкающую пин на общий провод. На 0 пин порта C поставим светодиод.
• При нажатии на кнопку светодиод должен загораться. При отпускании кнопки - гаснуть. Вместо кнопки можете подсоединить гибкую перемычку и закорачивать её на общий провод.
Алгоритм работы:
1) Подтягиваем седьмой пин порта D7 к питанию. На пине висит +5 вольт.
2) У порта D есть т.н. "регистр флагов" PIND, в который автоматически записывается лог.1, если на пине порта висит логическая 1; И записывается логический 0, если напряжение на пине порта - лог. 0. В нашем случае в момент запуска программы в 7 разряд регистра PIND записывается лог. единица.
3) При закорачивании D7 на общий провод напряжение на пине падает до нуля. В 7 разряд регистра PIND записывается лог. нуль.
4) В бесконечном цикле с большой скоростью просматриваем содержимое 7 разряда регистра PIND (поллинг). Если в разряде окажется нуль, значит кнопка не нажата. Ветвим программу и подаём 1 на С0 (зажигаем светодиод).
5) Если в 7 разряде регистра PIND окажется лог. единица, то кнопка не нажата. Ветвим программу по другой ветке и подаём на C0 логический 0.
Программа на CodeVisionAVR:
#include <mega8515.h>
#define PD7 7 // Переобозначение 7 пина порта D на его имя.
void main(void)
{
PORTD = 0b10000000; // Подключаем подтягивающий PULL-UP резистор к 7 пину порта D.
DDRD = 0b00000000; // Настроим порт D на ввод информации.
// Важна последовательность! Сперва подключаем PULL-UP резистор,
// и только потом настраиваем порт на ввод, иначе кнопка работать не будет.
DDRC = 0b11111111; //Настроим порт С на вывод информации.
while(1) // Бесконечный цикл опроса кнопок (поллинг).
{
if (PIND &= 1<<PD7) // Считываем 7 пин порта D.
{
PORTC =0b00000000; // Если 1 (кнопка не нажата), то гасим светодиод.
}
else
{
PORTC = 0b00000001; // Если 0 (т. е. кнопка нажата), то зажигаем светодиод.
}
}
}
2) Инвертирование пина при нажатии на кнопку. Детектор фронта:
• При нажатии на кнопку (или закорачивании перемычки на общий провод) инвертируем несколько пинов микроконтроллера.
Проблема:
Программа на CVAVR представляет из себя самодельный детектор фронта с 1 (кнопка не нажата или перемычка не закорочена, пин подтянут к плюсу питания) на 0 (кнопка нажата или перемычка закорочена, пин подтягивается к общему проводу). При отслеживании перескока с 1 на 0 (на седьмом пине порта D) пины порта С инвертируются. В отличие от узла отслеживания внешних прерываний, "чистый" порт не имеет детектора фронта, и детектор фронта (в нашем случае нисходящего) приходится делать самому (программным путём).
Программа на СodeVisionAVR:
#include <mega8515.h>
#include <delay.h>
int Knopka_Staroe, Knopka_Novoe;
void main(void)
{
PORTD = 0b10000000; // Подключаем подтягивающий резистор к 7 пину порта D.
DDRD = 0b00000000; // Настроим порт D на ввод информации.
DDRC = 0b11111111; // Настроим порт С на вывод информации.
// Программируем самодельный детектор фронта с 1 до 0 (кнопка не нажата / кнопка нажата).
while(1) // Бесконечный цикл опроса кнопок (поллинг).
{
Knopka_Staroe = (PIND&=(1<<7)); // Записываем старое состояние кнопки в переменную Knopka_Staroe.
if (Knopka_Staroe) // Если Knopka_Staroe равно 1 (кнопка не нажата), то...
{
delay_ms(80); // Пауза для подавления дребезга контактов.
Knopka_Novoe = (PIND&=(1<<7)); //...считываем новое состояние кнопки.
if (!Knopka_Novoe) // Новое состояние кнопки должно быть равно 0 (нажата).
{ // В этом случае падающий фронт сформирован и можно инвертировать пины.
delay_ms(80); // Пауза для подавления дребезга контактов.
PORTC ^= (1<<5 | 1<<6 | 1<<7); // Инвертируем пины 5, 6, 7.
}
}
}
}
3) Реакция микроконтроллера на внешний электрический импульс. PULL-DOWN резистор:
• Пусть микроконтроллер должен реагировать не на нажатие кнопки, а на импульс напряжения с внешнего источника (например от другого микроконтроллера, от датчика).
• На 7 пин порта D микроконтроллера ATmega8515 подаём напряжение от внешнего источника (например прикасаемся к пину батарейкой), имитируя подачу сигнала по линиям связи.
• Если на 7 пине порта D висит +5 вольт (лог. единица), зажигаем светодиод на 0 пине порта C.
• Если на 7 пине порта D висит 0 вольт (лог. нуль), гасим светодиод на 0 пине порта C.
Алгоритм работы:
1) Можно сделать так: к 7 пину порта D подключим резистор, постоянно подтягивающий пин к общему проводу (т.н. PULL-DOWN резистор). На пине при этом висит лог. нуль. При касании пина плюсом батарейки на пин вешается напряжение +5 вольт (лог. единица). В микроконтроллерах AVR встроенного PULL-DOWN резистора нет, поэтому подключим внешний резистор (любой от 1кОм до 1000кОм с 7 пина порта D на общий провод).
2) В бесконечном цикле с большой скоростью просматриваем содержимое 7 разряда регистра PIND (поллинг). Если в разряде окажется лог. единица, значит на пин подаётся внешний сигнал. Ветвим программу и подаём 1 на С0 (зажигаем светодиод).
3) Если в 7 разряде регистра PIND окажется лог. нуль, значит внешний сигнал отсутствует или имеет нулевой лог. уровень. Ветвим программу по другой ветке и подаём на C0 логический 0.
Программа на CodeVisionAVR:
#include <mega8515.h>
#define PD7 7 // Переобозначение 7 пина порта D на его имя.
void main(void)
{
DDRD = 0b00000000; // Настроим порт D на ввод информации.
DDRC = 0b11111111; //Настроим порт С на вывод информации.
while(1) // Бесконечный цикл опроса кнопок (поллинг).
{
if (PIND &= 1<<PD7) // Считываем 7 пин порта D...
{
PORTC =0b00000001; // ...если 1 (т. е. внешний сигнал подаётся), то зажигаем светодиод на C0.
}
else
{
PORTC = 0b00000000; // ...если 0 (т. е. внешний сигнал не подаётся или имеет нулевой лог. уровень), то гасим светодиод на C0.
}
}
}