ruhi

логическое И на AVR

48 сообщений в этой теме

ruhi    34

Меня тут порадовали задачкой для АВР (я когда то очень много таких порешал, на практике - напомнили молодость :) ):

http://cxem.net/mc/mc446.php

сформулирована так: Нужно два быстрых элемента "И" и одновибратор. Можно использовать серию 155 у которой время срабатывания даже меньше получается, но не подходит по энергопотреблению. Хотелось бы сделать это на Attiny13.

Остановимся пока на 

Цитата

два быстрых элемента "И"

Я, соответственно, предложил реализацию:

Можожно сделать так:
loop1:
in reg1, pina; 1-tick
in reg2, pinb; 1-tick
and reg1, reg2; 1-tick
LSR reg1; 1-tick
out portB, reg1; 1-tick
rjmp loop1; 2-tick

Это код на ассемблере , который реализует два «элемента И» на АВР со временем срабатывания около 1мкс, в зависимости от тактовой частоты МК.

На частоте 16 MHz это 7/16 мк-секунды(7 ticks, на самом деле +4 = 11тиков максимум время срабатывания, позже поясню), входы элемента-И должны быть на одинаковых пинах условных портов A and B, а выходы следующие по старшинству биты-пины. Вообще говоря перед выводом в порт, скорее всего, нужно будет еще маску добавить это еще +1 тик!


Цикл можно переделать на использование только одного порта. Мой вариант в закодированном архиве приатачен, ключ выложу через неделю!

Мне интересно можно ли сделать быстрее чем у меня получилось! Сможет кто нибудь предложить вариант решения?
В общем, похоже что, на ассемблере можно написать «два элемента И» со временем срабатывания около 1.5мкс даже на 10МГц при произвольном расположении ног на одном порту.

bestAvrCodeForAnd.7z

Изменено пользователем ruhi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    357

К сожалению,  проблема не в скорости. Проблема в ДЖИТТЕРЕ.

На выходе Вы получите мечущийся фронт с переменной задержкой.

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

Поэтому сейчас в МК применяются специальные микро ПЛИС (как периферийный модуль) для решения входных и выходных логических асинхронных задач.

Изменено пользователем my504

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
5 минут назад, my504 сказал:

К сожалению,  проблема не в скорости. Проблема в ДЖИТТЕРЕ.

На выходе Вы получите мечущийся фронт с переменной задержкой от почти нуля до 1,5 мкс.

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

Життер это для периодических сигналов, можно уточнить задачу:

переключения случаются не чаще раз в мили секунду, случайность задержки срабатывания в пределах до максимально разрешенной задержки разрешена!

То есть по условию задачи, життер в вашем определении, не является проблемой!

Изменено пользователем ruhi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    357

Джиттер - это для ЛЮБОГО сигнала. Нестабильность фронта выходного сигнала по отношению к входному и есть джиттер.

Если речь о миллисекундах, то зачем чего то там оптимизировать? Как правило, подобную логику делают с входной и выходной синхронизацией. То есть с определенным тактированием защелкивают входы, программно рассчитывают выходную функцию, а потом ее разом выводят (выходное тактирование). 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
15 минут назад, my504 сказал:

Как правило, подобную логику делают с входной и выходной синхронизацией. То есть с определенным тактированием защелкивают входы, программно рассчитывают выходную функцию, а потом ее разом выводят (выходное тактирование). 

Было бы интересно посмотреть код! Скажу по секрету у меня получилось 6 (шесть) инструкций в цикле.

А оптимизировать надо чтобы понять пределы возможного.То есть, на что же можно рассчитывать!

15 минут назад, my504 сказал:

Джиттер - это для ЛЮБОГО сигнала. Нестабильность фронта выходного сигнала по отношению к входному и есть джиттер.

Я про другое определение думал, но в данном контексте такое определение совершенно уместно, но такой життер не является проблемой по условиям задачи, он разрешен, главное что он ограничен сверху!

Изменено пользователем ruhi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@ruhi Распишите точно задачу. А то в комментах по ссылке куча всего. И диаграммки желательно тоже. Ну вы и хвастун)))

Изменено пользователем MasterElectric

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В ответе вариант с мультивибратором или просто логическое И 2 шт.? Ничего не понятно. А что желающих нет :D

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
В 29.01.2018 в 22:01, MasterElectric сказал:

Распишите точно задачу.

Про одновибратор я сам еще до конца не выяснил! Поэтому:

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

если на вход1 подана логическая единица,

на входе2 логический ноль, на выходе должен быть лог-ноль.

И при переключении входа2 в 1-цу , на выходе с задержкой Т (не больше Т!!! - то есть меньше можно!!!) должна появиться логическая единица!

Соответственно, надо написать код который реализует ДВА таких элемента на одном порте контроллера, то есть на ногах одного порта (PORTB, PINB, DDRB - например). И определить соответствующее этому коду максимальное Т!

Это, получается, задача определения предельных возможностей управления портом на AVR-ассемблере (спасибо @my504 за уточняющие вопросы), для всей линейки процессоров поддерживающих систему команд. На результат решения которой, в дальнейшем можно ориентироваться при разработке прикладных решений(, как минимум, а, даст бог, и еще что то интересное проявится).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
В 26.01.2018 в 17:49, my504 сказал:

Если речь о миллисекундах, то зачем чего то там оптимизировать?

Там время срабатывания должно быть хотя бы в десять раз (и тоже "например"!) меньше чем время переключения на входах, миллисекунды я для примера назвал, может быть и меньше, собственно максимальное время переключения, как раз и определяет с какой скоростью можно переключать входные сигналы, то есть с какой скоростью можно реагировать!

Кстати, если вы посмотрите программную реализацию USB на AVR, то как раз увидите где это надо! Там как раз подобная задача, только намного заковыристее, прямого контроля-управления "ногами" решена,

там следят за фронтами, меряют время, выставляют уровни в соответствии с заданными последовательностями фронтов, задержек ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    493

При наличии достаточного объема flash проблема джиттера и быстродействия решается достаточно просто: для всех комбинаций пинов порта составляется таблица выходных состояний "логических элементов", затем считывается порт, по таблице находится выходное состояние и выводится в порт. Джиттер отсутствует, быстродействие предельное. Легко реализуются любые "логические" элементы с общим количеством входов до 8 и таким же кол-вом выходов.

Можно таблицу и в ОЗУ сделать, если его больше 256 байтов, и это, возможно, позволит еще чуток поднять быстродействие...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    357
1 минуту назад, ARV сказал:

 Джиттер отсутствует

Даладна!!!

:lol:

Джиттер НЕИЗБЕЖЕН при ЛЮБОМ синхронном приеме сигнала. Входной сигнал и сигнал тактирования входной защелки некогерентны по определению, а значит будут наблюдаться БИЕНИЯ внутреннего входного, а значит и выходного, сигнала.

Ровно поэтому невозможно осуществить захват асинхронного счетчика внутренним тактированием МК.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
6 минут назад, ARV сказал:

При наличии достаточного объема flash проблема джиттера и быстродействия решается достаточно просто: для всех комбинаций пинов порта составляется таблица выходных состояний "логических элементов", затем считывается порт, по таблице находится выходное состояние и выводится в порт. Джиттер отсутствует, быстродействие предельное. Легко реализуются любые "логические" элементы с общим количеством входов до 8 и таким же кол-вом выходов.

Можно таблицу и в ОЗУ сделать, если его больше 256 байтов, и это, возможно, позволит еще чуток поднять быстродействие...

Джиттер (очень мне не нравится использование этого термина в данном контексте, ну ладно), не возможно исключить, а в остальном, именно при этом подходе получилось 6(шесть) инструкций в цикле!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    493

В моём понимании джиттер - это недетрминированные колебания интервала между сменой сигнала на входе и соответствующего изменения на выходе. Иначе говоря, колебания длительности "времени распространения" сигнала. С точностью до периода тактовой частоты МК в табличном методе джиттер будет отсутствовать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    357
7 минут назад, ruhi сказал:

если вы посмотрите программную реализацию USB на AVR, то как раз увидите где это надо!

Это "надо" при любых софтовых задачах. Но причем тут USB? Этот протокол совершенно нечувствителен к джиттеру.  Мало того, его софтовая реализация не позволяет реализовать поставленную здесь задачу, поскольку управление стеком (машиной состояний стека) имеет более высокий приоритет, нежели логическая функция выхода или входа. Оная функция - суть есть крошечный кусок кода общего цикла.

3 минуты назад, ARV сказал:

С точностью до периода тактовой частоты МК

А период тактовой частоты - это не джиттер? :o

Тут обсуждается вопрос в скорости реакции измеряемой  максимум десятком циклов. Зачем нужна такая скорость, если 8...10%-ный джиттер - это "не джиттер"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
4 минуты назад, my504 сказал:

Но причем тут USB? Этот протокол совершенно нечувствителен

USB не при чем, я упомянул ПрОГРАММНУЮ РЕАЛИЗАЦИЮ юсб. 

проблема неопределенности времени реакции на фронт там тоже присутствует, и она решена!

Изменено пользователем ruhi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    357

Программная реализация ЮСБ ничем не отличается от железной.  Организовать формальный опрос-логическую функцию-вывод при управлении D+D- невозможно без учета требуемого времени на остальное. Время потраченное на примитивную логическую функцию и ввод-вывод  на несколько десятичных порядков меньше остального.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@ruhi Ну у меня получилось 8 и 9 инструкций, быстрее не придумал. Интересно будет посмотреть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
2 минуты назад, my504 сказал:

Программная реализация ЮСБ ничем не отличается от железной.

Это как это? Это похоже на то что вы заговариваетесь, пытаясь доказать то что вам хочется, даже не смотря на то что это не соответствует действительности :( !

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    357

Приведите пример. В каком месте USB протокола нужно с высокой скоростью выводить бит на основании анализа двух других битов?

Может я чего то и не знаю, но в протоколе USB нет такой процедуры...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
7 минут назад, my504 сказал:

высокой скоростью выводить бит на основании анализа двух других битов?

там анализируются фронты и задержки на одной линии (один бит), но алгоритм работает на основе как минимум двух значений: текущего значения бита, задержки от предыдущего фронта.

и я уже точно не помню, но кажется в каких то случаях анализируются, все таки обе линии D+ D-.

Изменено пользователем ruhi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Мой вариант:

// вариант №1
start:
    in        r16, PinB
    mov       r17, r16
    lsl       r17
    and       r16, r17
    lsl       r16 
    andi      r16, 0x24
    out       PortB, r16
    rjmp      start

// вариант №2
start_2:
    ldi       r16, 0x24       
    sbic      PinB, 0
    sbis      PinB, 1
    cbr       r16, 0x04
    sbic      PinB, 3
    sbis      PinB, 4
    cbr       r16, 0x20
    out       PortB, r16
    rjmp      start_2

 

@ARV Да я ошибался, думал вычисление смещения займет много времени.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
my504    357
51 минуту назад, ruhi сказал:

там анализируются фронты и задержки на одной линии (один бит), но алгоритм работает на основе как минимум двух значений: текущего значения бита, задержки от предыдущего фронта.

и я уже точно не помню, но кажется в каких то случаях анализируются, все таки обе линии D+ D-.

 

Анализ состояния двух пинов (они дифференциальные) собственно необязателен, но желателен, чтобы обеспечить помехозащищенность.

Даже если и находить логическую функцию этих пинов, причем тут ВЫВОД? 

Вы так и не показали аналог проставленной здесь задачи по реализации вентиля И (ИЛИ, исключающее ИЛИ и т.п.).

Изменено пользователем my504

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ruhi    34
1 час назад, my504 сказал:

Вы так и не показали аналог проставленной здесь задачи по реализации вентиля И (ИЛИ, исключающее ИЛИ и т.п.).

Под тем что задача аналогичная, я имел ввиду, что там тоже написан на ассемблере и прерываниях анализ "ног" контроллера, и в зависимости от этого анализа формируются уровни на портах строго по тактам.

Извините за недосказанность!

Совершенно точно можно сказать, что там реализована некоторая логическая функция (намного более сложная!!!), я не в коем случае, не утверждал что там реализован именно вентиль И (ИЛИ, исключающее ИЛИ ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Похожие публикации

    • Автор: Денис Оробей
       Помогите написать простую задачку (для вас - простую, а я не шарю), на плате контроллера-конструнтора KIT-8515 нужно  сделать вот это: "Пусть движковыми переключателями задаются два четырехзначных операнда.  Напишите и протестируйте программу, при работе которой после нажатия кнопки 1 операнды складывались, а при нажатии кнопки 2 операнды вычитались, а результат операции выводился на светодиоды"
      Прикреплённый файл - начало задачки.
      Заранее благодарствую:)
      123.rar
    • Автор: Николай Зубий
      Как сделать  устройство, выводящие на индикатор время, прошедшее с момента последней перезагрузки контроллера?
    • Автор: forestdozor
      Здравствуйте!

      Мне нужно измерить длительность импульса. Для этого сначала применял внешнее прерывание, а теперь перешел на режим захвата таймера в Atmega 328.
      Однако сейчас происходит странное: Через определенное таймер просто останавливается. Гугл результатов не дает, ни у кого захват таймера 1 не останавливается.
      Подскажите пожалуйста, что делать?
      Среда разработки CodeVisionAVR v3.12. Сейчас попробовал версию 3.3, толку нет. Не работает. Код максимально упростил, но по прежнему толку ноль.
      Переполнение таймера 0 так же работает отлично, до тех пор, пока что-то не произойдет с прерыванием по захвату. Как только что-то произошло - мк останавливается...
      Может немножко подождать, и увеличить значение счетчика current_timp еще на пару значений... Совсем не знаю что делать.
       
       
      interrupt [TIM1_OVF] void timer1_ovf_isr(void)
      {
      TCNT1H = 0x00;
      TCNT1L = 0x00;
      }
      // Timer1 input capture interrupt service routine
      interrupt [TIM1_CAPT] void timer1_capt_isr(void)
      {
       
             TCNT1H = 0x00;
             TCNT1L = 0x00;           // Это уже уровень танцев с бубном "авось поможет" - не помогает.
         
              current_timp++;          // Все упрощено до максимума. Мне бы он хоть количество периодов для начала...
              
        //  }
      }
      // Прерывание по переполнению первого таймера
      interrupt [TIM0_OVF] void timer0_ovf_isr(void)
      {
      // Обнуление счетного регистра.
      TCNT0=0x00;

          
          counter ++;
          if (counter > 10)
          {
                  lcd_clear();
                  sprintf(buffer,"%d us", current_timp);
                  lcd_gotoxy(0,0);
                  lcd_puts(buffer);
                  counter = 0;
          }
          
          
      }

      // Главный цикл программы
      void main(void)
      {

      #pragma optsize-
      CLKPR=(1<<CLKPCE);
      CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
      #ifdef _OPTIMIZE_SIZE_
      #pragma optsize+
      #endif

      // Port B initialization
      // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
      DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
      // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
      PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
      // Port C initialization
      // Function: Bit6=In Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
      DDRC=(0<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
      // State: Bit6=T Bit5=1 Bit4=1 Bit3=1 Bit2=1 Bit1=1 Bit0=1
      PORTC=(0<<PORTC6) | (1<<PORTC5) | (1<<PORTC4) | (1<<PORTC3) | (1<<PORTC2) | (1<<PORTC1) | (1<<PORTC0);
      // Port D initialization
      // Function: Bit7=Out Bit6=Out Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
      DDRD=(1<<DDD7) | (1<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
      // State: Bit7=1 Bit6=1 Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
      PORTD=(1<<PORTD7) | (1<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
      // Делители таймера 0 рассчитаны таким образом , что его тактовая частота = 15,625 КГц. Расчет был на применение в схеме семисегментников, но с LCD индикатором будет информативнее.
      TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
      TCCR0B=(0<<WGM02) | (1<<CS02) | (0<<CS01) | (1<<CS00);
      TCNT0=0x00;
      OCR0A=0x00;
      OCR0B=0x00;
       
      // Настройка таймера 1
      TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
      TCCR1B=(1<<ICNC1) | (1<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
      TCNT1H=0x00;
      TCNT1L=0x00;
      ICR1H=0x00;
      ICR1L=0x00;
      OCR1AH=0x00;
      OCR1AL=0x00;
      OCR1BH=0x00;
      OCR1BL=0x00;
      // Разрешение прерывания по переполнению таймера 0
      TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (1<<TOIE0);
      // Timer/Counter 1 Interrupt(s) initialization
      TIMSK1=(1<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);
    • Автор: voltex
      Всем привет! Подскажите, пожалуйста, как правильно считать данные с внешней eeprom по шине spi, в данном случае 25LC256.
      Написал код ссылаясь на даташит. Собрал схему в протеусе, подключил spi отладчик и вот что получил в итоге. Так же не могу проверить получается записать данные в память или нет. Весь код прикрепил.
       

      main.c
    • Автор: CUBE
      Не могу запустить асинхронный режим. 
      Ниже будет представлен код которым пытаюсь отладить. Там в 1 коде идёт работа от внутреннего источника таков (стоит 1МГц).  После 5 миганий таймер должен перейти в асинхронный режим и мигать с частотой в 1 Гц. У меня происходит 5 миганий потом ничего. Фьюзы менять пробовал, ничего не дало, сейчас дефолт. Корпус кварца к земле тянуть пробовал - безрезультатно. 
      Возможно что-то в подключении накосячил, если не видно на фото ниже, спрашиваете, нужно будет - нарисую схему. 
      Компилятор Atmel Studio 7
      Шью через Sind Prog 2.1.1 + USBasp 2.0
      Вот код: 
      .macro outi 
       ldi r16, @1 
       out @0, r16 
      .endm 
      .org $000 
      rjmp reset 
      .org $001 
      reti 
      .org $002 
      reti 
      .org $003 
      reti 
      .org $004 
      rjmp timer2_ovf 
      .org $005 
      reti 
      .org $006 
      reti 
      .org $007 
      reti 
      .org $008 
      reti 
      .org $009 
      reti 
      .org $00A 
      reti 
      .org $00B 
      reti 
      .org $00C 
      reti 
      .org $00D 
      reti 
      .org $00E 
      reti 
      .org $00F 
      reti 
      .org $011 
      reti 
      .org $012 
      reti 
      .ORG INT_VECTORS_SIZE 
       
      reset: 
      .equ portout=portd 
      .equ ddrout=ddrd 
      .def led=r17 
      .def mask=r18 
      .def counter=r19 
       outi spl,low(ramend) 
       outi sph,high(ramend) 
       
       outi ddrout, 0xff 
       
       outi tccr2, 0b00000111 
       outi timsk, 1«toie2 
       
        
       
        
       ldi led,1«5 
       ldi mask,1«5 
       sei 
      cycle: 
      cpi counter, 10 
      breq offtim 
       rjmp cycle 
       
      timer2_ovf: 
      inc counter 
       out portout, led 
       eor led, mask 
      reti 
        
      offtim: 
      outi timsk, 0«toie2 
      rjmp asinxron 
       
      asinxron: 
       outi assr, 0b00001000 
      back: 
       in r16, assr 
       cpi r16, 0b00001000 
       brne back 
       
        outi tccr2, 0b00000101 
        outi tcnt2, 0 
        outi ocr2, 0 
        outi timsk, 1«toie2 
       
       
      m1: 
      rjmp m1


      Верх меги на фото слева.