В начало | Зарегистрироваться | Заказать наши киты почтой
 
 
 
 

Грызём микроконтроллеры. Урок 9. Клавиатура вглубину

📆20 января 2010   ✒️Spirit   🔎31.704   💬10  
И снова приветствую Вас в моей лекционной!
На этот раз я расскажу Вам как "сэкономить" выводы микроконтроллера, не ограничивая функциональности органов управления.
Список всех частей:
Грызём микроконтроллеры. Урок 1. Моргаем 8-ю светодиодами. CodeVision, Proteus, ISIS
Грызём микроконтроллеры. Урок 2. CodeVision и С
Грызём микроконтроллеры. Урок 3. Циклы, прерывания и массивы
Грызём микроконтроллеры. Урок 4. Мерим температуру или напряжение
Грызём микроконтроллеры. Урок 5. Кодовый замок
Грызём микроконтроллеры. Урок 6. Прошиваем МК
Грызём микроконтроллеры. Урок 7. Подключение к МК кнопок, клавиатуры, энкодера
Грызём микроконтроллеры. Урок 8. Программирование кнопок, клавиатуры, энкодера
Грызём микроконтроллеры. Урок 9. Клавиатура вглубину


Десяток кнопок по одному проводу

Для управления устройством далеко не обязательно подключать каждую кнопку к отдельному выводу МК. Например, если в вашем устройстве есть "лишний" вход аналого-цифрового преобразователя (АЦП, ADC), то его вполне можно использовать для подключения клавиатуры с десятком кнопочек :laughing:

Принцип очень прост. Резисторы R1-R6 (см. схему) создают делитель напряжения. Когда ни одна кнопка не нажата, цепь делителя разорвана, на входе МК присутствует напряжение, равное напряжению питания. При нажатии на любую кнопку, ко входу МК подключается один или несколько резисторов (а для верхней кнопки ни одного), образуя делитель напряжения. Теперь остается только измерить (оцифровать посредством АЦП) это напряжение и определить нажатую кнопку.
Такой способ очень часто используют в съемных панелях автомагнитол. Представьте, что было бы, если бы для каждой кнопки в разъеме был отдельный контакт wassat

Но для начала нам придется разобраться как работает сам АЦП.

Посмотрим на скриншот из CodeWizard:
Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.


В нашем конкретном случае высокая точность не нужна, поэтому мы используем 8-и битное преобразование и фильтров ставить не будем. А для вывода данных используем два семисегментных индикатора.

Создайте проект с указанными на скриншоте настройками АЦП, сделав все выводы порта B выходами, и настроив таймер Timer0 на работу от внутреннего генератора частотой 0,977kHz (и не забудьте установить галочку Overflow Interrupt, включив тем самым прерывание переполнения таймера).

В сгенерированном программой тексте сразу увидим новую функцию read_adc(). Это готовая функция для получения результатов АЦП. Параметром ей передается номер входа АЦП, напряжение на котором нужно оцифровать. В нашем случае это ADC0, соответственно вызов функции будет выглядеть так:
read_adc(0)


Теперь в функции прерывания таймера Timer0 напишем
PORTB= read_adc(0);


Эта команда будет считывать значение АЦП и записывать его в порт B, к которому подключены семисегментные индикаторы, на которых мы и будем видеть значение АЦП для нажатой кнопки.

Компилируем...

И с ужасом смотрим на ошибку:
Error: ...sources11.c(30): undefined symbol 'read_adc'

"Всего одна строка и ошибка???" - рвем мы на себе волосы am
Дословный перевод " Ошибка: в_таком-то_файе (в 30-й строке): неизвестный символ 'read_adc' "
Но ведь всё правильно!!! Откуда тогда ошибка? crying

А ошибка на самом деле банальнейшая. Мы пытаемся вызвать функцию, о которой программа пока еще не знает. Генератор кода расположил функцию прерывания таймера ДО функции АЦП, а компилятор, доходя до нашей строки говорит, что мы пытаемся вызвать функцию, которой нет.

Чтобы всё заработало, нужно сначала "научить" компилятор этой функции, а потом уже ее вызывать.
Для этого просто вырезаем функцию прерывания таймера и вставляем ее ПОСЛЕ функции АЦП.

Вот теперь компилируем и проверяем в ISIS

Промоделировав всё это дело, видим, что каждой кнопке соответствует определенное значение АЦП, зная которое, можно точно идентифицировать нажатую кнопку. Но не стоит забывать, что модель идеализирует реальную схему. Если вы соберете всё это дело в железе, сразу увидите, что значение АЦП немного плавает и не совпадает с полученным в ISIS. Обусловлено это тем, что напряжение на входе АЦП зависит от напряжения питания, так же МК ловит помехи извне и со своего же кристалла. Поэтому для идентификации советую использовать интервал
(x-n1) < x < (x+n1)
где x - значение АЦП полученное в модели, а n1 и n2 - некоторые константы. Какое взять n, можно определить опытным путем, или, как делаю я, посчитать "расстояние" между соседними кнопками и взять его половину. К примеру, 3-й кнопке соответствует значение B1, четвертой - 86, B1-86=2B. Разделим его пополам - получаем 15. Значит для 3-й кнопки интервал будет
(0xB1-0x15) < x < (0xB1+n2)
0x9C < x < (0xB1+n2)

n2, соответственно, определяется разностью со значением второй кнопки

А для 4-й кнопки интервал
(0x86 -n1) < x < (0x86+0x15)
(0x86 -n1) < x < 0x9B

n1 вычисляем из разности с пятой кнопкой.
Главное, не забудьте, что интервалы не должны пересекаться!

Над программной реализацией определения кнопки я предлагаю Вам потрудиться самостоятельно tongue

Ну и напоследок бочка дегтя... Я не зря упомянул в начале описания этого метода автомагнитолы. Наверняка многие сталкивались в них с такой проблемой, когда ты хочешь от прибора одно, а делает он совсем другое am
Так как в основе этого метода лежит делитель напряжения, он очень чувствителен к его параметрам. А механические контакты кнопок имеют свойство окислятся, что увеличивает их сопротивление и нарушает параметры делителя. Поэтому без фанатизма пожалуйста wink - чем больше кнопок, тем меньше между ними интервал и больше вероятность "промаха" идентификации.

И еще один маленький совет: если программа определила нажатие какой-либо кнопки, не поленитесь запустить АЦП еще раз (а может и 2 или 3 раза) и проверить, в один ли интервал попадают эти два значения. Это позволит избежать многих ошибок в распознании кнопок.


Матричная клавиатура.

Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.


Принцип и устройство мы ранее уже разбирали, поэтому заострять внимания на этом я не буду.
А вот программа уже становится интересной :laughing:

На этот раз первые три вывода порта D у нас будут использоваться как выходы, а следующие 4 - как входы.

Помните, что регистр PORT используется как для входов, так и для выходов?
Если вывод настроен как выход, то ясное дело, что на нем будет то, что записано в соответствующем бите регистра PORT.
А вот для входов этот регистр определяет, подключен ли к нему внутренний подтягивающий резистор.

Вот Вам, как пища для размышлений упрощенная схема вывода МК:



Положение "вверх" для "выключателя" означает единицу в соответствующем регистре, а положение "вниз" - ноль

Для упрощения схемы я предлагаю использовать внутреннюю подтяжку для входов МК. Значит нам ни в коем случае нельзя записывать нули в 3-6 разряды порта D, иначе мы отключим резисторы и МК не сможет точно определить что у него на входе лог. "1" или лог. "0".

Поэтому значения для выходов (выводы PORTD.0 - PORTD.2) нужно либо записывать побитово:
Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.


Перебор столбцов будем производить в функции прерывания таймера. Для корректной работы нашего алгоритма создадим глобальную переменную stolb, в которой у нас будет храниться номер активного столбца. Если Вы опишете ее в самой функции прерывания, то она будет создаваться при запуске функции, а при ее окончании будет удаляться, а значит, и ее значение сохраняться не будет. А вот глобальная переменная ни от чего не зависит и подходит нам идеально.
Состояния строк клавиатуры будем проверять в том же прерывании (не отходя от кассы, как говорится), сразу после изменения активного столбца.

Вот, что получилось у меня:
Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.


