Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Re: Хитрые, необычные алгоритмы и код

Вт фев 24, 2015 21:05:03

добрый вечер господа!!!поделиться пока нечем но нужна помощь...суть такова ,что мне нужен алгоритм для реализации шим в атмега8 таймер 16ти битный , хочу использовать его выводы для управления оборотами двигателя..суть проблемы как реализовать дэад тайм?? буду использовать 2 канала .сигналы на выходе в противофазе.как работает таймер и режим шим я в курсе .спасибо за помощь.))пример на асм был бы тоже кстати для понимания :beer: :beer:

Re: Хитрые, необычные алгоритмы и код

Вт фев 24, 2015 22:20:38

Просто задавать коэффициент заполнения так, чтобы каналы в сумме не давали 100% (255).

Например, один ШИМ-канал настраиваем как обычно, второй с инверсией, и задаем для одного значение ШИМ 120, а для другого 128, например. Получится защитный интервал в 8 отсчетов таймера, когда оба канала выключены.

Re: Хитрые, необычные алгоритмы и код

Ср фев 25, 2015 07:52:17

Можно так. Меняя значение delta в диапазоне 4...508 будет изменение постоянной составляющей

Re: Хитрые, необычные алгоритмы и код

Ср фев 25, 2015 20:28:25

спасибо огромное!! попробую что получиться

Re: Хитрые, необычные алгоритмы и код

Чт мар 05, 2015 11:24:21

график для понимания моей задачи
Вложения
график деад тайм.JPG
график для понимания моего вопроса
(14.45 KiB) Скачиваний: 916

Re: Хитрые, необычные алгоритмы и код

Вт апр 21, 2015 19:40:04

блин чет я в тупике..сделал шим с корекцией фазы но тут проблема..мне надо еще менять частоту в пределах от 50 до 30гц.а в этом режиме никак..только разными коэфициентами деления таймера..деад тайм получается но тоже не важнецкий скважность не должна превышать 50%..что делать подскажите плиз

Re: Хитрые, необычные алгоритмы и код

Пн июн 08, 2015 07:58:46

А я снова о прерываниях.

Не всегда реакция на прерывание должна быть немедленной (мгновенной) Большей частью это не так. Чаще всего задержка от прерывания до реакции на него в десяток-другой команд ничего плохого за собой не влечет. Если задача укладывается в эти рамки, то есть возможность использовать общую программу обслуживания прерываний, которая сохраняет-восстатавливает SREG и избранные регистры, а, при нужде, может и запустить селектор задач, переключить стек в вытесняющей многозадачке и т.п.

Сам прием я подсмотрел в недрах ядра RT-11. Конечно, на PDP-11 с ее разнообразием вариантов команды JSR это выглядит особо изящно, но и на любой платформе со стеком, доступным программно, хотя бы на уровне PUSH/POP, все и выглядит и работает нормально.

Вот реализация для AVR:


Используется это так:

Код:
Interrupt_Label:         ; Сюда ссылается один из (r)jmp из таблицы векторов
   push   r16
   rcall   inten
   ...      ; Здесь располагается индивидуальная программа обслуживания
   ...      ; этого конкретного прерывания
   ret      ;  Заканчивается она RET'ом, а не RETI. Регистр R16 будет восстановлен позже,
; в общей программе, о нем заботиться не нужно.


Здесь RCALL INTEN - не вызов подпрограммы INTEN, а безусловный переход к ней с передачей в стеке параметра - адреса индивидуальной подпрограммы обслуживания этого конкретного прерывания, которая пишется после этого RCALL'а. Завершается она обычным RET'ом, после которого в общей программе будут восстановлены все регистры, включая SREG и сохраненный перед переходом к INTEN R16, после чего будет сделатн RETI.

Собственно, этот прием - разновидность использования сопрограмм, здесь индивидуальная подпрограмма обслуживания конкретного прерывания вызывается, как сопрограмма, на жаргоне тех времен говорили "засопрограммить". Так вот, "засопрограммить" ожидание прерывания в сложном драйвере какого-либо устройства - тоже очень плодотворный прием, например, при реализации сложного протокола передачи/приема данных через USART. Вместо могучего switch'а, который разбирается, куда надо идти, получив очередное прерывание, пишем простую линейную или разветвленную программу, а в месте, где требуется подождать очередного прерывания, пишем, допустим, RCALL TOWait, а эта "подпрограмма" сохранит в статической памяти все, что надо, включая адрес возврата в вызвавшую ее программу и выйдет из прерывания. Затем, когда произойдет прерывание, вторая часть этой "подпрограммы" восстановит све сохраненное ее первой частью и перейдет по сохраненному адресу, то есть на команду, следующую за тем самым RCALL TOWait. Вот, опять же, пример для AVR:

В начале примера стоит обслуживание таймера Т0, который обеспечивает прерывания с частотой 256 Гц (кварц 14745600, прескалер 256), а далее - сама программа ожидания прерывания от USART'а. Она расчитана на "засопрограммленное" обслуживание входов в прервыание (та самая программа INTEN). Вот сильно урезанный кусочек моего проекта с использованием этой программы:

Для вызова этой программы помещаем адрес буфера в X и пишем
Код:
 cli
 rcall   ttyout
 sei

Сюда управление вернется сразу после первого вызова TOWait. Можно заниматься чем угодно, не трогая USART, R16, X и буфер с сообщением. Когда понадобится передавать новое сообщение, то следует дождаться, пока R16 не обнулится, после чего можно пересылать новое сообщение.

Re: Хитрые, необычные алгоритмы и код

Пн июн 08, 2015 08:04:12

akl писал(а):Здравствуйте. Недавно, на соседнем форуме был задан вопрос о быстром умножении 24-разрядных чисел. Было предложено использование алгоритма Дональда Кнута. В результате появился код, который выполняет
Умножение 24р*24р=48р выполняется за 75 тактов и занимает 65 слов
Умножение 32р*32р=64р выполняется за 134 такта и занимает 117 слов
Формат представления чисел старший-младший

Замечательно! А нет ли где-нибудь готового деления 64-разрядного числа на 32-разрядное, чтобы получить 32р частное и 32р остаток? Время некритично - хоть 100000 тактов.

Re: Хитрые, необычные алгоритмы и код

Пн июн 08, 2015 08:21:05

Для AVR использую такую. Она, правда, примитивна как лом и, наверно, не очень смотрится в этой теме, но в качестве основы, думаю, пойдёт.

Re: Хитрые, необычные алгоритмы и код

Пн июн 08, 2015 09:26:21

По АВРкину варианту... ( по посту afz )
Надо сначала прерывание текущего уровня закрыть, а уж затем на "хвост" переходить.
Ибо пока будет действовать текущее прерывание все другие прерывания будут недоступны.
Т.Е. более оптимально подстановка адреса сопровождающей подпрограммы в стек и RETI с последующим RET из сопровождающей подпрограммы.
in rn,SREG
ldi r16,low (prog)
push r16
ldi r16,high (prog)
push r16
reti
Одначе там несколько нюансов по SREGу - запись не в стек, а в один из регистров регистрового файла и на момент восстановления окантовка из
prog:
; собственно текст программы
CLI
out SREG,rn ; n=2-15
SEI
RET
Правда это только в случае, ежли прерывание данного уровня не произойдет ранее, чем закончится его "хвост" обработки - иначе потребуется "флажковый семафор" для отработки "наложения в период исполнения".
:beer:

Re: Хитрые, необычные алгоритмы и код

Пн июн 08, 2015 10:26:17

BOB51 писал(а):По АВРкину варианту... ( по посту afz )
Надо сначала прерывание текущего уровня закрыть, а уж затем на "хвост" переходить.
Ибо пока будет действовать текущее прерывание все другие прерывания будут недоступны.
Не всегда (далеко не всегда) это критично. Программа обслуживания конкретного прерывания, обычно, короткая - максимум - десяток-другой команд, а чаще всего - меньше. Большие же действия лучше исполнять "в фоне".
BOB51 писал(а):Т.Е. более оптимально подстановка адреса сопровождающей подпрограммы в стек и RETI с последующим RET из сопровождающей подпрограммы.
in rn,SREG
ldi r16,low (prog)
push r16
ldi r16,high (prog)
push r16
reti
Одначе там несколько нюансов по SREGу - запись не в стек, а в один из регистров регистрового файла
Зачем? Чем ему плохо в стеке? Если же задержка от прерывания до реакции на него сильно критична, то этим приемом лучше не пользоваться.
BOB51 писал(а): и на момент восстановления окантовка из
prog:
; собственно текст программы
CLI
out SREG,rn ; n=2-15
SEI
RET
Правда это только в случае, ежли прерывание данного уровня не произойдет ранее, чем закончится его "хвост" обработки - иначе потребуется "флажковый семафор" для отработки "наложения в период исполнения".
:beer:
Я бы в таком случае не стал открывать прерывания "для всех", то есть в общей части. Если уж приспичило их открыть, то это надо делать в индивидуальном обслуживании, предварительно сняв у устройства бит разрешения прерываний от него, а затем сделав SEI. Ну, и, окончив эти (длительные) действия сделал бы CLI, взвел бит разрешения прерываний от устройства и вышел. Естественно, такое можно делать только с устройствами, которые могут подождать. Но лучше, все-таки, перенести длительную обработку в фон.

Re: Хитрые, необычные алгоритмы и код

Пн июн 08, 2015 14:47:23

Почему "не в стек, а в тенёк"...
При переходе подстановкой адреса через стек - лишние сложности по определению места хранения статус-регистра.
Теперь насчет "почему открыто для всех"...
Собственно весь смысл такого приема быстрой реакции на прерывание и состотит в том, чтоб не занимать ресурс обработки прерываний при относительно длинном обработчике.
В противном случае зачем вообще перепрыгивать невесть куда внутри уже действующего прерывания с применением фокуса подстановки, если достаточно простого длинного перехода на обработчик расположенного в таблице векторов? А в конце прцедуры обработки банального RETI...
И лишние ячейки стека не занимаются и излишняя сложность перехода устранена.
Индексный CALL хорош в случае, если вектор прерывания всего один, а обслуживаемых источников несколько (аналогия среднемладших ПИКов). Поскольку у АВРок векторов в достатке, да еще и с некоторой приоритетностью ICALL для трюка прыжка на прикладной участок, да еще с непогашенным прерыванием... как-то излишне наворочено однако... :dont_know:

Re: Хитрые, необычные алгоритмы и код

Вт июн 23, 2015 15:03:54

Немного не в тему, ну да ладно.
Есть у меня любимая игрушка на Андроиде. И как все донатные игрушки она предоставляет выбор: жди или плати. Поскольку я жмот, я жду.
Заметил одну особенность: если подключиться к вайфаю на работе (а может, и не только?) время в выключенном состоянии начинает отсчитывать как-то странно:
Прихожу утром на работу, быстренько поиграю (просто запущу) с вайфаем, выключаю.
После рабочего дня если запустить без_доступа_интернета, окажется что в игре прошло... около 2-х часов. Но если включить инет, игровое время сразу скакнёт на 6 часов вперёд :)))

Re: Хитрые, необычные алгоритмы и код

Пн июн 29, 2015 05:32:57

akl писал(а):Для AVR использую такую. Она, правда, примитивна как лом и, наверно, не очень смотрится в этой теме, но в качестве основы, думаю, пойдёт.
Я надеялся скопипастить... :)

А вот в начале (на первой странице) темы про асм авр таки нашлась полезная ссылка на ссылку на вот этот материал: http://elm-chan.org/cc_e.html, там в разделе AVR assembler libraries много вкусного. И можно скопипастить.

Re: Хитрые, необычные алгоритмы и код

Пн июл 13, 2015 13:37:48

Добрый день, хотелось бы понять как организованы предвыборки у dso138 - набор из которого можно собрать осциллограф. Вот часть схемы отвечающая за это
http://prntscr.com/7s49m7
А вот вся схема.
http://img.yunqudao.com/UploadFolder/4f ... /23_15.JPG
Так как оцифровка производится внутренним АЦП, то для быстрого сохранения надо использовать DMA. Алгоритм получения предвыборок следующий, наполняем половину буфера затем по срабатыванию триггера заполняем оставшуюся часть, в зависимости от настроек количество предвыборок и поствыборок может изменяться.
Надо отметить, что размер буфера DMA можно менять только при выключенyом DMA, поэтому на ходу изменять размер буфера не получится.

Может у кого-то есть идеи как это может быть реализовано?

Вопрос снят разобрался.

Re: Хитрые, необычные алгоритмы и код

Сб авг 08, 2015 20:27:53

baghear писал(а):Вопрос снят разобрался.

Тогда расскажите всем как разобрались.

Re: Хитрые, необычные алгоритмы и код

Сб авг 08, 2015 22:57:57

А вот так
https://m.youtube.com/watch?v=YSC2J1qom2g
Заполняем нужную часть буффера игнорируя триггер, только потом начинаем заполнение буффера по триггеру, буфер кольцевой.

Re: Хитрые, необычные алгоритмы и код

Вс авг 09, 2015 01:22:17

Хочу проконсультироваться по поводу алгоритма.
Например с АЦП в 10 битном формате я снимаю два значения.
Ток и Напряжение. Каждое значение снимаю, к примеру 100 раз за секунду.
Данные надо накапливать в счетчик по Ah и по wh.
Счетчик Аh переменная Unsigned int А - хранит ампер часы
Unsigned char D хранит сотые ампера. Когда D отсчитала 100, А++, а D=0
Каждую 1/100 данные.

Одна сотая Аh = 3600*(АЦП значение 1A) если значение 1А = 100 тогда Константа будет 360 000
Теперь мы в переменную каждую сотую секунду будем накапливать значение АЦП, если она перевалит за 360 000
D++, а из переменной мы вычитаем 360 000.
Первая проблема константа вылазит за размерами Int - это создает нагрузку на маленький АВР
Вторая проблема чтоб считать wh потому что и так большую константу надо умножать на напряжение.

Как мне оптимизировать алгоритм для АВР?

Re: Хитрые, необычные алгоритмы и код

Вс авг 09, 2015 07:50:49

У Вас константа 360 000 полезное значение 36, остальные нули. Считайте в KAh, то есть КилоАмперЧасах, то же самое с Ваттами, а лучше спросите в ветке про С там подскажут, я только учусь.

Re: Хитрые, необычные алгоритмы и код

Вс авг 09, 2015 14:04:31

Вы наверное не правильно поняли меня? Притом вопрос адресован всем.
Что бы лучше понять посмотрите картинку.
Это дисплей на котором я вывожу информацию
Как видите выводится ампер часы с точностью до одной сотой.
Но этот счетчик постоянно тикает по мере чего реально ток течет через шунт.
Замеры тока делаю 100 раз в секунду.
Значение может быть от 0 до 1023 в 10 битном формате.
Дальше предположим что в результате калибровки я выяснил что при значение 100 это ток в 1А. Но один ампер может быть и 99 и 102. На разных девайсах значение может немножко отличатся.
А в течение одно часа это 3600сек * 100измерений в сек = получаем 360 000 измерений за час
А значение 1А = 100 АЦП значений тогда получается что 1 Ампер час равняется 360 000 * 100 = 36 000 000 АЦП значений
Но поскольку 0.01 Аh это одна сотая ампера то это в 100 раз меньше.
То есть 360 000 АЦП значений равняется одной сотой ампера. Но это при условии что 1 = 100 АЦП значений
если 1 А = 130 АЦП значений, тогда 0.01Ah = 468 000 АЦП значений

как все работает допустим то 2,3А в момент измерения = 230 АЦП значений - суммируем
следующее измерение 235 - суммируем
следующее измерение 250 - суммируем
следующее измерение 295 - суммируем
и так далее
и каждый раз сравниваем сумму с 360 000
Если сумма перевалила за 360 000 тогда сумма = сумма - 360 000
а сотые Ah увеличивается на одно значение.
и продолжаем дальше.

Поскольку 360 000 больше 65535 это получается уже переменная типа long, а с такой переменной МК 8бит пахать и пахать
суммировать и сравнивать - мучительные операции. Вот и думаю как улучшить алгоритм.


Изображение
Вложения
lcd-ah.PNG
(2.48 KiB) Скачиваний: 1348
Ответить