» » Микроконтроллеры. Связь с внешним миром. Часть 3.

 
 
 
10

Микроконтроллеры. Связь с внешним миром. Часть 3.

Разместил Spirit 20 января 2010. Просмотров: 27 282

И снова приветствую Вас в моей лекционной!
На этот раз я расскажу Вам как "сэкономить" выводы микроконтроллера, не ограничивая функциональности органов управления.
Десяток кнопок по одному проводу.

Для управления устройством далеко не обязательно подключать каждую кнопку к отдельному выводу МК. Например, если в вашем устройстве есть "лишний" вход аналого-цифрового преобразователя (АЦП, 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 загружен 219 раз.
Владимир (Spirit)
Старый Оскол
Профиль Spirit
Электронщик-практик, в основном занимаюсь микроконтроллерами. Есть неплохой опыт и в аналоговой технике (все мы начинали с УМЗЧ =)).
Одержим идеей автоматизации жилища а-ля "Умный дом" =)
 

Понравилось? Палец вверх!

  • всего лайков: 15

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

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


Схема на Датагоре. Новая статья Soft-start на MOSFET и выключатель питания для УНЧ и других устройств... Привет, друзья! Делал я как-то УНЧ с конденсаторами фильтра БП по 50.000 мкФ в плече. И задумал...
Схема на Датагоре. Новая статья Таймер от 1 секунды до 100 часов на микроконтроллере ATMEL AT89C2051... Картинка от Novelty Kitchen Timers В радиолюбительской практике частенько необходим таймер:...
Схема на Датагоре. Новая статья Простейший кодовый замок на реле, для начинающих... Начну с того, что на работе у меня стоял какой-то древний самодельный кодовый замок, который уже не...
Схема на Датагоре. Новая статья Схемка в блокнот. Реле времени на КМОП микросхемах... Иногда возникает необходимость отключать (или включать) нагрузку по истечении определенного...
Схема на Датагоре. Новая статья Сделай сам станочек для намотки + счетчик витков из калькулятора: быстро и сердито... Понадобилось мне в один прекрасный день намотать катушки, и сразу же возник вопрос как считать...
Схема на Датагоре. Новая статья Микроконтроллеры. Связь с внешним миром. Часть 2... Здравствуйте, дорогие Датагорцы! По некоторым слабо зависящим от меня причинам не мог участвовать в...
Схема на Датагоре. Новая статья Регулятор громкости на TDA7313 и PIC 16F876A.... Для новой конструкции мне понадобился блок управления громкостью и тембрами. Я выбрал...
Схема на Датагоре. Новая статья Микроконтроллеры. Связь с внешним миром. Часть 1. Клавиатура... Очень давно обещал продолжить цикл статей по работе с микроконтроллерами, но не было физической...
Схема на Датагоре. Новая статья Однофазный привод постоянного тока... В основе разработки электропривода лежит принцип работы следящего привода с одноконтурной системой...
Схема на Датагоре. Новая статья Универсальный привод с Системой Импульсно — Фазового Управления... Регулятор служит не только для плавного регулирования оборотов двигателя постоянного тока, но в...
Схема на Датагоре. Новая статья Грызем микроконтроллеры. Урок 3.... Эту статью я начну с провокационного вопроса… А какую конструкцию на основе МК хотите создать ВЫ? ...
Схема на Датагоре. Новая статья Ремонт зарубежных автомагнитол... Котунов А. В., Родин А. В. Ремонт зарубежных автомагнитол. — М.: СОЛОН-Пресс, 2003. — 176 с: ил. —...
<
  • Гражданин
20 января 2010 01:33

Дима / dimamukhin

Цитата
  • С нами с 9.04.2009
  • Ушёл в реал Пользователь offline
  • 12 комментариев
  • 0 публикаций
 
  • 0
Как всегда , понятно и доходчиво ! 5 +

Молодец smile


<
  • Прохожий
20 января 2010 04:53

/ aleyer

Цитата
  • С нами с --
  • 0 комментариев
  • 0 публикаций
 
  • 0
Очень вовремя получилось, как раз пригодилась информация о том, как использовать АЦП. Побольше бы таких практичных и доступных для понимания статей на разную тематику smile Спасибо!

<
  • Прохожий
20 января 2010 10:55

/ mars-73

Цитата
  • С нами с --
  • 0 комментариев
  • 0 публикаций
 
  • 0
Владимир, а в какой версии протеуса создан
проект находящийся в архиве ?

<
  • Прохожий
20 января 2010 13:52

/ RazorBack

Цитата
  • С нами с --
  • 0 комментариев
  • 0 публикаций
 
  • 0
Спасибо, отличная статья. Продолжение будет?

<
  • Кандидат
21 января 2010 03:44

Виктор / Vikent

Цитата
  • С нами с 28.12.2009
  • Ушёл в реал Пользователь offline
  • 5 комментариев
  • 0 публикаций
 
  • 0
Спасибо за статью!

<
  • Прохожий
22 января 2010 16:39

/ Spirit

Цитата
  • С нами с --
  • 0 комментариев
  • 0 публикаций
 
  • 0
mars-73
Proteus 7.6 SP0

<
  • Кандидат
26 января 2010 03:15

Игорь / xtrason

Цитата
  • С нами с 4.10.2009
  • Ушёл в реал Пользователь offline
  • 6 комментариев
  • 0 публикаций
 
  • 0
Ну Вова, как всегда, молодец!!! Как раз вовремя... надо было к проекту на 16 меге кнопки прикрутить, а как сделать лучше - не знал... Теперь знаю!!! Ура!!! winked

<
  • Прохожий
9 апреля 2010 20:06

/ DeN1S

Цитата
  • С нами с --
  • 0 комментариев
  • 0 публикаций
 
  • 0
отличная статья, но 0,0025В * 256 = 0,64В, это там где про ацп

<
  • Гражданин
22 января 2011 16:34

Александр / MerBas

Цитата
  • С нами с 8.12.2010
  • Ушёл в реал Пользователь offline
  • 19 комментариев
  • 0 публикаций
 
  • 0
Володя,спасибо за интересную лекцию.Напряжение показывает отлично,я тут-же попробовал определить номера кнопок.Пришлось подобрать резисторы,получилось!Но когда не нажата ни одна из кнопок-индикатор высвечивает не ноль.
Замена строчки:
PORTB=read_abc(0)
на:
unsigned int i;
i=read_adc(0);
if(i>6)i=0;//6 кнопок
PORTB=i;
и индикатор стал показывать правду
Конечно надо-бы так:
if(i=read_adc>6)i=0;
но мой CodeVision это не переварил...

<
  • Прохожий
1 ноября 2012 15:03

/ Vik84

Цитата
  • С нами с --
  • 0 комментариев
  • 0 публикаций
 
  • 0
Спасибо за статьи! Продолжение будет?
И другой вопрос, выставить на Таймере 0 частоту 0,977kHz в CVAVR нет возможности, но сравнив код, если я выставляю минимальной значение = 7.813kHz в бите TCCR0=0x05 тоже самой что и при частоте 0,977kHz, т.е. это одно и тоже?

Добавление комментария


Налетай! Паяльники, станции, жала с доставкой
  • smilelolbyewinkyahoocoollaughing
    crazybadcryingsadirefulsickstraight
    ballooncakegooddrinksmailbombsun
    nightrainstarscolddashguitar-manhandshake
    musicnegativenopardonshoksleepunknown
    wackoyawnblushbullyhashsmokingwhew
Скопируйте текст вашего комментария на случай неверного ответа на контрольный вопрос.