Ну аот, пока раскурил даташит - ты уже готовый пример дал. Разобрался я. CTC работает только по совпадению А, а прерывания по обеим. Так что ставим A=2B и получаем меандр!
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Сб янв 29, 2011 00:10:33
Друг Кота
Карма: 25
Рейтинг сообщений: 99
Зарегистрирован: Вс янв 24, 2010 19:19:52 Сообщений: 4468 Откуда: Главный Улей России (Moscow)
Рейтинг сообщения:0
Да. Тут это надо учесть. Иначе он из прерываний не будет вылезать. Если в твоём проекте таймер работает без деления частоты, то в принципе всё готово. Ну а если используется деление тактов через прескаллер, то можно и его сбрасывать СТС режимом, если есть критичность к точности начала первого меандра генерируемой частоты. Ведь подделитель по сути является счётчиком. В даташите должно быть описано, каким битом и в каком регистре это делается или настраивается.
_________________ I am DX168B and this is my favourite forum on internet!
Нет, тут точность не нужна. Посчитал. Предел - 20 тактов (число 20 в регистре A, 10 в B), при этом между прерываниями он выполняет 1 команду основного цикла. Для опроса кнопок больше и не надо. Соответственно и частота на выходе = csk/20. Если взять кварц на 20 - имеем чистый мегагерц меандра + немного полезной работы Так же имеем настройку частоты на выходе в плоть до csk/254
Считается кстати просто: 4+4 (вход-выход в прерывание) +1 (команда внутри) + столько-же второе прерывание + команда основного цикла = (8+1) + (8+1) + 1 = 19. Пополам не делится, берём 20.
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Сб янв 29, 2011 00:44:28
Друг Кота
Карма: 25
Рейтинг сообщений: 99
Зарегистрирован: Вс янв 24, 2010 19:19:52 Сообщений: 4468 Откуда: Главный Улей России (Moscow)
Рейтинг сообщения:0
Намотаю себе на ус. К стати, мы входим в прерывание. Сначала попадаем на вектор, а от туда, через rjmp в сам обработчик. У нас случайно не больше тактов уйдёт на вход в прерывание? RJMP помоему больше 1го такта съедает + 1 такт на попадание в вектор прерывания ещё до rjmp.
_________________ I am DX168B and this is my favourite forum on internet!
rjmp - два вход в прерывание - 4 выход - 4 (там операции со стеком) Точно... Про вектор я и забыл. Но ситуация такая: reti всегда возвращает на следующую команду, которая выполнится, и только потом сработает следующее прерывание. Во всяком случае при меньших цифрах всё равно по одной команде выполняется внутри цикла (я их даже пометил, чтоб не ошибиться)
Код:
.include "m48def.inc" ;---------- .cseg .org 0x0000 rjmp RESET .org OC0Aaddr rjmp TIM1_COMPA .org OC0Baddr rjmp TIM1_COMPB ;---------- .org INT_VECTORS_SIZE TIM1_COMPA: nop reti ;---------- TIM1_COMPB: nop reti ;---------- RESET: ldi r16, Low(ramend) out SPL, r16 ldi r16, High(ramend) out SPH, r16 ;---------- ldi r16,10 out OCR0A, r16 ldi r16, 5 out OCR0B, r16
ldi r16, (1<<WGM01) out TCCR0A, r16 ldi r16, (1<<OCIE0A)+(1<<OCIE0B) sts TIMSK0, r16 ldi r16, (1<<CS00) out TCCR0B, r16 sei ;---------- LOOP:
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Сб янв 29, 2011 01:19:38
Друг Кота
Карма: 25
Рейтинг сообщений: 99
Зарегистрирован: Вс янв 24, 2010 19:19:52 Сообщений: 4468 Откуда: Главный Улей России (Moscow)
Рейтинг сообщения:0
Возможно, где-то я и затупил, но у меня вышло следующее, если верить счётчику тактов студии: 4 такта - попадание в вектор. 2 такта - прыжок с него в обработчик. 1 такт - команда внутри обработчика. 4 такта - выход из прерывания. Итог - 11 тактов на обработку одного прерывания. 22 такта на обработку обоих прерываний. 4 такта в основной программе(4 NOPа) + 2 такта на прыжок (RJMP LOOP) Всего 6 тактов.
Наверное можно включить ещё один такт к обработчику прерывания. Когда в регистре TCNT число становится равным регистру OCR, то флаг прерывания выставляется моментально, но только при следующем такте начинается процесс входа в вектор. Хотя нет. Всё правильно.
_________________ I am DX168B and this is my favourite forum on internet!
Последний раз редактировалось DX168B Сб янв 29, 2011 01:27:46, всего редактировалось 2 раз(а).
Ну да, всё правильно. В коде у меня стоят цифры 5 и 10, что явно меньше 22х. И всё равно студия между прерываниями обрабатывает по одному нопу. Значит отлично - не обсчитаешься, основной код всегда будет потихоньку ползти. Допустим на те же кнопки и индикацию с лихвой хватит.
Может, я спросонок чего-то не понял, но если уже всё равно таймер в режиме CTC (т.е. таймер уже всё равно свёрнут до периода меандра), то зачем прерывания и зачем себя ограничивать по частоте?
.set period, 2 ; Период меандра в два такта генератора - минимальный.
;---------- .text .global main main: ldi r16, 0xFF out DDRD, r16 ldi r16, period/2 - 1 out OCR0A, r16 ldi r16, (1<<COM0A0) | (1<<WGM01) out TCCR0A, r16 ldi r16, (1<<CS00) out TCCR0B, r16
; а тут период меандра в восемь тактов генератора, что естественно 1: sbi PIND,7 rjmp 1b
.end
При 8-мегагерцовом внутреннем RC отлично генерит меандр 4МГц на OC0A Я на тини15 с внутренним 1.6 МГц делал управление линейкой S9226, генерировал 0.4 МГц такт аппаратно и синхронно с ним стартовый импульс программно. При этом ещё опрос кнопок для регулирования в +- пероида накопления сигнала и двиганья влево-вправо строба на осциллограф.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Кстати, как раз для той линейки я меандр генерировал несколько более сложным образом. Мне нужна была в программе привязка к фазе меандра, а в режиме инверсии вывода по совпадению значение TCNT0 такой информации не несёт.
Можно установить FAST PWM + CTC, тогда период PWM определяется OCR0A, а на OCR0B получаем ШИМ. Если в OCR0B занести половинку преиода, опять получим меандр. Итого код
Если цикл в конце заменить полезной работой. то есть два меандра и полностью свободый процессор.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Сб янв 29, 2011 18:54:45
Друг Кота
Карма: 25
Рейтинг сообщений: 99
Зарегистрирован: Вс янв 24, 2010 19:19:52 Сообщений: 4468 Откуда: Главный Улей России (Moscow)
Рейтинг сообщения:0
avreal писал(а):
Может, я спросонок чего-то не понял, но если уже всё равно таймер в режиме CTC (т.е. таймер уже всё равно свёрнут до периода меандра), то зачем прерывания и зачем себя ограничивать по частоте?
Было бы всё так просто, то мы бы не дёргали портом в прерываниях и так бы не извращались. Дело в том, что нам надо было вывести меандр совсем из другого вывода, так как на ноге, которая предназначена для выхода ШИМа, уже сидела другая периферия и нам надо было дёргать другой ногой. Ну вот например мой МК (ATTINY26L) имеет на борту встроенный RC генератор на 64МГц для ШИМа.
_________________ I am DX168B and this is my favourite forum on internet!
Да, DX168B точно понял ситуацию. Задействовать аппаратный режим проблем нет. Да и вообще, при необходимости, можно впаять отдельный кварцевый генератор (стоит около 30 рублей) и не трогать контроллер. Тут скорее интересная головоломка, нежели практическая необходимость. Которую мы решили!
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Сб янв 29, 2011 20:33:37
Друг Кота
Карма: 67
Рейтинг сообщений: 1060
Зарегистрирован: Чт сен 18, 2008 12:27:21 Сообщений: 19768 Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения:0 Медали: 1
DX168B писал(а):
надо было вывести меандр совсем из другого вывода, так как на ноге, которая предназначена для выхода ШИМа, уже сидела другая периферия и нам надо было дёргать другой ногой
Опять же похвастаю, в СиЛабовских контроллерах нет жёсткой привязки периферии к конкретному выводу МК
_________________ [ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ] Измерить нннада?
Заголовок сообщения: Re: Ассемблер (ASM) для AVR в вопросах и ответах
Добавлено: Сб янв 29, 2011 22:52:32
Друг Кота
Карма: 25
Рейтинг сообщений: 99
Зарегистрирован: Вс янв 24, 2010 19:19:52 Сообщений: 4468 Откуда: Главный Улей России (Moscow)
Рейтинг сообщения:0
А на мощных ПЛИСах можно даже пень III отгрохать, если постараться. А мы решаем нестандартную задачу. Чем-то напоминает передачи из Discovery, типа "Свалка" Есть куча хлама и нам надо сделать что-то работающее.
_________________ I am DX168B and this is my favourite forum on internet!
Дело в том, что нам надо было вывести меандр совсем из другого вывода, так как на ноге, которая предназначена для выхода ШИМа, уже сидела другая периферия и нам надо было дёргать другой ногой.
Точно, я просто тему невнимательно просмотрел, там явно о занятости ног сказано было. Вот как бывает, сначала какой-то светодиод или кнопка займёт ногу ШИМ, а потом корячиться приходится. Как в той байке про инженера, которого берут на ставку уборщицы потому, что ставка инжерена уже занята. Уборщицей. Которую брали на работу, когда ставка уборщицы была занята электриком.
DX168B писал(а):
Ну вот например мой МК (ATTINY26L) имеет на борту встроенный RC генератор на 64МГц для ШИМа.
Старушка tiny15 тоже не дура в этом смысле. А на тини26 я лет семь назад приставалку к людям делал (ик-барьер и рекламная требуха из AT45DB на динамик при подходе к стенду с товаром), звук тем ШИМ-ом и делал.
ploop писал(а):
В коде у меня стоят цифры 5 и 10, что явно меньше 22х. И всё равно студия между прерываниями обрабатывает по одному нопу. Значит отлично - не обсчитаешься, основной код всегда будет потихоньку ползти. Допустим на те же кнопки и индикацию с лихвой хватит.
А по барабану, там можно хоть 1 и 2 поставить. Всё равно между прерываниями будет по команде из основного кода, а прерывание будет выполняться столько, сколько сможет. Просто флаги взводиться будут несколько раз подряд без обработки. Фигня может быть в одном случае - если запросы идут слишком часто (за время обработки OCR0A срабатывает дважды), то по выходу из обработчика OCR0A опять вызовется он же, а OCR0B не вызовется, так как у него ниже так называемый приоритет. Т.е. при слишком частых запросах выполняться будет только OCR0A и на линии будет фиксированный уровень. В переходной зоне будет в разы прыгать период - OCR0B то будет вклиниваться, то не будет.
И, кстати, в первый раз такты были посчитаны правильно rjmp из вектора на код не нужен, как не нужны и два прерывания. Если у нас таки мега48, а не что-то старое. Вектора OCR0A и OCR0B идут подряд, можно прерывание OCR0B не использовать и код поместить прямо в зоне векторов, сделав в прерыванииинвертирование состояния ноги. Причём не при помощи SBI, занимающей два такта, а при помощи OUT, занимающей один такт. Тогда минимальное время обработки 4+1+4 = 9 тактов. Заодно при слишком частых запросах просто перестанет уменьшаться период, так как прерывание одно.
Код:
.include "m48def.inc"
.cseg .org 0x0000 rjmp start
.org OC0Aaddr out PINC, r2 ; Инвертируем PORTС5 reti ; Место вектора OC0Baddr - он все равно не используется ; а на меге168 вектора и так по два слова, так что всё влезет на "своё" место
.org INT_VECTORS_SIZE start: ldi r16, Low(ramend) out SPL, r16 ldi r16, High(ramend) out SPH, r16
ldi r16, 3 ; специально явно слишком мальенкое число, чтобы видеть минимальное время out OCR0A, r16
ldi r16, (1<<WGM01) out TCCR0A, r16 ldi r16, (1<<OCIE0A) sts TIMSK0, r16 ldi r16, (1<<CS00) out TCCR0B, r16
ldi r16, (1<<5) | (1<<4) out DDRC, r16 ldi r16, (1<<5) mov r2, r16 ; Занимаем под то дело "нижний", менее дефицитнй, регистр
sei
; надо же как-то увидеть реальную загрузку процессора прерываниями ldi r16, (1<<4) loop: out PINC, r16 ; инвертируем PORTC4 rjmp loop
«меандр», естественно, вышел немного не меандр, так как в осноном коде есть комады с разным временем выполнения. Поскольку команд всего две, по осциллографу на выходе PORTC5 устойчиво единичка (прерываем 1-тактовую команду) немного короче, чем нолик (прерываем 2-тактовую).
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
У всех «достаточно новых» AVR - например, у tiny13, mega48, но не у mega8A (она хоть и новая, но аналог старой mega8) есть такая особенность. Триггер хранения состояния выхода PORTx охвачен обратной связью с инвертором, которая активируется записью единицы в соответствующий PINx При записи в PORT значение в триггер попадает с шины данных, при записи в соответствующий PIN - инверсное значение старого состония. Писать единичку в PIN можно как при помощи SBI, так и при помощи OUT. Нолики в OUT не влияют на состояние соответствующих выходов.
Для конкретного контроллера смотреть картинку в I/O-Ports - Ports as General Digital I/O (там схема проще, так как не замешивается инвертирование по Output Compare) или в Alternate Port Functions. Если есть такая вот запись через мультиплексор, то это оно. Там же и в тексте абзац
Цитата:
Toggling the Pin Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the SBI instruction can be used to toggle one single bit in a port.
_________________ Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 311
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения