Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Подмешивание в видеосигнал
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
idono
Разбираюсь с АТмегой16, на этот раз экспериментирую с подмешиванием данных (хотя бы палочек-полосок) в композитный видео-сигнал.

Перерыл все возможные гуглы, нашел несколько реализаций, нашел описание передачи видео-сигнала. Читал, смотрел, опять читал. С железом более-менее разобрался, принцип работы понятен.
А вот с софтом не очень, не хватает познаний. Так что все рассуждения основываются на познаниях из мануалов "для чайников" rolleyes.gif

Итак, купил LM1881, кварц 16 мгц, конденсаторы, резисторы, пару диодов. Подключил все это к меге16 - сигнал горизонтальной синхронизации на вход внешних прерываний INT0, вертикальной на INT1. Получается что прерывание по INT0 возникает в начале прорисовки каждой строки, а INT1 в начале каждого кадра (или полукадра, т.к. рисуется через строчку). Ногу PD7 сделал выходом и подключил обратно к центральной жиле видеокабеля через диод и сопротивление.

Сделал счетчик строк, который прибавляет 1 при каждом INT0 и обнуляет при INT1.
Посидел, подумал, написал... в прерывании INT0 ждем нужной строки, после чего ждем определенное время, включаем "питание" на PD7, опять ждем, выключаем питание. Получается горизонтальная линия определенной длины и с определенным смещением от левого края.

Нарисуем крест. В обработчике INT0 условие - если строка не та, которая нам нужна, то ждем, включаем PD7 и сразу же выключаем (чтобы получить штрих с наименьшим размахом). Т.к. задержка в каждой строке одинаковая, должна получится ровная вертикальная линия. Но не получается : wacko.gif Линия гуляет как бы лесенкой на всем протяжении. По логике получается, что временной интервал от начала прерывания до начала включения PD7 при одинаковых значениях получается разным sad.gif
Фото стоп-кадра экрана прикрепил.

Вот кусок кода с обработкой прерываний:
Код
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
          if (vert==150) {      
                i=10;
                while(i--) { #asm("nop"); }
                PORTD.7=1;
                i=30;
                while(i--) { #asm("nop"); }
                PORTD.7=0;  
          }
          else {
               i=20;
                while(i--) { #asm("nop"); }
                PORTD.7=1;
                PORTD.7=0;  
          }  

        vert++;
}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
// Place your code here  
        vert=0;  
}




Обучите, пожалуйста, чайника основным принципам правильного построения изображения на этой железной связке (LM1881 + atmega16). Для начала хотя бы прямых линий rolleyes.gif
PSP
Прерывание не обрабатывается мгновенно, всегда происходит завершение выполнения текущей команды фоновой программы, а это обычно от одного до нескольких тактов, плюс время входа в прерывание. Почитайте раздел "Interrupt Response Time" из datasheet. При тактовой 16 МГц это даст переменную задержку не менее 62.5 нс, что составляет больше 1% от ширины экрана, т.к. видимая часть меньше полной длительности строки 64 мкс.
Можно пытаться бороться с неопределенностью момента старта используя сигнал прерывания для выхода из состояния SLEEP, но остается проблема несинхронности тактового генератора процессора и синхроселектора. Или видел вариант применения строчного синхроимпульса в качестве сигнала "сброс" с одновременным разрешением работы тактового RC-генератора процессора. Это позволяет привязать генератор к фазе синхросигнала.
Serj78
на 16 мгц совершенно достаточно засыпать потом просыпаться , на глаз не заметно. дополнительной синхронизации не требуется. у меня строчки от начала кадрового импульса (титры выводятся внизу экрана) считаются таймером, во время свободной части кадра проц занят полезным делом smile.gif

также поищите поиском avr-vga там есть проект текстового вывода на экран.
fmdost
Цитата(Serj78 @ Dec 21 2007, 00:41) *
на 16 мгц совершенно достаточно засыпать потом просыпаться , на глаз не заметно. дополнительной синхронизации не требуется. у меня строчки от начала кадрового импульса (титры выводятся внизу экрана) считаются таймером, во время свободной части кадра проц занят полезным делом smile.gif

А если засинхронизировать таймер счётчик по синхроимпульсам строк, то можно попробовать использовать выходы compare для аппаратного рисования. Напримет compare1 есть вкл compare2 есть выкл, и сразу в них новые значения. ИМХО не пробовал, просто подумалось.
=VRA=
Все это на раз делается даже без LM1881
rx3apf
Цитата(PSP @ Dec 21 2007, 00:19) *
Прерывание не обрабатывается мгновенно, всегда происходит завершение выполнения текущей команды фоновой программы, а это обычно от одного до нескольких тактов, плюс время входа в прерывание. Почитайте раздел "Interrupt Response Time" из datasheet. При тактовой 16 МГц это даст переменную задержку не менее 62.5 нс, что составляет больше 1% от ширины экрана, т.к. видимая часть меньше полной длительности строки 64 мкс.


Нет, чуть больше 0.1% - ведь разница три порядка, а не два. А 0.1% не очень заметны. Но по-хорошему, надо бы принимать дополнительные меры к синхронизации.

Цитата(PSP @ Dec 21 2007, 00:19) *
Можно пытаться бороться с неопределенностью момента старта используя сигнал прерывания для выхода из состояния SLEEP, но остается проблема несинхронности тактового генератора процессора и синхроселектора. Или видел вариант применения строчного синхроимпульса в качестве сигнала "сброс" с одновременным разрешением работы тактового RC-генератора процессора. Это позволяет привязать генератор к фазе синхросигнала.

Для RC-генератора выход из sleep даст необходимую синхронизацию. Альтернатива - PLL для тактового генератора.
idono
Вставил бесконечный цикл с idle(); в главной функции - расстояния между изломами вертикальной линии стани больше. Померял линейкой ширину "перелома" (эксперементирую на проекторе, поэтому померять вполне реально) - получилось действительно около 0.2% погрешности.

Выходит, что мои волнения были напрасны, для небольшого экрана такая погрешность будет вполне допустима beer.gif

Следующим шагом попробую выводить осмысленные буковки.
Кстати, те проекты avr-vga и телеметрию для воздушного шара я нашел и изучил в первую очередь. По коду почти ничего не понял sad.gif

Буду постить свои попытки изучить систему в этой теме, если вы не против rolleyes.gif Может быть еще кому-то из начинающих она поможет в будущем.

Если я правильно понял принцип построения текста на экране - есть некий двухмерный массив с битами 0 1, как бы матрица для построения цифры по слоям, в котором цифра, например, 1 выглядит так (беру цифру с разрешением 8х12, как в проекте avr-vga):

11111111
11111111
10000111
11100111
11100111
11100111
11100111
11100111
11100111
11100111
11111111
11111111

Имея массив с текстом для вывода и счетчик текущей строки, выводим чисто построчно, перемигиваясь в каждой строке нулями и единицами. Ну и конечно надо учитывать, что изображение строится через строку.

// пошел пробовать smile.gif
alux
Смотри на avrfreaks в последних проектах "AVGA demo".
idono
Цитата(alux @ Dec 21 2007, 10:48) *
Смотри на avrfreaks в последних проектах "AVGA demo".

там что-то совсем жестко, я и элементарные проекты разобрать не могу sad.gif

написал сам как смог прорисовку одного символа:

Код
int start_line=100;    // начинаем вывод с линии номер 100
int cur_line=0;         // переменная для отсчета линий с момента начала прорисовки символа

// сам тестовый символ (нарисован 0 единичками)
char symbol[8]={0b01111111,
                0b01000001,
                0b01000001,
                0b01000001,
                0b01000001,
                0b01000001,
                0b01000001,
                0b01111111};

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
         //если находимся в области прорисовки:
          if (vert>start_line && vert<start_line+9)  {
                i=30;
                while(i--) { #asm("nop"); }    // задержка перед выводом (для отступа слева)
  
                PORTD.7=symbol[cur_line] & (1 << 0); // присваиваем порту вывода 1, если в нулевом бите symbol единица (т.е. включаем белый пиксел)
                PORTD.7=symbol[cur_line] & (1 << 1); // тоже, но проверяем первый бит
                PORTD.7=symbol[cur_line] & (1 << 2); // второй бит
                PORTD.7=symbol[cur_line] & (1 << 3); // и так далее
                PORTD.7=symbol[cur_line] & (1 << 4);
                PORTD.7=symbol[cur_line] & (1 << 5);
                PORTD.7=symbol[cur_line] & (1 << 6);
                PORTD.7=symbol[cur_line] & (1 << 7);                
                          
                cur_line++; // переходим на опрос слдующего элемента массива
                
          } else {              
                cur_line=0; // сбрасываем позицию на ноль, если находимся вне области прорисовки
          }

        vert++; // увеличиваем счетчик горизонтальных линий
}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
        vert=0;  //сбрасываем счетчик линий при начале прорисовки нового кадра
}


В результате получается такой широченный символ smile.gif
Как с максимальной скоростью вывести на PORTD.7 сразу все восемь бит переменной? То есть если в переменной "0b01011100", то на порт PD7 быстренько по-очереди выведутся значения 0 1 0 1 1 1 0 0
Циклом for() получается еще дольше, чем я в ряд записал, видимо процессор тратит много тактов на такие операции
GDI
Цитата
видимо процессор тратит много тактов на такие операции

А вы посмотрите что у вас в асм листиге получилось, там же, небось еще и выборка из массива каждый раз делается,
как вариант №1 осмелюсь предложить перед операцией собственно вывода сделать чтение нужного байта из массива в какую то переменную, а потом сдвигать виты только из этой переменной, примерно так:
Код
      
                tmp =  symbol[cur_line]        
                PORTD.7=tmp & (1 << 0); // присваиваем порту вывода 1, если в нулевом бите symbol единица (т.е. включаем белый пиксел)
                PORTD.7=tmp & (1 << 1); // тоже, но проверяем первый бит
                PORTD.7=tmp & (1 << 2); // второй бит
                PORTD.7=tmp & (1 << 3); // и так далее
                PORTD.7=tmp & (1 << 4);
                PORTD.7=tmp & (1 << 5);
                PORTD.7=tmp & (1 << 6);
                PORTD.7=tmp & (1 << 7);

возможно того же эффекта можно добиться используя оптимизацию по скорости компилятора.

вариант №2, сделать аппаратный вывод битов, например через внешний регистр с параллельной загрузкой и последосательным выходом, можно попробовать для этой цели приспособить аппаратный SPI, который есть на МК. А еще, если есть свободный порт, например то же PORTD, то можно сделать так:
Код
PORTD = symbol[cur_line];
PORTD >>= 1; //и так 8 раз
при этом все линии порта кроме младшей должны быть свободны а на выводе PORTD.0 мы получим последовательность битов, начиная от младшего, либо можно получить биты, начиная со старшего , если применить сдвиг в другую сторону, тогда последовательность будет выходить с PORTD.7
idono
Чтение байта из массива перед выводом помогло, ширина символа сократилась примерно в полтора раза. Опимизация компилятора по скорости уменьшила символ еще на столько же! Спасибо за советы, GDI

Теперь символ 8х12 выглядит вполне хорошо. Теперь попробую привязать готовый массив с шрифтом, дабы букву можно было оттуда выбирать и делать вывод
idono
нарисовал из нулей массив цифр, написал функцию для прерывания. Старался делать все без массивов и циклов - при срабатывании прерывания, перед выводом делаю все вычисления, байты сравниваю и тп, потом в ряд идет вывод. Да условия перед этим выводом такой сложности, что вывод поспевает уже к концу отрисовки строки, только только 3 цифры успеваю вывести.

