как нарисовать анимацию, я понял.
Спойлер//ATMEGA328
//ВЫВОДЫ ATMEGA328 НА СЕГМЕНТЫ
#define A 1
#define B 4
#define C 16
#define D 64
#define E 128
#define F 2
#define G 8
int h1,h0,m1,m0; // h1 - десятки часов, h0 - еденицы часов и так далее
unsigned char digit_out[4], // буфер экрана (нумерация от 0 до 3 плюс четвертый невидимый разряд)
cur_dig; // тек.высвечиваемый символ (позиция)
unsigned char digits[] = {
(A+B+C+D+E+F), // 0
(B+C), // 1
(A+B+D+E+G), // 2
(A+B+C+D+G), // 3
(B+C+F+G), // 4
(A+C+D+F+G), // 5
(A+C+D+E+F+G), // 6
(A+B+C), // 7
(A+B+C+D+E+F+G), // 8
(A+B+C+D+F+G), // 9
(A+B+C+E+F+G), // A - 10
(C+D+E+F+G), // b - 11
(A+D+E+F), // C - 12
(B+C+D+E+G), // d - 13
(A+D+E+F+G), // E - 14
(A+E+F+G), // F - 15
(A+E+F), // Г - 16
(A+B+F+G), // 17 - символ градус цельсия
(0), // 18 - пусто
(C+E+G), // n - 19
(D+E+F+G), // t - 20
(A+B+C+E+F), // П - 21
(B+C+E+F+G), // Н - 22
(A+B+E+F+G), // Р - 23
(A+C+D+E+F+G), // Б - 24
(D+E+F), // L - 25
(E+G), // r - 26
(A+C+D+F+G), // S - 27
(E+F), // I - 28
(A+D+E+F+C), // G - 29
(A), // - - 30
(B), // _ - 31
(C), // - - 32
(D), // _ - 33
(E), // - - 34
(F), // _ - 35
(G), // - - 36
(A+E+F+B), // M - 37
(F+A+B+C) // M - 38
};
void setup() {
DDRD = 0xFF; // порт D на OUTPUT
DDRB = 0xFF; // порт B на OUTPUT
cli();
TCCR1A = 0b00000000; // OC1A Отключен
TCCR1B = 0b00001011; // делитель 64, сброс при совпадении 1A (режим СТС)
OCR1A = 0x041; // 5ms
TIMSK1 = 0b0000010; // запусе прерывания А таймера 1
sei();
}
void loop() {
h1=2; //тут будем читать потом время
h0=3;
m1=1;
m0=4;
/*
(A), // - - 30
(B), // _ - 31
(C), // - - 32
(D), // _ - 33
(E), // - - 34
(F), // _ - 35
(G), // - - 36
*/
for (byte i =0; i<7;++i){ // это сколько кадров
unsigned int AA[] = {30,31,32,33,34,35,h1};
unsigned int BB[] = {35,34,33,32,31,30,h0};
unsigned int CC[] = {30,31,36,35,m1,m1,m1};
unsigned int EE[] = {30,36,33,34,32,35,m0};
Надо помедленнее, покадрово бы посмотреть, станет понятнее, что в каком порядке включается/выключается.
А так то в принципе он там сами цифры не трогает, а эффекты сделаны методом наложения посегментной маски по AND для гашения части сегментов. То есть, эффект представляет собой отдельный алгоритм, накладываемый на сегменты в процессе динамической индикации.
Как это реализовать. То есть, нужно иметь карту анимации всех сегментов в виде массива N*7*4 элементов, в котором N - количество кадров анимации, 7 - число сегментов, 4 - число разрядов. В массиве 1 означает пропускание сигнала на сегмент, 0 - запрет включения сегмента. И дальше при запуске эффекта через операцию AND эта маска подмешивается к формирователю выходных состояний индикации.
С анимационными эффектами конечно нужно поработать в плане красивости. Для этого нужно медленно покадрово просмотреть показанное видео и записать всё по порядку в карту анимации.
2Serzh2000. Самый простой и тупой способ следующий: 7 сегментов. Дискретность времени мультиплексирования делаем кратно 7. Точка живёт сама по себе. Либо подумать.
Маски.
Скажем, нужно вывести по сегментно. Делаем маски:
Seg_A - 0x00000001
Seg_B - 0x00000010
Seg_C - 0x00000100
Seg_D - 0x00001000
Seg_E - 0x00010000
Seg_F - 0x00100000
Seg_G - 0x01000000
Теперь мы делаем так:
Нам нужно вывести 1234. Сами нарисуйте. У нас кратно 7. Первый такт. Маска A. В этот момент будут выводиться только сегменты A. И так далее. Нужна синхронизация. Чтобы первый выводимый символ совпадал с сегментом A.
Как то так. На каждый эффект свой алгоритм и свои маски.
Я создавал графические конструкторы. Есть программы, редакторы 7 сегментных дисплеев. Там тебе сразу и хексы сегментов выдает.
Если что, пиши в личку. Поэкспериментируем.
Ух, давно я не занимался семисегментниками.
Как я уже говорил, суть в чем должна быть: ни символы цифр, ни переменные, хранящие активируемые сегменты, не изменяются в процессе анимации. А при выводе каждого разряда в процессе динамическоей индикации происходит наложение маски эффекта по логическому AND на сегменты текущего разряда. Этот метод позволяет не влиять на формирование символов цифр, но независимо добавлять анимированный эффект гашения сегментов в разрядах в любом порядке по карте анимации
.
То есть, функция, реализующая динамическую индикацию, должна выглядеть вот в таком виде:
через интервал переключения разрядов вызывается эта функция, она для каждого текущего разряда индикатора берет из таблицы анимации значение накладываемой маски и накладывает по AND эту маску на данные для отображения сегментов в текущем разряде. Когда анимация остановлена, маска возвращается 0xFF, пропуская все сегменты. Текущая маска сегментов всего индикатора переключается другой функцией, ответственной за непосредственно воспроизведение анимации.
Логическая операция AND (и)
AND обозначается знаком &.
Оператор AND выполняется с 2-мя битами, возьмём, к примеру, a и b. Результат выполнения операции AND равен 1, если a и b равняются 1. В остальных случаях результат равен 0. Например, с помощью AND мы можем вкл/выкл сегмента по нашему массиву эффектов
вот почти понимаю ... разжуйте еще немного желательно с примерами
Операция побитового AND между двумя числами с удовольствием применяется для наложения так называемой маски на число.
То есть,
0110 1111 - число
&
0001 1110 - маска
=
0000 1110 - результат. Только совпадение 1 в одноименных позициях битов числа и маски пропускает на выход 1 в этой позиции бита, а где нет совпадения - там бит на выход 0. Это свойство и используется для гашения разрядов, не влияя на исходные данные символа.
Щас, допишу до полноценной анимации, соберу на макетке, попробую показать. Давно с семисегментниками не работал уже.
Ааа, вон чо.. Ну так я пишу только для STM32, на AVR уже давно ничего не делаю. Поэтому полный код будет вам непонятен.
На том видео показан индикатор, работающий в режиме динамической индикации. Сегменты A-G всех четырех разрядов запараллелены, поэтому чтобы отобразить разные цифры в каждом разряде, в один момент времени активируется только один разряд. Индикаторы различаются по направлению светодиодов - с общим анодом (CA) и с общим катодом (CC). У индикатора CC чтобы зажечь сегмент, нужно на вывод разряда подать 0, а на выводы сегментов подавать высокие уровни.
Порядок работы с дин.индикацией будет таков
* Отображение первого разряда:
- погасить все сегменты
- активировать разряд 1 (подав на него низкий уровень) и деактивировать разряды 2,3,4 (подав на них высокие уровни)
- подать на сегменты нужную комбинацию для первого разряда, и он включится
*Выждать интервал времени, равный 1/4 периода дин.индикации.
* Отображение второго разряда:
- погасить все сегменты
- активировать разряд 2 и деактивировать разряды 1,3,4
- подать на сегменты нужную комбинацию для второго разряда
...и так далее до последнего разряда, и далее по кругу. Гашение сегментов перед сменой активированных разрядов нужно для исключения паразитной засветки сегментов в соседнем разряде. Интервалы переключения разрядов задаются каким-нибудь таймером и функция переключения разрядов вызывается в прерывании этого таймера. Весь круг индикации проходит например за 1/80 с, таким образом интервал переключения разрядов - 1/(80/4) = 1/20 или 0,05 с.
Такая хитрая посегментная анимация делается, как я показал выше, с помощью наложения маски сегментов. А анимация "бегущая строка" делается просто изменением содержимого переменных, хранящих данные сегментов для каждого разряда. Эти переменные - как раз и есть массив buf[4].
2Serzh2000. Развивайте у себя алгоритмическое мышление. Любой проект, даже рукоблудие выходного дня состряпанное на коленке левой пяткой рассматривается как полноценный проект. Это развивает отношение к своему труду.
Мне в свое время тоже это сказали. Берете бумагу, карандаш, стирательную резинку. И начинаете проектировать. Проектирование сверху вниз. Верх - это устройство в целом. Функционал, интерфейс. И начинаем дербанить на кубики. Эти кубики вы тоже дербаните. На каждом этапе анализируете. Представьте себе это устройство и кубики. Взаимодействие кубиков. И рисуйте, рисуйте. Да, лень порой. Переламывайте. Смотрите внутри себя на будущий результат.
Декомпозиция, анализ, синтез.
вот есть, к примеру число h1=2;
из сегментов оно выстраивается так
DDRB = 0b11101101; //2
мне нужно читать биты в произвольном порядке и записывать и в переменную rezultat
DDRB = 0b11101101; // читаем
rezultat = 0b00100000; //записали
DDRB = 0b11101101; // читаем
rezultat = 0b00100001; //записали