
Ассемблер (ASM) для AVR в вопросах и ответах
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Ну аот, пока раскурил даташит - ты уже готовый пример дал. Разобрался я. CTC работает только по совпадению А, а прерывания по обеим. Так что ставим A=2B и получаем меандр! 

- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Всё верно.
Удачи в обучениях. 

I am DX168B and this is my favourite forum on internet!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Спасибо.
Проверил, всё нормально. Вставить только коррекцию на 4 такта на прерывание и возврат из него.
Проверил, всё нормально. Вставить только коррекцию на 4 такта на прерывание и возврат из него.
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Да. Тут это надо учесть. Иначе он из прерываний не будет вылезать. Если в твоём проекте таймер работает без деления частоты, то в принципе всё готово. Ну а если используется деление тактов через прескаллер, то можно и его сбрасывать СТС режимом, если есть критичность к точности начала первого меандра генерируемой частоты. Ведь подделитель по сути является счётчиком. В даташите должно быть описано, каким битом и в каком регистре это делается или настраивается.
I am DX168B and this is my favourite forum on internet!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Нет, тут точность не нужна. Посчитал. Предел - 20 тактов (число 20 в регистре A, 10 в B), при этом между прерываниями он выполняет 1 команду основного цикла.
Для опроса кнопок больше и не надо. Соответственно и частота на выходе = csk/20. Если взять кварц на 20 - имеем чистый мегагерц меандра + немного полезной работы
Так же имеем настройку частоты на выходе в плоть до csk/254
Для опроса кнопок больше и не надо. Соответственно и частота на выходе = csk/20. Если взять кварц на 20 - имеем чистый мегагерц меандра + немного полезной работы
Так же имеем настройку частоты на выходе в плоть до csk/254
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Считается кстати просто: 4+4 (вход-выход в прерывание) +1 (команда внутри) + столько-же второе прерывание + команда основного цикла = (8+1) + (8+1) + 1 = 19. Пополам не делится, берём 20.
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Намотаю себе на ус.
К стати, мы входим в прерывание. Сначала попадаем на вектор, а от туда, через rjmp в сам обработчик. У нас случайно не больше тактов уйдёт на вход в прерывание?
RJMP помоему больше 1го такта съедает + 1 такт на попадание в вектор прерывания ещё до rjmp.
RJMP помоему больше 1го такта съедает + 1 такт на попадание в вектор прерывания ещё до rjmp.
I am DX168B and this is my favourite forum on internet!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
rjmp - два
вход в прерывание - 4
выход - 4
(там операции со стеком)
Точно... Про вектор я и забыл. Но ситуация такая: reti всегда возвращает на следующую команду, которая выполнится, и только потом сработает следующее прерывание.
Во всяком случае при меньших цифрах всё равно по одной команде выполняется внутри цикла (я их даже пометил, чтоб не ошибиться)
вход в прерывание - 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:
nop ;1
nop ;2
nop ;3
nop ;4
RJMP LOOP
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Возможно, где-то я и затупил, но у меня вышло следующее, если верить счётчику тактов студии:
4 такта - попадание в вектор.
2 такта - прыжок с него в обработчик.
1 такт - команда внутри обработчика.
4 такта - выход из прерывания.
Итог - 11 тактов на обработку одного прерывания.
22 такта на обработку обоих прерываний.
4 такта в основной программе(4 NOPа) + 2 такта на прыжок (RJMP LOOP) Всего 6 тактов.
Наверное можно включить ещё один такт к обработчику прерывания. Когда в регистре TCNT число становится равным регистру OCR, то флаг прерывания выставляется моментально, но только при следующем такте начинается процесс входа в вектор. Хотя нет. Всё правильно.
4 такта - попадание в вектор.
2 такта - прыжок с него в обработчик.
1 такт - команда внутри обработчика.
4 такта - выход из прерывания.
Итог - 11 тактов на обработку одного прерывания.
22 такта на обработку обоих прерываний.
4 такта в основной программе(4 NOPа) + 2 такта на прыжок (RJMP LOOP) Всего 6 тактов.
Наверное можно включить ещё один такт к обработчику прерывания. Когда в регистре TCNT число становится равным регистру OCR, то флаг прерывания выставляется моментально, но только при следующем такте начинается процесс входа в вектор. Хотя нет. Всё правильно.
Последний раз редактировалось DX168B Сб янв 29, 2011 01:27:46, всего редактировалось 2 раза.
I am DX168B and this is my favourite forum on internet!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Ну да, всё правильно.
В коде у меня стоят цифры 5 и 10, что явно меньше 22х. И всё равно студия между прерываниями обрабатывает по одному нопу. Значит отлично - не обсчитаешься, основной код всегда будет потихоньку ползти. Допустим на те же кнопки и индикацию с лихвой хватит.
В коде у меня стоят цифры 5 и 10, что явно меньше 22х. И всё равно студия между прерываниями обрабатывает по одному нопу. Значит отлично - не обсчитаешься, основной код всегда будет потихоньку ползти. Допустим на те же кнопки и индикацию с лихвой хватит.
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Всё... Теперь всё на своих местах.... 
I am DX168B and this is my favourite forum on internet!
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Может, я спросонок чего-то не понял, но если уже всё равно таймер в режиме CTC (т.е. таймер уже всё равно свёрнут до периода меандра), то зачем прерывания и зачем себя ограничивать по частоте?
При 8-мегагерцовом внутреннем RC отлично генерит меандр 4МГц на OC0A
Я на тини15 с внутренним 1.6 МГц делал управление линейкой S9226, генерировал 0.4 МГц такт аппаратно и синхронно с ним стартовый импульс программно. При этом ещё опрос кнопок для регулирования в +- пероида накопления сигнала и двиганья влево-вправо строба на осциллограф.
Код: Выделить всё
.nolist
#define __SFR_OFFSET 0
#include <avr/io.h>
.list
.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Я на тини15 с внутренним 1.6 МГц делал управление линейкой S9226, генерировал 0.4 МГц такт аппаратно и синхронно с ним стартовый импульс программно. При этом ещё опрос кнопок для регулирования в +- пероида накопления сигнала и двиганья влево-вправо строба на осциллограф.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Кстати, как раз для той линейки я меандр генерировал несколько более сложным образом. Мне нужна была в программе привязка к фазе меандра, а в режиме инверсии вывода по совпадению значение TCNT0 такой информации не несёт.
Можно установить FAST PWM + CTC, тогда период PWM определяется OCR0A, а на OCR0B получаем ШИМ.
Если в OCR0B занести половинку преиода, опять получим меандр.
Итого код
генерирует три меандра.
OCR0B - 1/2 тактовой частоты процессора
OCR0A - 1/4 тактовой
PORTB7 - 1/8 тактовой.
Если цикл в конце заменить полезной работой. то есть два меандра и полностью свободый процессор.
Можно установить FAST PWM + CTC, тогда период PWM определяется OCR0A, а на OCR0B получаем ШИМ.
Если в OCR0B занести половинку преиода, опять получим меандр.
Итого код
Код: Выделить всё
.nolist
#define __SFR_OFFSET 0
#include <avr/io.h>
.list
.set period, 2 ; Период меандра в два такта генератора
;----------
.text
.global main
main:
ldi r16,0xFF
out DDRD, r16
ldi r16, period - 1
out OCR0A, r16
ldi r16, period/2 - 1
out OCR0B, r16
ldi r16, (1<<COM0A0) | (1<<COM0B1) | (1<<WGM01) | (1<<WGM00)
out TCCR0A, r16
ldi r16, (1<<WGM02) | (1<<CS00)
out TCCR0B, r16
1: sbi PIND,7
rjmp 1b
.endOCR0B - 1/2 тактовой частоты процессора
OCR0A - 1/4 тактовой
PORTB7 - 1/8 тактовой.
Если цикл в конце заменить полезной работой. то есть два меандра и полностью свободый процессор.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
avreal писал(а):Может, я спросонок чего-то не понял, но если уже всё равно таймер в режиме CTC (т.е. таймер уже всё равно свёрнут до периода меандра), то зачем прерывания и зачем себя ограничивать по частоте?
Было бы всё так просто, то мы бы не дёргали портом в прерываниях и так бы не извращались.
Дело в том, что нам надо было вывести меандр совсем из другого вывода, так как на ноге, которая предназначена для выхода ШИМа, уже сидела другая периферия и нам надо было дёргать другой ногой.
Ну вот например мой МК (ATTINY26L) имеет на борту встроенный RC генератор на 64МГц
для ШИМа.

