Ассемблер (ASM) для AVR в вопросах и ответах
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Можно же попробовать. Написать пару строк кода в АВР Студио, скомпилировать, погонять и посмотреть результат.
- Реклама
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: Ассемблер (ASM) для AVR в вопросах и ответах
а походу здесь (@0/255)*255 всегда будет 0, если @0 < 255, а если @0=255 тогда единица
- Леонид Иванович
- Друг Кота
- Сообщения: 4779
- Зарегистрирован: Сб апр 02, 2011 12:40:46
- Откуда: Минск
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Операции с константами делаются в целочисленной арифметике. В AVRASM в 32-разрядном виде, а в AVRASM2 - в 64-разрядном. Поэтому чтобы не терять точность, лучше сначала умножать, потом делить.gauss писал(а):После деления на 255 умножаться будет дробь, или целое число, если @0 не кратно 255?
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Что-то я туплю. Как взять модуль отрицательного двухбайтного числа в дополнительном коде? НаписалНо есть сомнения, будет ли это работать вообще и с результатом преобразования DS18B20 в 9-битном разрешении в частности.
Код: Выделить всё
com high;
neg low;[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Код: Выделить всё
sbrs high, 7 ; проверить на отрицательность
rjmp ready ; положительное -> уходим
; отрицательное -> меняем знак:
com high
neg low
sbci high, 0xFF
ready:- Реклама
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Да, действительно без этой команды можно славить глюк (0 вместо -16°С) вне зависимости от разрешения датчикаa_skr писал(а):sbci high, 0xFF
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Доброго дня, коты!
Поиграв с кнопочками и бегающим огоньком, по маршруту a-b-c-d-e-f, перехожу к новой стадии игры.
Хочу написать программу, которая будет при нажатии на кнопку выводить на тройной семисегментный индикатор число, на 1 больше предыдущего. 000 - 001 - 002 ... 193 и т.п. Когда счёт будет доходить до 999, все цифры обнуляются и идём по-новой.
Сейчас думаю над архитектурой программы. Написал вот такой вот алгоритм:
Даём имена 6 регистрам:
темп1,2,3
темп-счётчик1,2,3
присваимваем семисегментный ноль в темп1,2,3, ( 0b00111111)
метка 1!!!
Включаем перывй индикатор 00000001
Выводим темп1 в порт
Включаем второй индикатор 00000010
Выводим темп2 в порт
Включаем третий индикатор 00000100
Выводим темп 3 в порт
Переходтим к 1!!!
Прерывание:
Увеличить Темп-счетчик1 на 1
Проверить, не равен ли темп-счётчик1 10.
Если нет, то метка НЕТ1
Если да, то метка ДА1
НЕТ1
загрузить в темп1 из массива семисегментный код, равный темп-счётчик1.
Выйти из обработчика
ДА1
записать в темп-счетчик1 0, загрузить в темп1 код, равный темп-счётчик1.
Увеличить темп счётчик2 на 1
Проверить, не равен ли темп-счётчик2 10
Если нет, то метка НЕТ2
Если да, то метка ДА2
НЕТ2
загрузить в темп2 из масства семисегментный код, равный темп-счётчик2.
Выйти из обработчика
ДА2
записать в темп-счетчик2 0, загрузить в темп2 код, равный темп-счётчик2.
Увеличить темп счётчик3 на 1
Проверить, не равен ли темп-счётчик3 10
Если нет, то метка НЕТ3
Если да, то метка ДА3
НЕТ3
загрузить в темп3 из масства семисегментный код, равный темп-счётчик3.
Выйти из обработчика
ДА3
Записать в темп-счётчик1,2,3 нули
записать код нулей в темп1,2,3
выйти из обработчика
Прошу посмотреть его, достаточно ли он логичен и короток или что-то лучше сделать по-другому?
Программу по нему тоже хочу написать сегодня
И ещё такой вопрос. Можно ли в обработчике прерываний поставить ссылку на метку, которая находится в теле основной программы?Будет ли снят флаг, сигнализируя, что обработка прерывания завершена? Вроде бы нет...?
В основе лежат статьи о массивах, динамической индикации и оперативной памяти, прочитанные в обучалке сайта.
Поиграв с кнопочками и бегающим огоньком, по маршруту a-b-c-d-e-f, перехожу к новой стадии игры.
Хочу написать программу, которая будет при нажатии на кнопку выводить на тройной семисегментный индикатор число, на 1 больше предыдущего. 000 - 001 - 002 ... 193 и т.п. Когда счёт будет доходить до 999, все цифры обнуляются и идём по-новой.
Сейчас думаю над архитектурой программы. Написал вот такой вот алгоритм:
Спойлер
Настраиваем стек, прерывания и т.п.Даём имена 6 регистрам:
темп1,2,3
темп-счётчик1,2,3
присваимваем семисегментный ноль в темп1,2,3, ( 0b00111111)
метка 1!!!
Включаем перывй индикатор 00000001
Выводим темп1 в порт
Включаем второй индикатор 00000010
Выводим темп2 в порт
Включаем третий индикатор 00000100
Выводим темп 3 в порт
Переходтим к 1!!!
Прерывание:
Увеличить Темп-счетчик1 на 1
Проверить, не равен ли темп-счётчик1 10.
Если нет, то метка НЕТ1
Если да, то метка ДА1
НЕТ1
загрузить в темп1 из массива семисегментный код, равный темп-счётчик1.
Выйти из обработчика
ДА1
записать в темп-счетчик1 0, загрузить в темп1 код, равный темп-счётчик1.
Увеличить темп счётчик2 на 1
Проверить, не равен ли темп-счётчик2 10
Если нет, то метка НЕТ2
Если да, то метка ДА2
НЕТ2
загрузить в темп2 из масства семисегментный код, равный темп-счётчик2.
Выйти из обработчика
ДА2
записать в темп-счетчик2 0, загрузить в темп2 код, равный темп-счётчик2.
Увеличить темп счётчик3 на 1
Проверить, не равен ли темп-счётчик3 10
Если нет, то метка НЕТ3
Если да, то метка ДА3
НЕТ3
загрузить в темп3 из масства семисегментный код, равный темп-счётчик3.
Выйти из обработчика
ДА3
Записать в темп-счётчик1,2,3 нули
записать код нулей в темп1,2,3
выйти из обработчика
Программу по нему тоже хочу написать сегодня
И ещё такой вопрос. Можно ли в обработчике прерываний поставить ссылку на метку, которая находится в теле основной программы?Будет ли снят флаг, сигнализируя, что обработка прерывания завершена? Вроде бы нет...?
В основе лежат статьи о массивах, динамической индикации и оперативной памяти, прочитанные в обучалке сайта.
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
МожноМожно ли в обработчике прерываний поставить ссылку на метку, которая находится в теле основной программы?
Нет. Но можно его снять вручную при необходимости, сбросив флаг I. Только имейте ввиду, что после перехода на прерывание в стек записывается адрес возврата, и не вернувшись, эти два байта так и останутся там висеть (получите утечку памяти). Конечно можно их и вручную убрать, но это уже не написание программы, а сплошные хаки, в которых вы запутаетесь через 10 минут.Будет ли снят флаг, сигнализируя, что обработка прерывания завершена?
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
ploop, спасибо. В данном случае я спрашивал про метку в обработчике, чтобы сэкономить 3 лишних строки кода, думаю, тут ни к чему. А в целом по алгоритму можете что-то сказать?
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Этот подход к программе может и заработает, но он довольно плохой.
Прерывание должно выполнятся как можно быстрее, оно предназначено для дел не требующих отлагательства.
Самый простой способ добится поставленной задачи - сделать программу модульной. В прерывании например, делать только вывод изображения на индикатор и ничего более. Прерывание будет вызвано переполнением таймера - это будет гарантировать что каждый сегмент будет гореть одинаковое время, и перекоса яркости не будет. Вывод осуществляется из 3-х ячеек памяти, по одной на сегмент и в них уже содержится семисегментный код который надо просто вывести в порт и все - поэтому работа эта будет сделана очень быстро.
В основной же программе, инкрементируем счетчик(2 байт), если он больше или равен 1000 - обнуляем, выполняем преобразование bin2BCD(алгоритмов на разную разрядность в сети можно найти по нескольку вариантов) и получаем нужные нам 3 цифры которые преобразуем по таблице <число>-<семисегментное представление> и записываем в эти 3 ячейки, ждем секунду(или какую скорость надо получить) и переходим к началу.
Вся прелесть в том что программа может и не знать как выводятся эти три ячейки. Просто знаем что содержимое ячеек непреенно будет отображено на индикаторе и нас ничего больше не интересует.
С точки зрения обработчика прерывания - существует только три эти ячейки и индикатор и его больше ничего не интересует. При необходимости, алгоритм легко можно масштабировать для больших разрядностей.
Прерывание должно выполнятся как можно быстрее, оно предназначено для дел не требующих отлагательства.
Самый простой способ добится поставленной задачи - сделать программу модульной. В прерывании например, делать только вывод изображения на индикатор и ничего более. Прерывание будет вызвано переполнением таймера - это будет гарантировать что каждый сегмент будет гореть одинаковое время, и перекоса яркости не будет. Вывод осуществляется из 3-х ячеек памяти, по одной на сегмент и в них уже содержится семисегментный код который надо просто вывести в порт и все - поэтому работа эта будет сделана очень быстро.
В основной же программе, инкрементируем счетчик(2 байт), если он больше или равен 1000 - обнуляем, выполняем преобразование bin2BCD(алгоритмов на разную разрядность в сети можно найти по нескольку вариантов) и получаем нужные нам 3 цифры которые преобразуем по таблице <число>-<семисегментное представление> и записываем в эти 3 ячейки, ждем секунду(или какую скорость надо получить) и переходим к началу.
Вся прелесть в том что программа может и не знать как выводятся эти три ячейки. Просто знаем что содержимое ячеек непреенно будет отображено на индикаторе и нас ничего больше не интересует.
С точки зрения обработчика прерывания - существует только три эти ячейки и индикатор и его больше ничего не интересует. При необходимости, алгоритм легко можно масштабировать для больших разрядностей.
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Alexeyslav, спасибо за пояснение! С первого прочтения понял не всё, щас вникну и поищу информацию, но думаю, что на эту тему ещё посоветоваться придётся 
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Привет, господа Коты.
Gudd-Head, я помню про правило 2х сообщений подряд, но как я говорил раньше, сообщение нельзя отредактировать или удалить, поэтому не ругайся.
Спустя пару дней схемотехнических ковыряний и забав с осциллографом, генератором импульсов, оптопар и т.п. возвращаюсь в ассемблер, чтобы сделать нечто простое, для реагирования на схему и подтверждения того, что всё сработало верно (ну, там, диод зажечь\потушить.
Что-то я от темы ушёл. Вопрос сегодня такой: заметил, что если вобработчике прерывания писать cli или вписываться в SREG запрет прерываний - команды не срабатывают. Так и должно быть?
Gudd-Head, я помню про правило 2х сообщений подряд, но как я говорил раньше, сообщение нельзя отредактировать или удалить, поэтому не ругайся.
Спустя пару дней схемотехнических ковыряний и забав с осциллографом, генератором импульсов, оптопар и т.п. возвращаюсь в ассемблер, чтобы сделать нечто простое, для реагирования на схему и подтверждения того, что всё сработало верно (ну, там, диод зажечь\потушить.
Что-то я от темы ушёл. Вопрос сегодня такой: заметил, что если вобработчике прерывания писать cli или вписываться в SREG запрет прерываний - команды не срабатывают. Так и должно быть?
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
А чего нового эти команды должны делать в прерывании? Ведь в обработчике прерывания они и так уже запрещены - перед вызовом обработчика CLI делается аппаратно.
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Упс...
Это я упустил. Я хотел, чтобы в прерывании запретились прерывания. В смысле, чтобы после выхода из этого прерывания, остальные уже не выполнялись, даже если флаги на них поставились во время выполнения первого.
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
а зачем Вам запрет прерываний после выхода из прерывания? Это какая-то конкретная задача или просто учебный пример?
Ставим плюсы: )
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Если надо запретить прерывания выходя из обработчика прерывания - используй команду RET вместо RETI, она не трогает флаг разрешения прерываний а в остальном её действие аналогичное.
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
ibiza11, привет! Если честно, я уже не помню что я делал, но это был учебный пример! 
Alexeyslav, спасибо, мне кажется, прием правда ценный
Сейчас у меня скорее не вопрос, а убедиться хочу
Смотрите, происходит прерывание. Мы переходим по метке INT. В процессе обработки прерывания мы перескакиваем куда-то по команде RJMP. И далее, после выполнения каких-то, действий выполняется команда RETI. После этого все будет в порядке? Я имею ввиду, что флаг в GIFR будет сброшен как надо и с указателем стека ничего не произойдет, тк команда RJMP ничего в память не заносит. Как RCALL например
Правильно?
Я это спрашиваю, тк щас начну писать свою версию динамической индикации трехзначного числа и в любом случае буду допускать ошибки. И сразу хочу убедиться, что ошибки не будут связаны с выполнением вышенаписанных команд
И еще сразу тут же уточню. Если вызвано какое-то прерывание, то на него установлен флаг. Флаг снимется, когда выполнится команда RETI. До этого момента повторные события, вызывающие это прерывание, например нажатие кнопки, ничего не сделают, потому что флаг навыполнение прерывания уже стоит и в очередь они не набираются.
UPD я написал сейчас программку, которая делает следующее:
Выводит на индикацию семисегментный код, который взят из массива.
При прерывании происходит увеличение на 1 адреса масива, из которого берется семисегментный код.
Естесственно, я забыл написать указания, которые после 9 будут обнулять увеличивающуюся цифру.
И при последующих прерываниях на индикацию выводятся хаотичные символы)
Как я понял, в памяти, сразу за матрицей, лежат другие числа. И их и выводит на индикацию моя программа?
Alexeyslav, спасибо, мне кажется, прием правда ценный
Сейчас у меня скорее не вопрос, а убедиться хочу
Смотрите, происходит прерывание. Мы переходим по метке INT. В процессе обработки прерывания мы перескакиваем куда-то по команде RJMP. И далее, после выполнения каких-то, действий выполняется команда RETI. После этого все будет в порядке? Я имею ввиду, что флаг в GIFR будет сброшен как надо и с указателем стека ничего не произойдет, тк команда RJMP ничего в память не заносит. Как RCALL например
Я это спрашиваю, тк щас начну писать свою версию динамической индикации трехзначного числа и в любом случае буду допускать ошибки. И сразу хочу убедиться, что ошибки не будут связаны с выполнением вышенаписанных команд
И еще сразу тут же уточню. Если вызвано какое-то прерывание, то на него установлен флаг. Флаг снимется, когда выполнится команда RETI. До этого момента повторные события, вызывающие это прерывание, например нажатие кнопки, ничего не сделают, потому что флаг навыполнение прерывания уже стоит и в очередь они не набираются.
UPD я написал сейчас программку, которая делает следующее:
Выводит на индикацию семисегментный код, который взят из массива.
При прерывании происходит увеличение на 1 адреса масива, из которого берется семисегментный код.
Естесственно, я забыл написать указания, которые после 9 будут обнулять увеличивающуюся цифру.
И при последующих прерываниях на индикацию выводятся хаотичные символы)
Как я понял, в памяти, сразу за матрицей, лежат другие числа. И их и выводит на индикацию моя программа?
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
1) Правильно, команда rjmp может использоваться повсеместно, включая и обработчик прерывания, главное, чтобы при выходе из обработчика была выполнена команда ret/reti. Только она освобождает стек от помещенного туда адреса возврата.
Надеюсь понятно объяснил.
2) Здесь неправильно. Есть флаг I - глобальное разрешение прерываний. Он снимается при входе в прерывание и выставляется при выполнении reti в конце обработчика. Еще есть флаг конкретного прерывания (это не флаг I). Флаг соответствующего прерывания выставляется при возникновении события прерывания(например переполнение счетчика таймера), если при этом выставлен флаг I, тогда программа переходит на обработчик прерывания и в стек помещается адрес возврата. Флаг соответствующего прерывания в AVR сбрасывается при входе в прерывание и если во время выполнения прерывания опять произойдет то же самое событие, то флаг соответствующего прерывания опять выставится. Но поскольку во время прерывания флаг I сброшен, то и повторного перехода на этот же обработчик прерывания не происходит. Переход произойдет только после выставления флага I, а это в свою очередь произойдет при выходе из прерывания. (Если конечно в обработчике не поставить команду sei).Mika писал(а):Если вызвано какое-то прерывание, то на него установлен флаг. Флаг снимется, когда выполнится команда RETI.
Надеюсь понятно объяснил.
3) Матрица, я полагаю, у Вас лежит в программной памяти микроконтроллера (Flash), а она для команды ld lpm (корр. Alexeyslav) (или какой Вы там пользуетесь для доступа к памяти?) едина. Естественно в программной памяти кроме Вашего массива данных еще есть код, который выполняется контроллером (коды команд). Вот эти коды читаются и выводятся на Ваш индикатор.Мikа писал(а):Как я понял, в памяти, сразу за матрицей, лежат другие числа. И их и выводит на индикацию моя программа?
Последний раз редактировалось ibiza11 Пн апр 29, 2013 08:58:27, всего редактировалось 1 раз.
Ставим плюсы: )
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
FLASH командой LD не читается, LD имеет доступ только к регистрам, портам ввода-вывода и RAM в едином адресном пространстве. общение с EEPROM - через порт ввода-вывода, с FLASH - через команды SPM/LPM.
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
согласен, перепутал.
давно не пишу на ассемблере, да и для AVR давно не писал. Пост поправил.
давно не пишу на ассемблере, да и для AVR давно не писал. Пост поправил.
Ставим плюсы: )