Для теста я пробовал вывести на одну из строк показания с датчика температуры - впритык к максимальной загрузке меги, но получилось (результат прикрепил).

Вот код (только основная проблемная часть)

Код
char symbol[13][12]={
                {
                0b00011000, // 0
                0b00100100,
                0b01000010,
                0b01000010,
                0b01000010,
                0b01000010,
                0b01000010,
                0b01000010,
                0b01000010,
                0b01000010,
                0b00100100,
                0b00011000
                },
                ..... и так далее
}

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{              
      //если текущая строка попадает в заданую область для 1го ряда цифр
        if (vert>start_line && vert<start_line+13)  {
           drawing1=number1; //присваиваем переменным прорисовки цифр drawing значения каких-то параметров
           drawing2=number2; //в тесте параметров нет, поэтому значения просто присвоены выше
           drawing3=number3;
           state1=1; // флаг нахождения в нужном диапазоне для обработчика ниже
        } else {
           state1=0;
        }  
        
        // случай со вторым рядом цифр
        if (vert>start_line2 && vert<start_line2+13)  {
           drawing1=number5;
           drawing2=number6;
           drawing3=number7;
           state2=1;
        } else {
           state2=0;
        }

         // случай с третьим рядом цифр
        if (vert>start_line3 && vert<start_line3+13)  {
           drawing1=number9;
           drawing2=number10;
           drawing3=number11;
           state3=1;
        } else {
           state3=0;
        }

    
          //если строка попадает в область прорисовки одного из 3х значений, то запускаем обработчик
          if (state1 || state2 || state3)  {
              
                        //вычисляем значение (0 или 1) каждого пиксела для всех 3х цифр в данной строке (тип переменной tmp - bit)
                        tmp00 =  symbol[drawing1][cur_line]& (0b10000000 >> 0);
                        tmp01 =  symbol[drawing1][cur_line]& (0b10000000 >> 1);
                        tmp02 =  symbol[drawing1][cur_line]& (0b10000000 >> 2);
                        tmp03 =  symbol[drawing1][cur_line]& (0b10000000 >> 3);
                        tmp04 =  symbol[drawing1][cur_line]& (0b10000000 >> 4);
                        tmp05 =  symbol[drawing1][cur_line]& (0b10000000 >> 5);
                        tmp06 =  symbol[drawing1][cur_line]& (0b10000000 >> 6);
                        tmp07 =  symbol[drawing1][cur_line]& (0b10000000 >> 7);  

                        tmp10 =  symbol[drawing2][cur_line]& (0b10000000 >> 0);
                        tmp11 =  symbol[drawing2][cur_line]& (0b10000000 >> 1);
                        tmp12 =  symbol[drawing2][cur_line]& (0b10000000 >> 2);
                        tmp13 =  symbol[drawing2][cur_line]& (0b10000000 >> 3);
                        tmp14 =  symbol[drawing2][cur_line]& (0b10000000 >> 4);
                        tmp15 =  symbol[drawing2][cur_line]& (0b10000000 >> 5);
                        tmp16 =  symbol[drawing2][cur_line]& (0b10000000 >> 6);
                        tmp17 =  symbol[drawing2][cur_line]& (0b10000000 >> 7);  
  
                        tmp20 =  symbol[drawing3][cur_line]& (0b10000000 >> 0);
                        tmp21 =  symbol[drawing3][cur_line]& (0b10000000 >> 1);
                        tmp22 =  symbol[drawing3][cur_line]& (0b10000000 >> 2);
                        tmp23 =  symbol[drawing3][cur_line]& (0b10000000 >> 3);
                        tmp24 =  symbol[drawing3][cur_line]& (0b10000000 >> 4);
                        tmp25 =  symbol[drawing3][cur_line]& (0b10000000 >> 5);
                        tmp26 =  symbol[drawing3][cur_line]& (0b10000000 >> 6);
                        tmp27 =  symbol[drawing3][cur_line]& (0b10000000 >> 7);    
                        
                        // и быстро выводим получившиеся значения с небольшой задержкой (промежутки между цифрами)
                        PORTD.7=tmp00;
                        PORTD.7=tmp01;
                        PORTD.7=tmp02;
                        PORTD.7=tmp03;
                        PORTD.7=tmp04;
                        PORTD.7=tmp05;
                        PORTD.7=tmp06;
                        PORTD.7=tmp07;
                        
                        delay_us(5);  
  
                        PORTD.7=tmp10;
                        PORTD.7=tmp11;
                        PORTD.7=tmp12;
                        PORTD.7=tmp13;
                        PORTD.7=tmp14;
                        PORTD.7=tmp15;
                        PORTD.7=tmp16;
                        PORTD.7=tmp17;
                        
                        delay_us(5);
                        
                        PORTD.7=tmp20;
                        PORTD.7=tmp21;
                        PORTD.7=tmp22;
                        PORTD.7=tmp23;
                        PORTD.7=tmp24;
                        PORTD.7=tmp25;
                        PORTD.7=tmp26;
                        PORTD.7=tmp27;
                                          
                cur_line++;
                
          } else {
                cur_line=0;    
          }
          

        vert++;  

}

// External Interrupt 1 service routine
interrupt [EXT_INT1] void ext_int1_isr(void)
{
// Place your code here  
        vert=0;  
}


Кажется все эти просчеты &, сдвиги битов и выборы из 3х-мерного массива в количестве 24 штуки сильно грузят процессор. Так, что 3й символ успевает выскочить уже почти в конце строки. Просчеты для 4го символа вставить конечно уже некуда sad.gif
Само собой разумеется, что алгоритм всех этих просчетов неверный. Хочется побольше информации на изображение наложить.

Подскажите более правильный алгоритм побитового вывода байта из массива в порт, пожалуйста crying.gif
Maik-vs
ИМХО это большой героизм советского толка писать такое на С. Лучше на ассемблере - там эмулятор точно считает время, можно всё учесть и пользоваться всякими хитростями. Сам интересуюсь подобной штукой, поэтому интересно, что у Вас получится. Видел проект, где пикселы строки заносятся во все 32 регистра, а потом тупо сдвигаются. Для сдвига, подумалось мне, можно использовать один из последовательных интерфейсов, кажется TWI может подойти. Или использовать внешний регистр сдвига как external RAM. Насчёт дрожания. PLL к строчной синхронизации конечно желателен, но у нас есть разработка с пиксельной частотой 20 МГц, буквы не дрожат.
rezident
Чтобы уменьшить джиттер и величину запаздываний вывода символов, вывод нужно разместить как можно ближе к точке входа в прерывание. Выводите сначала заранее подготовленный буфер и только потом уже делайте проверки и готовьте для вывода следующий буфер.
rx3apf
Цитата(Maik-vs @ Dec 21 2007, 20:17) *
Для сдвига, подумалось мне, можно использовать один из последовательных интерфейсов, кажется TWI может подойти. Или использовать внешний регистр сдвига как external RAM.

TWI - не лучший вариант. SPI - тоже. А вот в новых мегах UART умеет работать как SPI, причем с буферизацией - это, наверное, как раз будет то, что нужно.
umup
Цитата
TWI - не лучший вариант. SPI - тоже


как раз по неплохо SPI передают, у UART частота ниже :
http://www.vga-avr.narod.ru/
http://www.serasidis.gr/circuits/AVR_VGA/avr_vga.htm
http://blog.makezine.com/archive/2007/06/a...a8_video_o.html
http://convergencepromotions.com/atmel/v_6..._6_pg-40-42.pdf
rx3apf
Цитата(umup @ Dec 21 2007, 21:12) *
как раз по неплохо SPI передают, у UART частота ниже :

Я же говорю не про классический UART, а про UART в режиме SPI, в котором данные передаются с той же скоростью, что и в "обычном" аппаратном SPI (до cpuclk/2), но с дополнительной буферизацией, которую "обычный" SPI не обеспечивает и для соблюдения правильной растактовки необходимо считать такты вручную, и даже при этом, между out в SPDR должно быть 16 тактов (при максимальной частоте, естественно), т.е. разрыв на границе 8 битов будет неизбежно. UART в режиме SPI есть, например, в m48/88/168.
Rst7
Цитата(rx3apf @ Dec 21 2007, 20:29) *
Я же говорю не про классический UART, а про UART в режиме SPI, в котором данные передаются с той же скоростью, что и в "обычном" аппаратном SPI (до cpuclk/2), но с дополнительной буферизацией, которую "обычный" SPI не обеспечивает и для соблюдения правильной растактовки необходимо считать такты вручную, и даже при этом, между out в SPDR должно быть 16 тактов (при максимальной частоте, естественно), т.е. разрыв на границе 8 битов будет неизбежно. UART в режиме SPI есть, например, в m48/88/168.


Я Вам больше скажу, разрыв там будет из-за особенностей реализации SPI, обязательно один бит пропустит. А UART в режиме SPI рулит - я через него эзернетовские пакеты отправлял при 20МГц wink.gif
idono
Цитата(Maik-vs @ Dec 21 2007, 20:17) *
ИМХО это большой героизм советского толка писать такое на С. Лучше на ассемблере - там эмулятор точно считает время, можно всё учесть и пользоваться всякими хитростями. Сам интересуюсь подобной штукой, поэтому интересно, что у Вас получится. Видел проект, где пикселы строки заносятся во все 32 регистра, а потом тупо сдвигаются. Для сдвига, подумалось мне, можно использовать один из последовательных интерфейсов, кажется TWI может подойти. Или использовать внешний регистр сдвига как external RAM. Насчёт дрожания. PLL к строчной синхронизации конечно желателен, но у нас есть разработка с пиксельной частотой 20 МГц, буквы не дрожат.


Для меня скорее наоборот на ассемблере будет героизмом писать, т.к. я вообще в нем ничего не знаю smile.gif
Так что пишу по мере возможностей на Си


Расскажите, пожалуйста, про TWI и SPI применительно к моей задаче. Посмотрел проекты другие, там идет запись в какой-то SPDR, почитал даташит, мало чего понял. Если не сложно, напишите пример вывода хотя бы одного байта в строку с помощью этих технологий, попробую разобраться что к чему.

Ну и надо попробовать вариант с выводом целого байта в свободный порт с последующим сдвигом, может это будет быстрее
idono
Сделал вариант с выводом байта целиком в порт с последующим сдвигом - занимает в 2 раза меньше времени, чем мой первый вариант, т.е. нужные мне символы дописались без проблем. При желании можно было бы еще с десяток циферок до конца строки успевать прописывать.

Итого вышло 4 строки по 6 символов в каждой (плюс в двух еще и точка разделительная).
Получилась отличная реализация телеметрии для авиа-модели, осталось отыскать пару датчиков давления, дабы менять скорость и высоту.

Спасибо всем за помощь и идеи a14.gif
Rst7
Цитата
Получилась отличная реализация телеметрии для авиа-модели, осталось отыскать пару датчиков давления, дабы менять скорость и высоту.


Ну датчиков давления как грязи разных, найти не проблема. Но я бы делал телеметрию не так.

Насколько я понял, у вас передается изображение с видеокамеры, установленной на БПЛА, но перед этим вы подмешиваете туда свою графику. А надо бы чуть наоборот - подмешивать в воздухе данные телеметрии в бинарном виде - например, отвести на них 8 микросекунд после гасящего строчного и передать, скажем, 1 байт за это время (да хоть используя USART). В результате, если вы будете смотреть картинку, то увидите справа столбик с данными. А уже на земле пропустить этот видеосигнал через коробочку, в которой проц вытащит байтик по строчному синхроимпульсу и отобразит его красиво буквами и цифрами (и, например, можно будет по необходимости эту информацию наложить или убрать). В этом случае, у вас получается возможность, записав видеосигнал, сохранить объективные цифровые данные, которые можно потом обрабатывать не вручную. Запись можно вести хоть на видеомагнитофон, хоть цифровать сразу на комп.

В профсистемах для этой цели используются невидимые интервалы (гашение и т.д.), но лучше пожертвовать маленьким кусочком картинки, тогда все можно сохранить, не заботясь, что данные могут быть обрезаны (например, при цифровке на комп, как понимаете, все данные вне видимой области уйдут в сад).
Xumuk
Привет всем wink.gif
Очень интересная тема, давно думал над этим и вот собрался.

Собрал схему (прошу прощения за её несоответвие ISO, ГОСТ, ДСТУ прочим стандартам smile.gif )


(Забыл нарисовать на схеме, общий провод конструкции соединен с общим проводом видеосигнала)
Но вывести что-то осознанное на экран не получилось sad.gif
Подскажите поожалуйста, может я допустил ошибку в схеме? Или в коде программы?

_______________________________________________________________
#include <tiny26.h>
#include <delay.h>

int i=0;

interrupt [EXT_INT0] void ext_int0_isr(void)
{
if(i>100 && i<200){
delay_us(10);
PORTA.7=1;
delay_us(20);
PORTA.7=0;
}
i++;
}


void main(void)
{

PORTA=0x00;
DDRA=0xFF;
PORTB=0x00;
DDRB=0x00;
TCCR0=0x00;
TCNT0=0x00;
PLLCSR=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;

GIMSK=0x40;
MCUCR=0x00;
GIFR=0x40;

TIMSK=0x00;

USICR=0x00;

ACSR=0x80;

#asm("sei")

while (1)
{
if(PINB.3==0){
i=0;
}
};
}
________________________________________________________________________________
_

Это конечно не Мега16, но ведь вывести квадратик должно хватить? Просто под рукой был макет на Тинни26, который можно было легко переделать.
idono
Xumuk, на схеме сразу бросается в глаза разрыв видео-сигнала. Сигнал рвать не надо, провода Vin и Vout надо оба подключить к центральной жиле видео-провода, не разрывая ее.
Тогда твой МК будет в нужный момент времени выдавать "в линию" напряжение, что будет белой точкой в строке (либо линией, смотря на сколько "включать" PA7)
fmdost
Только вертикальную скорость нужно отображать ввиде столбика или полоски. Иначе легко запутаться в цифрах.
idono
Цитата(Т.Достоевский @ Dec 23 2007, 21:54) *
Только вертикальную скорость нужно отображать ввиде столбика или полоски. Иначе легко запутаться в цифрах.

Это точно, но у меня пока до вертикальной скорости дело не дошло. Не думаю, что разрешения стандартных датчиков давления + АЦП хватит для измерения вертикальной скорости с разрешением хотя бы 0.5 м/с
fmdost
Цитата(idono @ Dec 23 2007, 22:27) *
Не думаю, что разрешения стандартных датчиков давления + АЦП хватит для измерения вертикальной скорости с разрешением хотя бы 0.5 м/с

Хватит. У меня знакомые моделисты делали. Ещё знакомые, делали измеритель давления для часов на мотороловском датчике, говорят на 16 битах меряли высоту комнаты. Уточню название завтра, ибо уже спят.
Можно ещё сделать как в больших самолётах. Баллон с маленькой дырочкой, и какой нибуль датчик расхода, или измеритель относительного давления.
Xumuk
Цитата(idono @ Dec 23 2007, 20:23) *
Xumuk, на схеме сразу бросается в глаза разрыв видео-сигнала. Сигнал рвать не надо, провода Vin и Vout надо оба подключить к центральной жиле видео-провода, не разрывая ее.
Тогда твой МК будет в нужный момент времени выдавать "в линию" напряжение, что будет белой точкой в строке (либо линией, смотря на сколько "включать" PA7)