Попробуйте подробно разобрать все действия (их там всего-то 6). Как и в математике, сначала выполняем действия в скобках fellow
А если что-то непонятно и не можете разобраться - спрашивайте на форуме. Объясню и дополню статью.

Творческих успехов!

Продолжение следует...


Исходники и готовые схемы для ISIS:
🎁keys3.rar  85.22 Kb ⇣ 243

Камрад, рассмотри датагорские рекомендации

🌼 Полезные и проверенные железяки, можно брать

Опробовано в лаборатории редакции или читателями.




 

Читательское голосование

Нравится

Статью одобрили 10 читателей.

Для участия в голосовании зарегистрируйтесь и войдите на сайт с вашими логином и паролем.
 

Поделись с друзьями!

 

 

Связанные материалы

 

Схема на Датагоре. Новая статья Грызём микроконтроллеры. Урок 7. Подключение к МК кнопок, клавиатуры, энкодера... Очень давно обещал продолжить цикл статей по работе с микроконтроллерами, но не было физической...
Схема на Датагоре. Новая статья Грызём микроконтроллеры. Урок 8. Программирование кнопок, клавиатуры, энкодера... Здравствуйте, дорогие Датагорцы! По некоторым слабо зависящим от меня причинам не мог участвовать в...
Схема на Датагоре. Новая статья Не стартует материнка от кнопки питания. Лечим очень нетривиальным методом... Приветствую читателей журнала Датагор! Есть у меня пожилой компьютер, которому уже исполнилось лет...
Схема на Датагоре. Новая статья Таймер от 1 секунды до 100 часов на микроконтроллере ATMEL AT89C2051... Картинка от Novelty Kitchen Timers В радиолюбительской практике частенько необходим таймер:...
Схема на Датагоре. Новая статья Ремонт зарубежных автомагнитол... Котунов А. В., Родин А. В. Ремонт зарубежных автомагнитол. — М.: СОЛОН-Пресс, 2003. — 176 с: ил. —...
Схема на Датагоре. Новая статья Проект «BRASS». Часть 2. Блок ДУ и mp3-модуль... Привет, камрады! Всех с майскими праздниками Мира, Труда, Радио и Победы! В первой части статьи о...
Схема на Датагоре. Новая статья Soft-start на MOSFET и выключатель питания для УНЧ и других устройств... Привет, друзья! Делал я как-то УНЧ с конденсаторами фильтра БП по 50.000 мкФ в плече. И задумал...
Схема на Датагоре. Новая статья Однофазный привод постоянного тока... В основе разработки электропривода лежит принцип работы следящего привода с одноконтурной системой...
Схема на Датагоре. Новая статья Простейший кодовый замок на реле, для начинающих... Начну с того, что на работе у меня стоял какой-то древний самодельный кодовый замок, который уже...
Схема на Датагоре. Новая статья Грызём микроконтроллеры. Урок 3. Циклы, прерывания и массивы... Эту статью я начну с провокационного вопроса… А какую конструкцию на основе МК хотите создать ВЫ?...
Схема на Датагоре. Новая статья Универсальный привод с Системой Импульсно — Фазового Управления... Регулятор служит не только для плавного регулирования оборотов двигателя постоянного тока, но в...
Схема на Датагоре. Новая статья Простой станочек для намотки + счетчик витков из калькулятора... Понадобилось мне в один прекрасный день намотать катушки, и сразу же возник вопрос как считать...
 

Комментарии, вопросы, ответы, дополнения, отзывы

 

<
Читатель Датагора

dimamukhin

<
Читатель Датагора

aleyer

<
Читатель Датагора

mars-73

<
Читатель Датагора

RazorBack

<
Читатель Датагора

Vikent

<
Читатель Датагора

xtrason

<
Читатель Датагора

DeN1S

<
Читатель Датагора

MerBas

<
Читатель Датагора

Vik84

Добавить комментарий, вопрос, отзыв 💬

Камрады, будьте дружелюбны, соблюдайте правила!

  • Смайлы и люди
    Животные и природа
    Еда и напитки
    Активность
    Путешествия и места
    Предметы
    Символы
    Флаги
 
 
В начало | Зарегистрироваться | Заказать наши киты почтой