- Динамическая индикация способом досчета
- Динамическая индикация | Программирование микроконтроллеров AVR
- Как работает динамическая индикация
- Схема подключения динамической индикации к микроконтроллеруATmega8
- Алгоритм написания кода для подключения динамической индикации
- Улучшаем программу для работы динамической индикации
- AVR Урок 11. Динамическая индикация. Часть 2
- Динамическая индикация
Динамическая индикация способом досчета
Путеводитель по журналу «Радио» 1981-2009 гг
Для Народного Хозяйства И Быта
Сигнализатор электронный СЭ-8
Охранное устройство для автомобиля.
Измеритель вибраций и перемещений
Болотов Б., Ситов В.
Фигурнов Е., Мрыхин С.
Для дистанционного измерения температуры от 0 до 150 градусов.
Автоматическая система зажигания
С регулятором угла опережения зажигания. Для мотоциклов с двухтактными двигателями.
Фигурнов Е., Мрыхин С.
Для дистанционного измерения температуры от 0 до 150 градусов.
Автоматическая система зажигания
С регулятором угла опережения зажигания. Для мотоциклов с двухтактными двигателями.
Бесконтактное реле времени
Мартынова Н., Чикваидзе Е.
Стабилизированный многоискровой блок зажигания
Измеритель энергии лампы вспышки
Петров В., Янишевский Н.
Бесконтактный датчик и индикаторы Ф207.
Три конструкции для сельского хозяйства
Купянский Г., Николаев В., Володарский В.
Частотомер для доильных аппаратов. Индикатор морозостойкости озимых культур. Индикатор мастита.
Блок управления тиристорами
Устройство защиты электродвигателя
Волик А., Марков А.
Для определения жирности молока.
Автоматический регулятор полива
Павлов Е., Чирков В., Штабный В.
Контролирующее устройство для автомобиля
Устройство управления электродвигателями
Пионтак Б., Скляр Е.
Стимулятор всхожести семян
Бобрицкий С., Ирха А., Федотовских Ю.
Комбинированная электронная система зажигания
Кодовый замок на МС
Индикатор для сельского электромонтера
Стабилизатор частоты вращения вала электродвигателя
Индикатор дефектов сварочных швов
Индикатор белка в молоке
Узел включения автосторожа
Блок управления садовым электронасосом
Устройство для подбора светофильтров
Масловский В., Шаповал В.
Простейший автомат для включения и выключения противоослепляющего устройства
Устройство для зажигания газа в плите
Алексаков Г., Терехов Г.
Фотореле на ИК-лучах
Широтно-импульсный регулятор напряжения
Ограничитель напряжения сварочного трансформатора
Источник
Динамическая индикация | Программирование микроконтроллеров AVR
Динамическая индикация широко применяется для отображения различной информации, например температуры, напряжения, времени или просто количества срабатывания каких-либо устройств или датчиков. Динамическая индикация на базе семисегментных индикаторов отлично согласуется в совместной работе с микроконтроллерами. Однако в литературе по программированию микроконтроллеров AVR данный вопрос рассмотрен очень поверхностно и далеко не в каждой книге, посвященной соответствующей тематике. Поэтому более подробно рассмотрим, как подключить семисегментный индикатор с динамической индикацией к микроконтроллеру, в данном случае – к ATmega8, но аналогия сохраняется для МК AVR любой серии.
По количеству разрядов (цифр) динамические семисегментные индикаторы бывают одноразрядные, двухразрядные, трехразрядные, четырехразрядные и очень редко – шестиразрядные. Основное внимание мы уделим четырехразрядным семисегментным индикаторам, как наиболее применяемому типу динамической индикации. Изготовляются они с общим анодом и общим катодом. Схемы соединения светодиодов отдельных сегментов представлены на рисунках.
Как видно из рисунков, каждый разряд, называемый digit, имеет свой отдельный общий в пределах разряда вывод. Поскольку рассматривается 4-х разрядная динамическая индикация, то таких выводы четыре – digit1, digit2, digit3, digit4.
Распиновка выводов 4-х разрядного семисегментного индикатора приведена на рисунке ниже. В данном случае показан вид сверху, то есть индикатор не нужно переворачивать вверх ногами.
Как работает динамическая индикация
Теперь рассмотрим, как работает динамическая индикация с общим катодом. Например, нам необходимо отобразить число 1987. Для этого следует в первый момент времени подать высокий потенциал на аноды сегментов, образующих единицу – b и c, а на общий катод первого разряда подать низкий потенциал. Общие катоды оставшихся трех разрядов – digit2, digit3 и digit4 остаются не подключенными.
Во второй момент времени получают питания сегменты, образующие цифру 9, общий катод второго разряда подключается к минусу, а digit1 теряет питание; digit2, digit3, как и раннее – остаются не подключенными.
В третий момент времени засвечивается цифра 8 на третьем индикаторе, а остальные индикаторы гаснут.
В четвертый момент времени получает питание последний индикатор и отображается цифра 7.
Далее все повторяется снова. При частоте переключений из разряда на разряда более 25 Гц за счет световой инерции светодиодов наши глаза не успевают заметить, как происходят переключения, поэтому визуально мы воспринимаем целостное свечение одновременно все разрядов.
Схема подключения динамической индикации к микроконтроллеру ATmega8
Сегменты динамической индикации будем подключать через токоограничивающие резисторы номиналом 330 Ом к выводам порта D микроконтроллера ATmega8. Выводы, отвечающие digit1, digit2, digit3, digit4 подсоединим через транзисторы n-p-n тип, например BC547 или 2n2222 к выводам порта B.
Если применять динамическую индикацию с общим анодом, тогда понадобятся биполярные транзисторы p-n-p типа, например BC557, эмиттеры которых нужно подсоединить к плюсу «+» источника питания, а коллекторы – к минусу «-» также через подтягивающий резистор 10 кОм. Принцип работы и подробные расчет транзисторного ключа описан ранее.
Алгоритм написания кода для подключения динамической индикации
Для большей конкретизации действий будем применять 4-х разрядный семисегментный индикатор с общим катодом. Первым делом следует создать массив цифр от 0 до 9. Этому мы уже научились ранее, вот здесь. Далее необходимо разбить 4-х значное число на четыре отдельных цифры. Например, число 1987 нужно разбить на 1, 9, 8 и 7. Затем единицу нужно отобразить в первом разряде индикатора, девятку – во втором, восьмерку – в третьем и семерку – в четвертом.
Среди многих алгоритмов разбивки многозначного числа на отдельные числа мы воспользуемся операциями деления и остатком от деления. Рассмотрим пример:
В языке С при использовании целочисленного типа данных int при выполнении деления все десятые, сотые и т. д., то есть все числа меньше единицы отбрасываются. Остаются только целые числа. Математическое округление здесь не работает, то есть 1,9 в данном случае будет 1, а не 2.
Команда “остаток от деления” обозначается знаком процента «%». Данная команда отбрасывает все целые числа и оставляет остальную часть числа. Например, 1987%1000 → 987; 1987%100 → 87; 1987%10 → 7.
Далее следует написать команду, которая сначала отобразит первый разряд и соответствующее ему число, потом, через некоторый промежуток времени, второй разряд и отвечающее ему число; и так далее. Ниже приведен код с комментариями.
#define F_CPU 1000000L
#include
#define CHISLO PORTD
#define RAZRIAD PORTB
unsigned int razr1 = 0, razr2 = 0, razr3 = 0, razr4 = 0;
unsigned int chisla [10] = <
// числа от 0 до 10
0x3f, 0x6, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x7, 0x7f, 0x6f
void vse_chislo (unsigned int rabivka_chisla)
razr1 = rabivka_chisla/1000; // тысячи
razr2 = rabivka_chisla%1000/100; // сотни
razr3 = rabivka_chisla%100/10; // десятки
razr4 = rabivka_chisla%10; // единицы
int main(void)
DDRB = 0b00001111;
DDRD = 0b11111111;
RAZRIAD = 0b00000001; // изначально 1-й разряд
CHISLO = 0x3f; // число 0
while (1)
vse_chislo(1987); // отображаемое число
RAZRIAD = 0b00000001; // включаем 1-й разряд, остальные выключаем
CHISLO = chisla [razr1]; // отображаем 1-ю цифру
_delay_ms(3);
RAZRIAD = 0b00000010; // включаем 2-й разряд, остальные выключаем
CHISLO = chisla [razr2]; // отображаем 2-ю цифру
_delay_ms(3);
RAZRIAD = 0b00000100; // включаем 3-й разряд, остальные выключаем
CHISLO = chisla [razr3]; // отображаем 3-ю цифру
_delay_ms(3);
RAZRIAD = 0b00001000; // включаем 4-й разряд, остальные выключаем
CHISLO = chisla [razr4]; // отображаем 4-ю цифру
_delay_ms(3);
Улучшаем программу для работы динамической индикации
Приведенный выше алгоритм является в большей степени обучающий, поэтому несколько упрощенный, но он также имеет место в программах, не выполняющих каких-либо быстрых расчетов в режиме реального времени. Единственным недостатком данного алгоритма является применение задержек, негативное влияние которых была рассмотрено ранее. Чтобы избавится от применения задержек можно применять прерывания от таймер-счетчиков. В ниже представленном коде задержки формируются с помощью нулевого таймер-счетчика и вызова прерывания по переполнению этого счетчика.
Для того, чтобы при каждом прерывании числа отображались последовательно в каждом разряде индикатора, добавлена переменная bc547, которая увеличивается на единицу при последующем вызове прерывания ISR (TIMER0_OVF_vect). Затем выполняется проверка значения переменной bc547 и получает питания соответствующий разряд. Когда bc547 становится больше четырех, происходит сброс в единицу.
Источник
AVR Урок 11. Динамическая индикация. Часть 2
Урок 11
Динамическая индикация
В прошлой части нашего занятия мы познакомились с принципом динамической индикации, собрали схему в протеусе.
Теперь закончим со сборкой и перейдём в проект, так как без соответствующего кода ничего работать на будет.
Начнем с порта B. Он у нас был сконфигурирован весь полностью на вход, но теперь так дело не пойдёт. Давайте половину порта сделаем на вход, а ту половину, где у нас подключены через транзисторы аноды индикаторов, сконфигурируем на выход. А подтягивающий резистор на ножке порта B переместим на другую ножку, к которой мы переподключили кнопку
DDRB = 0b00001111;
PORTB = 0b00100000;
Теперь, если мы соберём код и запустим его в протеусе, то у нас будут работать одновременно два индикатора. Это нам не подходит. Поэтому думаем дальше.
Прибавим разрядность переменной i. Пока под две цифры нам и char подойдёт, но на будущее нам этого не хватит. Поэтому сделаем это заранее
unsigned int i ;
И ещё нам под цифры каждого разряда потребуются также переменные
unsigned char R1 =0, R2 =0;
Также добавим ещё одну функцию, которая будет заниматься выводом двухзначной цифры на дисплей. Поэтому в качестве входного параметра здесь будет unsigned int. Добавим данную функцию перед функцией main()
void ledprint ( unsigned int number )
В данной функции мы распределим всю двухзначную цифру по разрядам.
Для этого мы применим математическую операцию, которая вычисляет остаток от деления. Обозначается она знаком %. Через данную операцию мы вычислим единицы. А затем, чтобы вычислить десятки, мы просто поделим на 10 входной параметр. Но так как у нас везде целочисленные операнды, то в результате получится целое число с выброшенным остатком, что и будет соответствовать десяткам, так как число у нас двухзначное
void ledprint ( unsigned int number )
R1 = number %10;
R2 = number /10;
А таймер мы сегодня применим не для того, чтобы он наращивал цифры, а для того, чтобы он поочерёдно зажигал цифры на индикаторах. Добавим ещё одну переменную. Добавить мы её также можем необязательно в начале файла, а можем непосредственно перед кодом функции-обработчика прерываний, главное чтобы переменная в функции уже была определена
unsigned char n_count =0;
И в зависимости от значения данной переменной, мы будем включать определённую ножку порта B, разрешая при этом вывод цифры на соответствующем индикаторе. Другую ножку порта мы будем отключать. Таже в том же условии мы будем вызывать функцию, которая будет включать комбинацию сегментов в зависимости от посланной переменной. Но так как определённая ножка порта B будет у нас отключена, то сегменты другого индикатора светиться на будут. Затем после всего этого мы будем прибавлять на 1 (инкрементировать) данную переменную. Но делать мы это будем до тех пор, пока она не достигнет значения 1. Вообщем, в связи с этим, переменная n_count будет равна либо 1, либо 0, так как пока у нас только 2 индикатора и соответственно будет только 2 варианта
if ( n_count ==0) < PORTB &=
(1 PORTB0 ); PORTB |=(1 PORTB1 ); segchar ( R1 );>
if ( n_count ==1) < PORTB &=
(1 PORTB1 ); PORTB |=(1 PORTB0 ); segchar ( R2 );>
n_count ++;
if ( n_count >1) n_count =0;
Теперь нам осталось только лишь в функцию ledprint() отправить какую-нибудь цифру. Давайте пока подадим любую и наращивать её пока не будем. Для этого мы вызовем функцию в main() после всех инициализаций, отправив в неё, например, число 97
ledprint (97);
Попробуем собрать проект и запустить его в протеусе. Мы видим, что код работает, динамическая индикация присутствует, но слишком наглядно, так как цифры светятся по очереди раз в 2 секунды.
Для наглядности работы динамической индикации это хорошо, но для постоянной работы не пойдёт. Глаз вообще не должен видимть динамику индикации. Должно быть впечатление, что цифры светятся постоянно.
Поэтому нам нужно настроить таймер на другую частоту. Попробуем порегулировать частоту делителем. Сделаем делитель 8 вместо 256 и, произведя нехитрые расчеты мы получим частоту 32. но так как у нас индикатора два, то получится на каждый по 16 герц. Этого конечно маловато, но попробовать можно. Чтобы нам выставить делитель 8, то мы в регистре TCCR1B должны включить бит CS11
TCCR1B |= (1 CS11 ); //установим делитель
Соберём код и посмотрим работу в протеусе. Вроде бы не мерцает. На живых индикаторах пока смотреть не будем. Если что, то потом подравим частоту. Пока займёмся счетчиком, нам нужно будет считать до 99, а затем начинать с нуля. Для этого раскомментируем весь код в бесконечном цикле, также раскомментируем переменные для кнопки
unsigned char butcount =0, butstate =0;
Также, раз уж считать мы будем до 99, то также исправим код вот здесь
То есть мы попробуем также кнопкой обнулять счётчик. Но так как мы кнопку переключили на другой пин, то нужно немного подправить проверяемое значение
if (!( PINB &0b00100000))
Также вместо функции segchar будет функция ledprint
ledprint ( i );
Ну, собственно, и всё.
Соберём наш код и проверим его сначала в протеусе. Всё у нас считается и сбрасывается кнопкой. Отлично!
Теперь прошьём контроллер и посмотрим на живых индикаторах работу кода.
Код работает, но индикаторы мерцают. Поэтому немножко ещё поиграем с частотой в таймере. Если убрать делитель совсем, то эксперементальным путём было выявлено, что наши индикаторы перестанут светиться вообще. Этот эксперимент вы можете увидеть во второй части видеоурока (ссылки на видеоурок внизу, достаточно кликнуть по нужной картинке, в принципе, как и в любом уроке). Поэтому придется нам поиграть с цифрой в регистре OCR1A. Причём мы докажем, что виновата не слишком высокая частота, а то, что без делителя просто отказывается работать таймер. Поэтому цифру мы рассчитаем так, чтобы частота при делителе была примерно такая же как и без делителя, но на предыдущем значении в OCR1A. Цифру мы получим примерно 3906. Превратим её в двоичный вид и занесём в регистровую пару OCR1A. Код станет вот таким
OCR1AH = 0b00001111; //записываем в регистр число для сравнения
OCR1AL = 0b01000010;
Теперь, если собрать код и прошить контроллер, мы увидим, что всё работает как надо
Программатор и индикаторы можно приобрести здесь:
Источник