Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Roman Venom
Сверлит текстолит когтями
Сообщения: 1135
Зарегистрирован: Сб июл 11, 2009 18:42:21
Откуда: Украина, г.Николаев

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Roman Venom »

akl
По поводу сброса-запуска таймера в прерывании
-запрет прерывания в самом прерывании нелогичен, т.к. I-флаг сбрасывается в прерывании аппаратно. Другое дело очищать флаги или исключать из таблиц состояния вызывающие такие требования (например первый элемент Вашей таблицы, в котором сразу в таймер загружается максимальное число, а таймер не остановлен. Т.е. следующее прерывание будет несанкционированным)
-манипуляции с предустановками в TCNT1 можут привести к появлению флага TOV1, да и другие флаги могут взвестись. Причем на аппаратном уровне. Я так привык делать
-остановил
-очистил, чтобы начинать с одной точки
-загрузил требуемое значение
-сбросил флаги
-запустил
Вы правы. Отлаживал свою программку и столкнулся что прерывания происходят весьма странно.
Итак, для полной прозрачности и уверенности, что всё теперь сделано правильно приведу пример.

Программа делает следующее. В 2-х циклах опрашивается кнопка вкл/выкл.
Когда кнопка нажимается в первом цикле, то начинается второй цикл. Когда нажата во втором - то первый цикл. В первом цикле разрешено прерывание по переполнению таймера 0, во втором таймера 1. Кнопка PA5 при замыкании вызывает "низкий".
Всё что касается настройки таймеров для читабельности подчеркну.

ldi work,0b00000101;
out TIMSK,work;разрешить прерывание по переполнению таймера 0 и таймера
rjmp stop


stop:
ldi work,0b00000100;
out TCCR0,work;выбрать К=256

ldi t_count0,250;
out TCNT0,t_count0;заряжаем таймер


stop1:

sbic PINA,PA5;проверяем на нажатие кнопку
rjmp stop1;не ражата - повторить опрос
otpusk_1:;нажата - проверить на отпускание
sbis PINA,PA5
rjmp otpusk_1
rjmp invertor;отпущена? выключаем таймер, запрещаем прерывания по нему, разрешаем по таймеру 1.

invertor:

ldi work,0b00000000;
out TCCR0,work;останавливаем
ldi t_count0,0;очищаем
out TCNT0,t_count0;заряжаем таймер;выводим.т.е. наш таймер0 "заглушен"


;теперь включаем прерывание по переполнению 16-битного таймера1:

ldi work,0b00000000;
out TCCR1А,work;тут ничего интересного нету, поэтому просто очищаем
ldi work,0b00000010;
out TCCR1В,work;выбрать К=8
ldi t_count1_H,0x01;
ldi t_count1_L,0x01;
out TCNT1H,t_count1_H;заряжаем таймер произвольными значениями, просто чтобы вызвать
out TCNT1L,t_count1_L;прерывание.


sw_pusk:
sbic PINA,PA5;проверяем на нажатие
rjmp sw_pusk;не нажата? повторная проверка
otpusk_2:
sbis PINA,PA5;нажата? проверяем на отпускание
rjmp otpusk_2;
rjmp stop;отпущена? перейти в цикл, где разрешено прерывание по таймеру0

Теперь наше прерывание.


TIM1_OVF:
ldi work,0x00
out TCCR1B,work;останов таймера
out TCNT1H,work;сбросить таймер-счётчик
out TCNT1L,work;

rjmp извлечь из таблички значение
извлечь из таблички значение:
бла-бла-бла. теперь у нас в TCNT1L и TCNT1H нужные числа
rjmp выход

выход:
ldi work,0xFF
out TIFR,work;сброс всех флагов
ldi work,0b00000010
out TCCR1B,work;запустить с К=8

reti
Успех - императив!
Реклама
Аватара пользователя
Roman Venom
Сверлит текстолит когтями
Сообщения: 1135
Зарегистрирован: Сб июл 11, 2009 18:42:21
Откуда: Украина, г.Николаев

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Roman Venom »

avreal
Liv абсолютно прав и для данного случая, ведь из таблички извлекается больше одного байта. Если уж на асме писать, то зачем делать хуже, чем сделает С-компилятор?
Ну у меня 2 таблицы значений. Одна для младшего регистра, другая для старшего. А так, безусловно, такой вариант более оптимальный.
Успех - императив!
Реклама
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение avreal »

Ну так не поленитьcя и слить их в одну правильную :-)
Только учесть переход от байтов к словам, индекс сначала сдвинуть влево (или сразу в программе его изменять всегда на 2, а не на 1).
В примере выше я про это забыл.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение akl »

avreal писал(а): Если уж на асме писать, то зачем делать хуже, чем сделает С-компилятор?
:shock: Использовать в качестве арбитра коды, сгенерированные СИ-компилятором в ветке "Ассемблер (ASM) для AVR в вопросах и ответах" слишком надуманно.
avreal писал(а):...Кстати, а почему в табличке константы хранятся старшим байтом по младшему адресу, неудобно же табличку задавать.
avreal писал(а):Ну так не поленитьcя и слить их в одну правильную
Будучи кодером-самоучкой, посмотрел материал
http://ru.wikipedia.org/wiki/%D0%9F%D0% ... 0%BE%D0%B2
Ваше утверждение о правильном порядке следования байтов малоубедительно. Да, как правило, так принято, но на Истину, в последней инстанции, не тянет. Извините. :oops: Поэтому и сделал такую оговорку.
akl писал(а):За одним попробовал свое представление занесения значений из таблицы в формате старший-младший. Находится в закомментированном T1_OVER1.
Реклама
Эиком - электронные компоненты и радиодетали
SII
Вымогатель припоя
Сообщения: 635
Зарегистрирован: Пт янв 30, 2009 14:50:35
Откуда: Солнечногорск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение SII »

akl писал(а):Ваше утверждение о правильном порядке следования байтов малоубедительно. Да, как правило, так принято, но на Истину, в последней инстанции, не тянет
Не влезая глубоко в спор, замечу, что относительно порядка байтов есть лишь два принципиально возможных подхода.

1. В архитектурах, имеющих средства обработки многобайтовых величин (это любые процессоры с разрядностью, превышающей 8, и некоторые 8-разрядные), хранить эти самые многобайтовые величины надо в том порядке, в каком того требует архитектура. К примеру, в IA-32 (x86) байты всегда хранятся в порядке "младший-старший", в мэйнфреймах IBM -- наоборот, "старший-младший".

2. В архитектурах, не имеющих средств обработки многобайтовых величин, сам по себе порядок хранения многобайтовых данных в памяти является безразличным. Однако не следует забывать про то, что адреса обычно имеют размеры, превышающие один байт, и они тоже иногда хранятся в памяти (например, сохраняются в стеке при вызове подпрограммы). Хотя для выполнения вычислений без разницы, в каком порядке данные находятся в памяти (всё равно обрабатывать их приходится по одному байту), лучше придерживаться того порядка, в котором хранятся адреса, иначе возможно возникновение путаницы (программист вручную выполнил вычисление какого-то адреса, однако сохранил его в памяти не в том порядке, в каком ожидает процессор, потому что привык к другому порядку для хранения обычных чисел).
Реклама
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение avreal »

akl писал(а):
avreal писал(а): Если уж на асме писать, то зачем делать хуже, чем сделает С-компилятор?
:shock: Использовать в качестве арбитра коды, сгенерированные СИ-компилятором в ветке "Ассемблер (ASM) для AVR в вопросах и ответах" слишком надуманно.
Дык эта... «изпод-С-шный» код не «арбитр», а опора, точка отсчёта. Или вспоминать в ветках про асм о коде, сгенерированном С-компилятором можно только тогда, когда человек на асме написал лучше? А когда человек написал две команды LPM и ADIW Z,1 там, где компилятор поставил бы одну LPM R0, Z+ — так уже и нельзя?
akl писал(а):Ваше утверждение о правильном порядке следования байтов малоубедительно. Да, как правило, так принято, но на Истину, в последней инстанции, не тянет.
Даже в приведенных Вами цитатах из моих сообщений говорится не о «правильном порядке байт», а о «правильной табличке». Из двух байтовых сделать одну словную, под выковыривание через LPM R, Z+. По порядку байт — правильную, такую, какая нужна для выбранного варианта кода считывания и занесения в таймер.
Это так — Вы придрались, я придрался, а теперь можно и поговорить :-)
Нравится выковривать из таблички с поряком «старший байт по младшему адресу» — я ж не против. Оно может показаться даже удобнее из-за нужного порядка записи в 16-битные регистры. Я просто показал, что и для «младший байт по млашему адресу» код считывания и записи в таймер выполняется то же время и занимает то же количесвто регистров. Зато удобнее для использования, словную табличку можно задавать через

Код: Выделить всё

  .dw 1025, 255
а не через

Код: Выделить всё

   .db $04, $01, $00, $FF
.
Младший байт по младшему адресу для AVR является естественным порядком (для других контроллеров может быть другое, но говорить о них в ветке про ASM+AVR ещё более «надуманно», чем о C+AVR).
  • Для словного суммирования-вычитания ADIW/SBIW младший байт лежит в регистре с меньшим номером.
  • Результат команд MUL укладывается на регистры так же.
  • Адрес для LPM/IJMP/ICALL в пару Z заносится так же, для LD/ST во все адресные пары заносится так же.
  • У всех 16-битных регистров периферии младший байт находится по младшему адресу
Единственное место, где порядок байт противоположнй — это адрес возврата на стеке. При вызове сначала делается push младшего байта адреса возврата, потом стршего. Но стек растёт вниз, поэтому в памяти выходит старший байт возврата лежит по меньшему адресу. Вот и всё. Но далеко не каждый асм-программист вручную разбрает адреса возврата со стека (хотя иногда на этом можно интересные вещи выкрутить), а RET сам знает, как оно там положено.
Ну и ассемблеры при занесении в память 16-битных слов при помощи .DW/.word заносят младший байт по младшему адресу.
Поэтому с таким порядком байт работать просто удобнее в подавляющем большинстве случаев.

В данном конкретном случае может ещё и стоит глянуть внимательнее, но на первый взгляд две байтовые полутаблицы не дают более короткого и быстрого кода, чем одна словная таблица, для словных таблиц независимо от поряка байт код выходит одинаковым по требуемым ресурсам (флеш, регистры, такты), а задавать табличку с LOW ENDIAN для AVR удобнее.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Реклама
Аватара пользователя
Alexeus
Вымогатель припоя
Сообщения: 690
Зарегистрирован: Вс мар 04, 2007 01:17:12

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeus »

что то не разберусь с массивами. Мега8.

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

Код: Выделить всё


;в тексте программы загружаю адрес метки
ldi XL,low(array*2)
ldi XH,high(array*2)
loop:
;затем пытаюсь загрузить значение в переменную
ld temp,X+
rjmp loop

array: 
.db 1,2,3,4
или массивы только с регистром Z и командой lpm работают???
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение DX168B »

Команда LD работает только с ОЗУ, а LPM с флэшью.

Код: Выделить всё

;**************** ОЗУ ***************
.dseg
buffer:   .byte 4
.cseg
.........
........
ldi  XL,  Low(buffer)
ldi  XH,  High(buffer)
ld  temp,  X  ; (или X+)

;*************** FLASH **************
.cseg
..............
........
array:
.db 0x01, 0x02, 0x03, 0x04
ldi  ZL,  Low(array*2)
ldi  ZH,  High(array*2)
lpm temp,  Z ;(или Z+, или после подгрузки ставишь adiw Z, 0x01)
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
Alexeus
Вымогатель припоя
Сообщения: 690
Зарегистрирован: Вс мар 04, 2007 01:17:12

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeus »

Спасибо. путаюсь я все время с этой памятью...
Аватара пользователя
Alexeus
Вымогатель припоя
Сообщения: 690
Зарегистрирован: Вс мар 04, 2007 01:17:12

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeus »

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

.db 0,4,0,6,0,8,0,0

проверка по нулям в конце не катит- могут стоять и нули во всем массиве.
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение GP1 »

Вопрос:
А зачем это надо?
- если массив определен во флеше то он однозначно имеет постоянный размер
- если массив заполняется в озу, то задается макс размер буфера и должен быть указатель где записан крайний элемент массива, этот указатель и есть текущий размер массива.
Чем дальше, тем больше становлюсь занудой...
Изображение
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6312
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

Alexeus писал(а):Подскажите, есть ли возможность подсчитать количество байт массива?

.db 0,4,0,6,0,8,0,0

проверка по нулям в конце не катит- могут стоять и нули во всем массиве.
Странный вопрос. В массиве столько байт, сколько на него и предусмотришшь при написании. Или это разборка чужой программы?
Учитывая, что это .db, имеется в виду массив констант. От адреса, следующего за массивом элемента отнимаешь адрес начала массива и умножаешь на 2. Но это еще не факт, что будет правильно. Части массива констант тоже могут иметь метки. В общем случае надо анализировать код, где этот ( эти ) массивы исользуются.
Аватара пользователя
Alexeus
Вымогатель припоя
Сообщения: 690
Зарегистрирован: Вс мар 04, 2007 01:17:12

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeus »

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

Код: Выделить всё

mas1:
.db 3,5,2,5,3,5
mas2:
.db 5,6,7,8,9, ... 
И нужно будет определить, брать еще значение по следующему адресу массива, или все, закончились данные.
в общем так не получиться, как я понял, т.к. по окончании одного массива, за ним в памяти может быть следующий.

а если организовывать через структуру

Код: Выделить всё

.dseg mas: .byte 8
, то можно будет в программе определить количество байт, отведенное метке mas?
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение GP1 »

Alexeus писал(а): а если организовывать через структуру

Код: Выделить всё

.dseg mas: .byte 8
, то можно будет в программе определить количество байт, отведенное метке mas?
Только в пределах этих 8 байт (ну или сколько там отведете под массив)
Чем дальше, тем больше становлюсь занудой...
Изображение
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6312
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Jack_A »

Alexeus писал(а): а если организовывать через структуру

Код: Выделить всё

.dseg mas: .byte 8
, то можно будет в программе определить количество байт, отведенное метке mas?
При чем тут структура? Не надо применять термины, имеющие другой общепринятый смысл. Директива .byte только лишь говорит компилятору, чтобы он отвел для этого массива 8 байт, после которых он может размещать следующую переменную. Процессору на этапе выполнения программы об этом неизвестно. Хранить константы в ОЗУ нехорошо, потому что их перед выполнением все равно придется заполнять с помощью программы.
Тут могут быть 2 варианта:
- ограничить массив каким-нибудь значением, которое заведомо не может быть данными ( если 0 не катит, тогда может быть 0xFF ? )
- первым байтом в массиве идет счетчик, показывающий, сколько данных в массиве. Если N данных в массиве перебраны, значит, поиск значения закончился безрезультатно.
А вообще вопрос надуманный. В чем суть проблемы?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение ARV »

Код: Выделить всё

.dseg 
mas:    
          .byte      8
end_mas:

.equ     mas_len = end_mas - mas
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
PersidCat
Родился
Сообщения: 18
Зарегистрирован: Чт дек 02, 2010 06:08:10
Откуда: Россия
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение PersidCat »

Помогите сделать такое:

нужно переслать 10 байт с одного адреса в другой. контроллер atmega16l

я пишу на Си, ассеблера не знаю!
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение GP1 »

PersidCat писал(а):...
я пишу на Си, ассеблера не знаю!
А тема называется "Ассемблер (ASM) для AVR в вопросах и ответах" :)))
Чем дальше, тем больше становлюсь занудой...
Изображение
Аватара пользователя
PersidCat
Родился
Сообщения: 18
Зарегистрирован: Чт дек 02, 2010 06:08:10
Откуда: Россия
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение PersidCat »

подкиньте мне плиз код на асме плиз
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение GP1 »

Код: Выделить всё

.def n=r17
.def tmp=r16

...
ldi ZL,low(buff1)
ldi ZH,high(buff1)
ldi YL,low(buff2)
ldi YH,high(buff2)
;***************************
clr n
next:
       ld tmp,Z+
       st Y+,tmp
       inc n
       cpi n,10
       brne next
....
;***************************
.dseg
buff1: .byte 10
buff2: .byte 10
где-то так, пересылка из buff1 в buff2
Чем дальше, тем больше становлюсь занудой...
Изображение
Ответить

Вернуться в «AVR»