Комрады, прошу помощи. Попался мне в лапы интересный дисплейчик от электронной сигареты. Очень кстати он подходит мне в проект термостата для портативного холодильника, но есть один нюанс - я с подобным никогда не работал, так что пытаюсь его освоить. Суть вот в чем: у дисплея сегменты подключены по методу чарлиплексинга и выведены на 6 выводов. Таблицу соответствия выводов и полярностей для каждого сегмента я сделал и все расписал, так что с этим вопросом не обращаюсь, мне нужен совет по подключению этой музыки к МК и реализации работы программы. Как вижу это я: каждый сегмент дисплея кодируется 6-ю байтами и заносится в массив, еще один массив такого же размера будет хранить 6-ти байтовую маску выводов порта, которые должны быть включены на выход во время индикации сегмента. Занимаем 1 порт контроллера под дисплей, индикация динамическая. Для отображения сегмента пишем в регистр порта нули, переводим весь порт на вход, чтобы погасить весь индикатор, затем пишем в в порт соответствующий нужному сегменту байт из массива и включаем нужные ножки порта на вывод записью соответствующей маски сегмента в регистр направления порта. После задержки продолжаем вывод следующего сегмента по вышеописанному алгоритму. Правильно ли такое решение, или я где-то ошибаюсь? Будет ли работать в таком режиме порт ввода-вывода. Работать будем с AVR.
UPD: не приложил фото дисплея, исправляюсь.
Морда:
Со стороны хвоста:
_________________ Не важно чем все начнется. Важно чем кончится!
roman.com, ну во первых начнем с того, что ваш пример кода не заработает как надо, а начнется полная ахинея. Во вторых предложение подключить по указанной схеме меня немного смущает: вы мне предлагаете дисплей расковырять и переразвести его? Он, как бы уже собран на заводе и его схема конечна и неизменна. В третьих, расписывать такую простыню после исправления для каждого кадра как минимум неэтично.
_________________ Не важно чем все начнется. Важно чем кончится!
Martian, К сожалению только размытыми фразами. Я же задал конкретный вопрос, расписав алгоритм работы так, как вижу его сам, с просьбой посмотреть и поправить, если я в чем то неправ.
_________________ Не важно чем все начнется. Важно чем кончится!
Не только размытыми, есть несколько статей, где всё полностью описано, с исходным кодом.
воспринимать алгоритм в таком описании сложно. есть Дракон, блок-схемы и т.д. Ваша задача - обычная динамическая индикация. Погасили все, затем определили и высветили все возможные сегменты в текущем кадре, и так бесконечно. В ленте столько кадров, сколько надо для отображения 888 Я бы больше переживал за электрическую часть - меня всегда напрягает непосредственное подключение светодиодов к микроконтроллеру при динамической индикации. При соблюдении нормальных условий яркость может оказаться недостаточной.
Martian, ну реализую, видно будет. Насчет яркости думаю проблем не будет, это индикатор все же, а не новогодняя елка. Меня больше смущает другой вопрос: при выводе каждого сегмента сначала порт настраивается на высокоимпендансное состояние, то бишь на вход. По моей логике я сначала пишу в регистр PORTx требуемое значение, а потом по маске включаю порт на выход записью в регистр DDRx той самой маски. Правильная ли очередность, или сначала надо порт на выход, а потом писать в него? Свой метод я применяю, отталкиваясь от логики работы той же 74hc595.
_________________ Не важно чем все начнется. Важно чем кончится!
Я не знаю устройства AVR, но попробовал бы так (запись в порт, а потом установка как выход). Если сначала на выход, а потом запись, то потом необходим сброс в ноль, лишняя операция, будет жаль, если так...
Таки дисплей я осилил этот, пока допиливаю код на полноценную работу с ним, но вывод информации проблем не составил. Яркость при частоте обновления 50 Гц вполне неплохая. И да, на свой же вопрос нашел ответ - разницы в очередности записи в регистры порта в принципе нет - работает все в любом порядке. А дисплей, вот он:
_________________ Не важно чем все начнется. Важно чем кончится!
В общем я таки добил этот дисплей, работает неплохо. Писал в Arduino IDE - никак с нее слезть проклятой не могу. Замечания к коду и битье тапком по морде приветствуются, кто в программировании разбирается, прошу глянуть и натыкать мордой в глупости. Описание работы программы в шапке кода подробно разжевано.
Кино про дисплей: Спойлер
Код: Спойлер
Код:
/* Программа написана в среде Arduino IDE. Использован МК AtMega328 c внешним кварцем 16МГц. _____ Подключение индикатора: | 1 | 2 | 3 | 4 | 5 | 6 | | PD0 | PD1 | PD2 | PD3 | PD4 | PD5 | ---------- Сегменты по банкам: 1) A, B, C, D, E, F, G; 0) A, B, C, D, E, F, G;
Логика работы программы следующая: Для работы используется прерывание таймера 1. Контроль работы а так же порядок выполнения операций осуществляется посредством счетчика на инкрементируемой переменной dyncounter. Частота прерываний - 10КГц. Для вывода данных на индикатор в данный момент используется 16-ти байтный буфер buff[16], представляющий из себя одномерный массив содержащий информацию для каждого из 16 сегментов в виде [A2,B2,A1,B1,C1,D1,E1,F1,G1,A0,B0,C0,D0,E0,F0,G0]. При выводе на индикатор в соответствии со значением dyncounter в регистр данных порта PORTx записываются данные сегмента из ячейки буфера, а в регистр направления порта DDRx соответствующая маска сегмента из массива segmentmask[16].
Функция buffops() занимается подготовкой выходных данных. Во время ее работы вывод информации на дисплей запрещен чтобы отображаемые данные были достоверными. Исходное число val в десятичном формате разбивается на разряды функцией digdisass() и помещает его в переменную vals[2]. Всвязи с особенностью дисплея отображать в старшем разряде только единицу? отображение этого разряда происходит по признаку val>=100. Если условие верное, показываем единичку, если нет, молчим в тряпочку. Она проверяет и в случае необходимости включает старший разряд индикатора, по очереди берет исходное число, разбитое на десятки и единицы из массива vals[2] и по битовой маске числа, соответствующей необходимым сегментам на дисплее, заполняет буфер вывода по следующей системе: переменной outseg1 присваивается значение битовой маски из массива segments1, где записаны битовые маски для чисел от 0 до 9. путем сдвига на 1 влево обрезается ненужный старший бит, так как каждый символ кодируется только 7-ю битами. в цикле каждый бит переменной segments1 сравнивается с маской digitmask, и пишет в выходной буфер данные для каждого из сегментов. В случае совпадения в соответствующую ячейку буфера будет записано значение из массива segments1, где содержатся битовые маски для отображения сегментов первого разряда, в случае несовпадения будет записан 0, означающий, что текущий сегмент зажигать не надо. Здесь же присутствует операция гашения незначащего разряда, если исходное число меньше 10. Заполнение осуществляется от сегмента A1 до сегмента G1. Далее таким же способом заполняется буфер для сегментов A0-G0, после чего снимается запрет на вывод дисплей и останавливается работа с буфером до полного обновления индикатора.
В программе присутствует переменная timecontr. Она нужна для автоинкремента исходного числа val в прерывании. Данная функция нужна для демонстрации работы программы.
Отображение символов пока не реализовано, оно ничем не отличается от отображения символов, необходимо увеличить обьем выходного буфера на 6 байт и дописать в функцию работы с буфером обработку символов. мне, как истинному коту пока лень ))))
if (++timecontr >= 1500) { if (++val >= 200) { // проверка только тогда, когда произошло приращение, а не всегда, выглядит более логичной val = 0; } timecontr = 0; } }
Это тоже можно записать более лаконично: outseg0 <<= 1; - читается даже проще, а использование лишь одного идентификатора уменьшает вероятность опечатки
Добавлено after 6 minutes 39 seconds:
Код:
void digdisass() { if (val >= 100) { vals[1] = (val - 100) / 10; vals[0] = val % 10; } if (val < 100) { vals[1] = val / 10; vals[0] = val % 10; } }
немного можно упростить:
Код:
void digdisass() { if (val >= 100) { vals[1] = (val - 100) / 10; } else { vals[1] = val / 10; } vals[0] = val % 10; }
Martian, Огромное спасибо за замечания. buffupdate можно вообще убрать, а вывод на индикатор ограничить значением счетчика dyncounter - надо было сразу так сделать, хорошо, что подсказали. Способ записи и проверки инкремента тоже утащил в уголок, буду теперь так делать. Со сдвигом битов я пока хреново дружу - сказывается обучение программированию с помощью ардуино - сейчас активно с него пытаюсь слезть. Я неправильно записывал выражения и они у меня просто не работали, поэтому пришлось извращаться. Например, вместо outseg0 <<=1; чукча писал outseg0 << 1; Внезапно это не работало , поэтому старым добрым железобетонным методом писал outseg0 = outseg0<<1. Это то работает.
Связка if()...else() у меня иногда выдает проблемы - неоднократно нарывался на неадекватно работающий код. Я же пока только учусь, вот уже и от delay и millis отучился вроде.
Добавлено after 13 minutes: В моем решении есть еще один недочет, который надо будет исправить - я для управления 6-ти выводным индикатором полностью занимаю весь 8-ми битный порт целиком. Надо будет перекошачить немного код, добавить запись в порт по маске требуемых выводов, чтобы остальные не трогать. Будет время, переделаю, а то 2 пина вникуда. То есть на вход все время
Добавлено after 20 minutes 2 seconds: Может это в виде статьи оформить и выложить тут же на сайте? Сам же информацию подробную недавно искал про такие индикаторы.
_________________ Не важно чем все начнется. Важно чем кончится!
Martian, тады вечерком добавлю управление символами и забузолю в статью. Спасибо за помощь, при написании статьи буду ссылаться на того, от кого получил знания.
_________________ Не важно чем все начнется. Важно чем кончится!
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 20
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения