Наконец-то появилось немного свободного времени, так что продолжим..
Напишем программу, которая будет выводить число от 0 до 999(при желании
количество разрядов можно увеличить) на светодиодный-семисигментный
индикатор по прерыванию от таймера.
Немного теории.
Перед выводом числа на индикатор его нужно преобразовать.
Будем преобразовывать из двоичного числа в двоично-десятичное, т.е.
число 0 равно 0000,
1 = 0001,
2 = 0010,
3 = 0011,
4 = 0100,
5 = 0101,
6 = 0110,
7 = 0111,
8 = 1000,
9 = 1001.
Алгоритм преобразования такой:
Сначала сравниваем - наше число больше ста или меньше, если больше вычитаем из него 100 и
опять сравниваем, и так пока оно не окажется меньше 100. Считаем сколько было
вычитаний, значит столько у нас и сотен. С оставшимся числом ,после вычитаний сотен,
проделываем тоже самое, только вычитаем десятки, а то что останется это - единицы.
Например число 567:
Оно больше 100, значит вычитаем 100, получаем 467. Опять больше 100, опять вычитаем 100.
Всего сотня отнимется 5 раз - значит у нас пять сотен, запомнили это число.
Остается 67, десять у нас отнимется 6 раз - значит у нас шесть десятков.
Остаток 7, так и оставляем.
В итоге в двоично-десятичном виде 567 будет выглядеть так: 101 110 111.
Выводить на индикатор будем динамически. Т.е. каждый разряд будет гореть какое-то время,
по очереди. Чтобы глаз не видел мерцание разряда - разряд должен обновляться с
частотой не менее чем 50Гц. Т.к. у нас 3 разряда - частота должна быть не менее 150Гц.
Теперь программа.Я взял индикатор с общим анодом, но при необходимости программу легко изменить для
индикатора с общим катодом.
Вывод на индикатор будет происходить по прерыванию от таймера. Т.е. при написании основной
программы уже не нужно будет зацикливаться на индикаторе(хотя для высокоточных приборов
учет необходим).
Рис1.Настройка таймера.
Время рассчитывается по такой формуле t=TCNT * Fкв/Kдел , где
t - нужное время,
TCNT - число в счетном регистре,
Fкв - частота кварца,
Kдел - коефициент деления пределителя.
Возьмем для обновления разряда 100Гц, тогда для 3 разрядов будет 300Гц.
Значит прерывание от таймера должно происходить каждые 1/300 = 0,0033сек.
Частоту кварца берем 4МГц, коефициент пределителя берем 64, тогда по формуле
TCNT = 0,0033 * 4000000 / 64 = 206.
Теперь в счетный регистр записываем 255-206=49 Т.К. прерывание происходит при переполнении
счетного регистра.
1->TOIE0 - разрешаем прерывание от таймера Т0.
1->NUMB_RAZR - устанавливаем с какого разряда начинаем выводить числа.
456->INDIK - здесь хранится число, которое будет выводиться на индикатор.
При выполнении основной программы его можно просто менять, а при
прерывании оно автоматически будет выводиться на индикатор.
BIN_V_DEC - подпрограмма, которая будет преобразовывать наше число из
двоичного кода в двоично-десятичный.
Остальное вроде понятно.
Рис2.Эта подпрограмма будет преобразовывать наше число из
двоичного кода в двоично-десятичный. Ее нужно вызывать всегда после
обновления числа в регистре INDIK.
^PERV
^VTOR
^TRET - это мы очищаем старые значения.
INDIK->TEMP_INDIK - здесь просто копируем наше число в другой регистр
для преобразования, чтобы наше число не затерлось.
Дальше алгоритм как я описал в теории.
В регистрах PERV, VTOR и TRET хранится наше число в двоично-десятичном коде.
Рис3.Timer_0_Overflow - это метка с которой будет обрабатываться прерывание от таймера.
SREG-> - это мы сохраняем содержимое регистра SREG в стеке, чтобы в
случае изменения его при прерывании вернуть прежнее значение в основную программу.
Желательно это делать при обработке каждого прерывания.
VIVI_V_INDIK - вызов подпрограммы, которая будет выводить число в индикатор.
255-206->TCNT0 - для того чтобы следующее прерывание произошло через 0,0033сек.
->SREG - восстанавливаем SREG из стека.
RETI - выход из обработки прерывания.
Рис4.Это подпрограмма, которая будет непосредственно выводить число на индикатор.
NUMB_RAZR <= 3 - здесь проверяем все разряды вывели или нет. Если третий
разряд вывели то начинаем опять с первого.
NUMB_RAZR = 1
NUMB_RAZR = 2
NUMB_RAZR = 3 - это мы проверяем какой разряд выводить, и соответственно
достаем число(в двоично-десятичном коде) для нужного разряда.
INDIK < 10
INDIK < 100 - проверка для того, чтобы не выводить 024 или 005, а выводить 24 и 5, будем
крайние нули гасить.
Razr_gash - эта подпрограмма как раз и гасит наш разряд.
Razr_1
Razr_2
Razr_3 - эти подпрограммы зажигают необходимый разряд, выводя на него "0", а на
остальные "1" (если индикатор с общим анодом).
PERV->TEMP
VTOR->TEMP
TRET->TEMP - здесь копируем двоично-десятичный код во временный регистр.
TEMP = 0
TEMP = 1
TEMP = 2
TEMP = 3
TEMP = 4
TEMP = 5
TEMP = 6
TEMP = 7
TEMP = 8
TEMP = 9 - здесь проверяем какое число нужно вывести в индикатор.
Cif_0
Cif_1
Cif_2
Cif_3
Cif_4
Cif_5
Cif_6
Cif_7
Cif_8
Cif_9 - подпрограммки, которые устанавливают на ногах микроконтроллера
необходимые уровни, для формирования числа на индикаторе.
NUMB_RAZR++ - увеличиваем номер разряда на 1 для вывода следующего разряда.
Рис5.Это подпрограмки, которые устанавливают необходимые уровни на ногах
микроконтроллера.
Тут вроде все ясно.
Чтобы изменить программу для индикатора с общим катодом нужно просто
поменять все "0" на "1", а "1" на "0".
Рис6.Здесь даем имя каждой ноге микроконтроллера.
Теперь для оптимизации разводки платы индикатор можно подключать к любым ногам
микроконтроллера(к портам), а в программе необходимо только изменить порты.
Например segA PORPD.0 на segA PORTC.4. Далее только скомпилировать программу - и все.
А, ну и конечно в начале программы настроить порты на выход.
Рис7.Здесь тоже все должно быть понятно - даем имена регистрам, с комментариями.
Рис8.Ну, это схема – тут тоже все ясно.
Рис9.Это работа в Proteus.
Поставил инверторы т.к. с транзисторами подтормаживала. Но в работоспособности
программы убедиться можно.
Рис10.Ну а это уже в железе.
В прикрепленном файле находятся программа в AB и схема для Proteus’а.
Надеюсь материал будет кому-то полезен и труд останется замечен.
Если есть вопросы - задавайте.
От замечаний и пожеланий тоже не откажусь.
С уважением Kotjara.
Присоединённый файл ( Кол-во скачиваний: 1550 )
Проги.rar