Спасибо wink.gif
Заработало biggrin.gif
Я не досмотрел, специально не соединял чтобы можно было лучше рассмотреть полученное изображение, а о том, что выходит телевизору не от чего синхронизироваться я как-то не подумал smile.gif

А можно узнать какой датчик для измерения температуры был использован?
idono
Цитата(Xumuk @ Dec 23 2007, 23:40) *
А можно узнать какой датчик для измерения температуры был использован?

AD22100 обычный аналоговый, на вход АЦП.
Может это не лучший вариант, везде пишут про использование каких-то датчиков с передачей инфы по l2c (даже в примерах cvavr такой использован, там кстати и название его написано)
idono
Объясните на пальцах, пожалуйста, как сделать вывод данных на видео через SPI?
А то чисто программно выводить слишком сложно выходит, а ведь надо еще и для кучи расчетов "мозгов" МК оставить help.gif
HCHUNTER
idono,

...от себя хотел добавить - обратите внимание на уровень оптимизации кода вашим компилятором (на какой уровень он выставлен). От этого будет сильно зависеть скорость работы таких конструкций как
i=10; while(i--) { #asm("nop"); }
или последовательный вывод строчек символов (где у вас подряд идут штук 20 одинаковых операторов).

А вывод делать нужно действительно через SPI ! Это самый быстрый метод. Пропускная способность порта для наших задач - фактически 8000000 точек в секунду.

Я сейчас озадачен той же самой проблемой, что и вы, с той лишь разницей, что я полностью формирую изображение на экране TV, а не накладываю текст.
На данный момент я добился вывода ч/б текстового поля размером 43х27 символов. Размер символа 8х12 точек.
Это же эквивалентно выводу ч/б картинки размером 340х312 пикселей.

Делаю все на AVR Mega8, но собираюсь переползать на Mega32, т.к. у "восьмерки" (впрочем как и у мега16) катастрофически не хватает памяти, а все видеообразы и таблицы символов целесообразно хранить во FLASH...
Serj78
Idono,
Надо просто помнить, что SPI - фактически сдвиговый регистр. вот и все. пишем в него данные (наш символ), он его самостоятельно выводит, а в это время можно подгружать из массива следующий- прошло прерывание по выводу байта- пихаем туда следующий символ. недостаток- не произвольные скорости вывода и невозможно сделать нулевое расстояние между символами, но это нам и не нужно. UART в режиме вывода как SPI возможно продвинутей будет.
HCHUNTER
Цитата(Serj78 @ Jan 1 2008, 14:09) *
невозможно сделать нулевое расстояние между символами


В принципе, можно его считать практически нулевым.
Все зависит от того, откуда выбирать данные.
Я выбирал с FLASH - скорость выборки довольно большая. Если на полностью белый фон выводить черные квадратики 8*12 (по размеру символа), то между ними видны еле-заметные белые полосочки.
А если выбирать из SRAM, то все заполняется очень плотно. Тогда влазит по-горизонтали даже до 47-48 символов. Без пробелов.
Но нужен контроллер с большим объемом памяти....

Причем, выбирать нужно тоже не из самих массивов, а однозначно напрямую - через указатели.
Xumuk
Может целесообразно использовать 2 микроконтроллера для вывода видео?
Первый МК занимается подсчетом нужных значений, ловит сигналы синхронизации и передает сигнал второму на порт о начале вывода каждой картинки или символа и само значение, которое нужно выводить (для скорости и простоты можно передавать значения параллельным способом порт-на-порт). У второго МК в памяти забиты таблицы символов, которые могут быть выведены и определены функции для вывода этих массивов в видео-поток.

Как вам такая идея?
Хотелось бы услышать мнения по такой схеме работы МК, может тут есть акие-то "подводные камни"?
Я еще не пробовал, но как закончится сессия в универе обязательно попробую smile.gif
Algol
HCHUNTER
А сколько вам необходимо ОЗУ? Может быть поставить внешную статическую рамину?
AndyBig
Цитата
Может быть поставить внешную статическую рамину?

Из нее будет медленно вычитываться.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.