I am DX168B and this is my favourite forum on internet!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Да, DX168B точно понял ситуацию. Задействовать аппаратный режим проблем нет. Да и вообще, при необходимости, можно впаять отдельный кварцевый генератор (стоит около 30 рублей) и не трогать контроллер.
Тут скорее интересная головоломка, нежели практическая необходимость. Которую мы решили!
Тут скорее интересная головоломка, нежели практическая необходимость. Которую мы решили!
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
DX168B писал(а):надо было вывести меандр совсем из другого вывода, так как на ноге, которая предназначена для выхода ШИМа, уже сидела другая периферия и нам надо было дёргать другой ногой
Опять же похвастаю, в СиЛабовских контроллерах нет жёсткой привязки периферии к конкретному выводу МК
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
А на мощных ПЛИСах можно даже пень III отгрохать, если постараться.
А мы решаем нестандартную задачу.
Чем-то напоминает передачи из Discovery, типа "Свалка"
Есть куча хлама и нам надо сделать что-то работающее.
А мы решаем нестандартную задачу.
Есть куча хлама и нам надо сделать что-то работающее.
I am DX168B and this is my favourite forum on internet!
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Точно, я просто тему невнимательно просмотрел, там явно о занятости ног сказано было. Вот как бывает, сначала какой-то светодиод или кнопка займёт ногу ШИМ, а потом корячиться приходится. Как в той байке про инженера, которого берут на ставку уборщицы потому, что ставка инжерена уже занята. Уборщицей. Которую брали на работу, когда ставка уборщицы была занята электриком.DX168B писал(а):Дело в том, что нам надо было вывести меандр совсем из другого вывода, так как на ноге, которая предназначена для выхода ШИМа, уже сидела другая периферия и нам надо было дёргать другой ногой.
Старушка tiny15 тоже не дура в этом смысле. А на тини26 я лет семь назад приставалку к людям делал (ик-барьер и рекламная требуха из AT45DB на динамик при подходе к стенду с товаром), звук тем ШИМ-ом и делал.DX168B писал(а):Ну вот например мой МК (ATTINY26L) имеет на борту встроенный RC генератор на 64МГц для ШИМа.
А по барабану, там можно хоть 1 и 2 поставить. Всё равно между прерываниями будет по команде из основного кода, а прерывание будет выполняться столько, сколько сможет. Просто флаги взводиться будут несколько раз подряд без обработки. Фигня может быть в одном случае - если запросы идут слишком часто (за время обработки OCR0A срабатывает дважды), то по выходу из обработчика OCR0A опять вызовется он же, а OCR0B не вызовется, так как у него ниже так называемый приоритет. Т.е. при слишком частых запросах выполняться будет только OCR0A и на линии будет фиксированный уровень. В переходной зоне будет в разы прыгать период - OCR0B то будет вклиниваться, то не будет.ploop писал(а):В коде у меня стоят цифры 5 и 10, что явно меньше 22х. И всё равно студия между прерываниями обрабатывает по одному нопу. Значит отлично - не обсчитаешься, основной код всегда будет потихоньку ползти. Допустим на те же кнопки и индикацию с лихвой хватит.
И, кстати, в первый раз такты были посчитаны правильно
Тогда минимальное время обработки 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Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Я не понял, как у вас происходит инвертирование бита. Поясните пожалуйста.
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
У всех «достаточно новых» 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. Если есть такая вот запись через мультиплексор, то это оно.
Там же и в тексте абзац
Триггер хранения состояния выхода 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.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.