добрый вечер господа!!!поделиться пока нечем но нужна помощь...суть такова ,что мне нужен алгоритм для реализации шим в атмега8 таймер 16ти битный , хочу использовать его выводы для управления оборотами двигателя..суть проблемы как реализовать дэад тайм?? буду использовать 2 канала .сигналы на выходе в противофазе.как работает таймер и режим шим я в курсе .спасибо за помощь.))пример на асм был бы тоже кстати для понимания
Просто задавать коэффициент заполнения так, чтобы каналы в сумме не давали 100% (255).
Например, один ШИМ-канал настраиваем как обычно, второй с инверсией, и задаем для одного значение ШИМ 120, а для другого 128, например. Получится защитный интервал в 8 отсчетов таймера, когда оба канала выключены.
_________________ Разница между теорией и практикой на практике гораздо больше, чем в теории.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
блин чет я в тупике..сделал шим с корекцией фазы но тут проблема..мне надо еще менять частоту в пределах от 50 до 30гц.а в этом режиме никак..только разными коэфициентами деления таймера..деад тайм получается но тоже не важнецкий скважность не должна превышать 50%..что делать подскажите плиз
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Пн июн 08, 2015 07:58:46
Опытный кот
Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42 Сообщений: 744 Откуда: Караганда, Казахстан
Рейтинг сообщения:0
А я снова о прерываниях.
Не всегда реакция на прерывание должна быть немедленной (мгновенной) Большей частью это не так. Чаще всего задержка от прерывания до реакции на него в десяток-другой команд ничего плохого за собой не влечет. Если задача укладывается в эти рамки, то есть возможность использовать общую программу обслуживания прерываний, которая сохраняет-восстатавливает SREG и избранные регистры, а, при нужде, может и запустить селектор задач, переключить стек в вытесняющей многозадачке и т.п.
Сам прием я подсмотрел в недрах ядра RT-11. Конечно, на PDP-11 с ее разнообразием вариантов команды JSR это выглядит особо изящно, но и на любой платформе со стеком, доступным программно, хотя бы на уровне PUSH/POP, все и выглядит и работает нормально.
Вот реализация для AVR: Спойлер
Код:
; Общий вход в прерывания. ; Перед вызовом сохранить R16 ; Здесь сохраняются SREG, R17,18, X и Z
IntEn: pop r16 ; Достаем адрес возврата sts reta1,r16 ; из стека и сохраняем его pop r16 ; в статической памяти. sts reta1+1,r16 ; Прерывания здесь закрыты, ; reta1, если где и использую, ; то тоже при закрытых прерываниях
; Далее сохраняемся in r16,SREG; push r16 push r17 push r18 push xh push xl push zh push zl
lds zh,reta1 ; и вызовем продолжение, как сопрограмму. lds zl,reta1+1 ; Оно закончится ret'ом, после его выполнения icall ; вернемся сюда.
; Восстановимся pop zl pop zh pop xl pop xh pop r18 pop r17 pop r16 out SREG,r16
; Восстановим R16, сохраненный перед вызовом inten pop r16 reti ; и чао-какао!
Используется это так:
Код:
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). Вот сильно урезанный кусочек моего проекта с использованием этой программы: Спойлер
Код:
TTYOUT: ; Первый вызов - синхронный
ldi r16,1 ; Взведем флаг "Есть данные на передачу" sbi UCSRB,UDRIE ; разрешим прерывание для передачи данных через USART rcall towait ; и вызываем "ожидание". На самом деле это выход из ; программы, сюда вернемся асинхронно, после прерывания
ldi r17,1 ; Передадим заголовок out udr,r17 ; (байты 0x01, 0x00) ldi r17,0 ; out udr,r17 ;
; А это - цикл побайтовой передачи данных из буфера (Х), в конце - 0x00
Для вызова этой программы помещаем адрес буфера в X и пишем
Код:
cli rcall ttyout sei
Сюда управление вернется сразу после первого вызова TOWait. Можно заниматься чем угодно, не трогая USART, R16, X и буфер с сообщением. Когда понадобится передавать новое сообщение, то следует дождаться, пока R16 не обнулится, после чего можно пересылать новое сообщение.
_________________ Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Пн июн 08, 2015 08:04:12
Опытный кот
Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42 Сообщений: 744 Откуда: Караганда, Казахстан
Рейтинг сообщения:0
akl писал(а):
Здравствуйте. Недавно, на соседнем форуме был задан вопрос о быстром умножении 24-разрядных чисел. Было предложено использование алгоритма Дональда Кнута. В результате появился код, который выполняет Умножение 24р*24р=48р выполняется за 75 тактов и занимает 65 слов Умножение 32р*32р=64р выполняется за 134 такта и занимает 117 слов Формат представления чисел старший-младший
Замечательно! А нет ли где-нибудь готового деления 64-разрядного числа на 32-разрядное, чтобы получить 32р частное и 32р остаток? Время некритично - хоть 100000 тактов.
_________________ Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Для AVR использую такую. Она, правда, примитивна как лом и, наверно, не очень смотрится в этой теме, но в качестве основы, думаю, пойдёт. Спойлер
Код:
; Программа деления 78 разрядного числа на 78 разрядное число ; R0...R9-ДЕЛИМОЕ, R10...R19-ДЕЛИТЕЛЬ!!!!R0...R9-РЕЗУЛЬТАТ ; R20...R29-РЕЗУЛЬТАТ,ZL-TEMP, ZH-ZERO ;********************************************************************** GDIV_ERROR: SET GDIV_OUT2: RET DIV: CLT ; сбос флага ошибки, если это не было сделано при входе в программу
SET ; нет, взвести в 1 сооответствующий разряд результата T_DIV20: ROL R29 ROL R28 ROL R27 ROL R26 ROL R25 ROL R24 ROL R23 ROL R22 ROL R21 ROL R20 BRTS T_DIV40
SUB R9,R19 SBC R8,R18 SBC R7,R17 SBC R6,R16 SBC R5,R15 SBC R4,R14 SBC R3,R13 SBC R2,R12 SBC R1,R11 SBC R0,R10 T_DIV40: DEC ZL BRNE T_DIV0 ;*************************************************************************** ; проверка остатка для округления результата DIV_OUT: LSL R9 ROL R8 ROL R7 ROL R6 ROL R5 ROL R4 ROL R3 ROL R2 ROL R1 ROL R0 ; остаток*2 или 0.ххх*2
По АВРкину варианту... ( по посту 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 Правда это только в случае, ежли прерывание данного уровня не произойдет ранее, чем закончится его "хвост" обработки - иначе потребуется "флажковый семафор" для отработки "наложения в период исполнения".
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Пн июн 08, 2015 10:26:17
Опытный кот
Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42 Сообщений: 744 Откуда: Караганда, Казахстан
Рейтинг сообщения:0
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 Правда это только в случае, ежли прерывание данного уровня не произойдет ранее, чем закончится его "хвост" обработки - иначе потребуется "флажковый семафор" для отработки "наложения в период исполнения".
Я бы в таком случае не стал открывать прерывания "для всех", то есть в общей части. Если уж приспичило их открыть, то это надо делать в индивидуальном обслуживании, предварительно сняв у устройства бит разрешения прерываний от него, а затем сделав SEI. Ну, и, окончив эти (длительные) действия сделал бы CLI, взвел бит разрешения прерываний от устройства и вышел. Естественно, такое можно делать только с устройствами, которые могут подождать. Но лучше, все-таки, перенести длительную обработку в фон.
_________________ Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Почему "не в стек, а в тенёк"... При переходе подстановкой адреса через стек - лишние сложности по определению места хранения статус-регистра. Теперь насчет "почему открыто для всех"... Собственно весь смысл такого приема быстрой реакции на прерывание и состотит в том, чтоб не занимать ресурс обработки прерываний при относительно длинном обработчике. В противном случае зачем вообще перепрыгивать невесть куда внутри уже действующего прерывания с применением фокуса подстановки, если достаточно простого длинного перехода на обработчик расположенного в таблице векторов? А в конце прцедуры обработки банального RETI... И лишние ячейки стека не занимаются и излишняя сложность перехода устранена. Индексный CALL хорош в случае, если вектор прерывания всего один, а обслуживаемых источников несколько (аналогия среднемладших ПИКов). Поскольку у АВРок векторов в достатке, да еще и с некоторой приоритетностью ICALL для трюка прыжка на прикладной участок, да еще с непогашенным прерыванием... как-то излишне наворочено однако...
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Вт июн 23, 2015 15:03:54
Друг Кота
Карма: 67
Рейтинг сообщений: 1012
Зарегистрирован: Чт сен 18, 2008 12:27:21 Сообщений: 18809 Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения:0 Медали: 1
Немного не в тему, ну да ладно. Есть у меня любимая игрушка на Андроиде. И как все донатные игрушки она предоставляет выбор: жди или плати. Поскольку я жмот, я жду. Заметил одну особенность: если подключиться к вайфаю на работе (а может, и не только?) время в выключенном состоянии начинает отсчитывать как-то странно: Прихожу утром на работу, быстренько поиграю (просто запущу) с вайфаем, выключаю. После рабочего дня если запустить без_доступа_интернета, окажется что в игре прошло... около 2-х часов. Но если включить инет, игровое время сразу скакнёт на 6 часов вперёд
_________________ [ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ] Измерить нннада?
Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
Добавлено: Пн июн 29, 2015 05:32:57
Опытный кот
Карма: 13
Рейтинг сообщений: 163
Зарегистрирован: Сб дек 22, 2012 08:17:42 Сообщений: 744 Откуда: Караганда, Казахстан
Рейтинг сообщения:0
akl писал(а):
Для AVR использую такую. Она, правда, примитивна как лом и, наверно, не очень смотрится в этой теме, но в качестве основы, думаю, пойдёт.
Я надеялся скопипастить...
А вот в начале (на первой странице) темы про асм авр таки нашлась полезная ссылка на ссылку на вот этот материал: http://elm-chan.org/cc_e.html, там в разделе AVR assembler libraries много вкусного. И можно скопипастить.
_________________ Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Добрый день, хотелось бы понять как организованы предвыборки у dso138 - набор из которого можно собрать осциллограф. Вот часть схемы отвечающая за это http://prntscr.com/7s49m7 А вот вся схема. http://img.yunqudao.com/UploadFolder/4f ... /23_15.JPG Так как оцифровка производится внутренним АЦП, то для быстрого сохранения надо использовать DMA. Алгоритм получения предвыборок следующий, наполняем половину буфера затем по срабатыванию триггера заполняем оставшуюся часть, в зависимости от настроек количество предвыборок и поствыборок может изменяться. Надо отметить, что размер буфера DMA можно менять только при выключенyом DMA, поэтому на ходу изменять размер буфера не получится.
Может у кого-то есть идеи как это может быть реализовано?
А вот так https://m.youtube.com/watch?v=YSC2J1qom2g Заполняем нужную часть буффера игнорируя триггер, только потом начинаем заполнение буффера по триггеру, буфер кольцевой.
Хочу проконсультироваться по поводу алгоритма. Например с АЦП в 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 потому что и так большую константу надо умножать на напряжение.
У Вас константа 360 000 полезное значение 36, остальные нули. Считайте в KAh, то есть КилоАмперЧасах, то же самое с Ваттами, а лучше спросите в ветке про С там подскажут, я только учусь.
Вы наверное не правильно поняли меня? Притом вопрос адресован всем. Что бы лучше понять посмотрите картинку. Это дисплей на котором я вывожу информацию Как видите выводится ампер часы с точностью до одной сотой. Но этот счетчик постоянно тикает по мере чего реально ток течет через шунт. Замеры тока делаю 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бит пахать и пахать суммировать и сравнивать - мучительные операции. Вот и думаю как улучшить алгоритм.
Сейчас этот форум просматривают: Google [Bot] и гости: 28
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения