Страница 5 из 7
Re: Научите писать под AVR
Добавлено: Сб сен 06, 2014 10:59:21
СКАЗОЧНИК
Уф... видимо, не умею я вопросы задавать...
Вот у меня два байта, в них записано число. Я вычитаю из младшего байта константу. В какой-то момент система понимает, что младший байт исчерпан и надо занимать уже у старшего байта. Все через флаг переноса.
Так вот, как работают эти два оператора??? Когда он понимает, что пора занимать? и Как он понимает, что занимать надо именно у того???
Для чайника....
Можно где почитать с картинками? Где разряды нарисованы???? А то я уже всякую арифметику двоичную смотрю...
Вот пример... есть temp, в нем младший байт числа и есть temp1, в котором старший байт.
Дальше
subi temp, 120 ; Здесь из младшего байта вычли 120. А если в младшем байте всего было предположим число 35... Значит надо искать остатки в старшем байте...
Откуда берется флаг переноса???
Re: Научите писать под AVR
Добавлено: Сб сен 06, 2014 11:18:55
Jack_A
Код: Выделить всё
div120: ldi r24,0
ldi r25,0
d5: subi r16,120
sbci r17,0
brcs d_fin
adiw r24,1
rjmp d5
d_fin: ret
Как-то так . В R16,R17 - делимое, в R24,R25 - результат (мл. - ст. ) . Не самый быстрый способ. Например, для 65535 занимает свыше 3800 машинных тактов.
Бит переноса С устанавливается, если при вычитании 7-й бит числа, из которого вычитают, меняется из 0 в 1.
C: Rd7 ·K7+ K7 · R7 +R7 ·Rd7
Set if the absolute value of the constant plus previous carry is larger than the absolute value of Rd; cleared otherwise.
Re: Научите писать под AVR
Добавлено: Сб сен 06, 2014 11:41:22
СКАЗОЧНИК
Тааааак... Вот что до меня начало доходить...
оператор subi вычитает из регистра константу и если регистр был меньше константы в любом случае появляется флаг переноса (С).
и оператор sbci вычитает из старшего регистра 0 и флаг переноса. Т.е., если флага не было, то ничего и не вычитает. А если флаг был от предыдущего оператора, то вычитает его.
Правильно?
А как тогда следующее вычитание сработает опять из того же младшего константы? Уже некорректно. Т.к. флаг переноса забрал единицу у старшего, но не распределил ее по младшему....
В чем смысл следующих двух операторов?
Re: Научите писать под AVR
Добавлено: Сб сен 06, 2014 11:52:03
Jack_A
СКАЗОЧНИК писал(а):
оператор sbci вычитает из старшего регистра 0 и флаг переноса.
Не совсем. Вычитает не обязательно 0, а столько, сколько ему заказано. SBCI R16,7 например. В нашем примере 0, потому что делитель однобайтовый. При следующем вычитании из младшего байта ничего страшного не случится, т.к. там не SBCI , а SUBI, и он предыдущий флаг игнорирует.
А дальше : если С установлен при SBCI старшего байта, то хана, делимое исчерпано и бегом на выход, а если нет - длинное (2-байтовое) прибавление 1 и на повтор цикла. Потому и выбраны R24,R25, что только эта пара ( не считая X,Y и Z ) допускает операцию с переносом в старший байт.
Рекомендую освоить какую-нить Астудию, в ней при пошаговой симуляции очень четко видно, что кто у кого забирает и что где устанавливает. Студия - лучший учитель, I think .
Re: Научите писать под AVR
Добавлено: Сб сен 06, 2014 12:05:17
СКАЗОЧНИК
Jack_A писал(а):В нашем примере 0, потому что делитель однобайтовый.
Вот эта фраза меня ввела в ступор... ( Я понял так, что из старшего байта надо вычитать только флаг переноса, поэтому и в команде написан 0... т.к. ничего больше не требуется.
Jack_A писал(а):При следующем вычитании из младшего байта ничего страшного не случится
Как же не случится? А где же занимаемая у старшего единица будет? Она же должна добавится в младший????
Jack_A писал(а):то хана, делимое исчерпано и бегом на выход,
Jack_A писал(а):прибавление 1 и на повтор цикла.
А вот это дошло. ))) Когда невозможно больше отнимать, тогда выход, а двухбайтовое прибавление можно заменить однобайтовым - это и будет результат без остатка.
Jack_A писал(а):Рекомендую освоить какую-нить Астудию
А вот чтобы в студии проверить, думаю, надо понять сначала что туда написать, чтобы это проверить. )))) Не будешь же абракадабру всякую эмулировать. ))))
А за помощь в любом случае спасибо!!!
З.З.Ы. Я короче, сделал так:
Код: Выделить всё
INT_0:
PUSHF
clr temp3
cli
in temp, TCNT1L
in temp1, TCNT1H
T: subi temp, 120
sbci temp1, 0
brcs FIN
inc temp3
rjmp T
FIN:
sei
POPF
ldi temp, 0x00 ; Обнуляем счетчик
out TCNT1H, temp
out TCNT1L, temp
reti
Просто, у меня не будет в частном двухбайтовых значений, т.к. до переполнения таймер не досчитает (он с запасом получился пятикратным...)
Однако вопрос про то, как перенос преобразует младший байт остается...
Re: Научите писать под AVR
Добавлено: Сб сен 06, 2014 14:52:30
Jack_A
СКАЗОЧНИК писал(а):
Как же не случится? А где же занимаемая у старшего единица будет? Она же должна добавится в младший????
Мы занимаем единицу не у старшего байта, а из флага С. В результате если вычитаемое будет больше уменьшаемого, взводится бит С, и фактически тогда будем вычитать не А - В , а ( А + 256 ) - В. Взведенный бит С в последующей команде SBCI Rx,0 как раз и вычитается из старшего байта.
З.З.Ы. Я короче, сделал так:
А вот так делать нельзя ! Длинные вычисления в прерывании - никогда не используйте ! В прерывании устанавливается флаг, в главном цикле посматриваем на этот флаг, и когда он установлен, производим какие-то телодвижения и сбрасывается флаг. Приблизно так :
Код: Выделить всё
; в прерывании :
inc FLAG
; в главной :
tst FLAG
breq bypass
call convers
sub FLAG,FLAG
bypass:
Само сабой разумеется, время выполнения преобразующей подпрограммы должно быть меньше, чем интервал срабатывания прерывания таймера, иначе получится каша : не успели обработать одно, а уже следующий самосвал разгружается
Похоже, конструируются часы

Так зачем каждый раз проводить преобразование ? Только при изменении показаний, выводимых на индикатор .
Re: Научите писать под AVR
Добавлено: Сб сен 06, 2014 15:16:57
СКАЗОЧНИК
Jack_A писал(а):Похоже, конструируются часы
Ага, типа того.
Jack_A писал(а):Длинные вычисления в прерывании
Я просто посчитал, что такое вычисление у меня успеет уложится в необходимый (возможный) интервал времени. Т.к. частота 20 МГц у МК, а частота вращения планки со светодиодами около 2000 оборотов/мин. То получается по моим вычислениям примерно от 20 до 40 миллисекунд на оборот (от скорости вращения зависит), замеряем постоянно, от прерывания до прерывания. Делим на 120 секторов, получается по 250 микросекунд на сектор (тоже примерно). За это время прохождения одного сектора в 3 градуса МК успевает выполнить около 5000 команд при такой частоте. Т.е. в прерывании должен успеть посчитать деление.
А дальше этот результат используем, во втором таймере, который формирует интервалы зажигания светодиодов на секторах... Как-то так.
Re: Научите писать под AVR
Добавлено: Сб сен 06, 2014 16:55:13
Jack_A
В данном конкретном случае может быть, но лучше приучить себя так не делать. Кстати, не все команды выполняются за один так, так что может быть впритык.
Re: Научите писать под AVR
Добавлено: Пн сен 15, 2014 13:57:35
СКАЗОЧНИК
Прошу прощения. Возник еще один вопрос...
А можно ли так написать?
ldi temp, (0<<5)
Задвинет ли эта команда ноль на пять позиций влево?
И можно ли писать так?
ldi temp, (1<<1)
ldi temp, (1<<5)
Не затрет ли мне первую единицу???
Re: Научите писать под AVR
Добавлено: Пн сен 15, 2014 14:00:08
Gudd-Head
СКАЗОЧНИК писал(а):Не затрет ли мне первую единицу???
А скопировать код в студию и запустить пошаговую отладку чтобы посмотреть?
Re: Научите писать под AVR
Добавлено: Пн сен 15, 2014 14:17:08
СКАЗОЧНИК
Блин...
Первая вообще байт в ноль сбрасывает...
А вторая затирает... (((( Я расстроен..
З.Ы. посмотрел в отладке в АВРстудио...
Re: Научите писать под AVR
Добавлено: Пн сен 15, 2014 14:21:46
Gudd-Head
Не расстраивайтесь
ldi temp, (1<<1)|(1<<5)
Re: Научите писать под AVR
Добавлено: Пн сен 15, 2014 14:22:38
СКАЗОЧНИК
Тогда ткните носом, куда почитать про это??? Просто мне надо в одном месте менять на нули, а в другом задвигать единицы в разные позиции, чтобы старые не портились... Т.е. накладывать маски... В Си было это, а в ассемблере не знаю..
З.Ы. есть одно НО...
Мне не нужно за один раз установить единицы... ((( Мне нужно в одной команде поставить одну единицу в нужный разряд, а в следующей, если условие выполнилось, добавить еще одну единицу в другой разряд, и так. далее.. Тоже самое с нулем... При этом байт который был уже исправлен, должен остаться таким, просто к нему добавляются нули или единицы...
Re: Научите писать под AVR
Добавлено: Пн сен 15, 2014 14:31:34
Gudd-Head
Установить нули можно предварительно загрузив единицы и проинвертировав: ldi temp, ~(1<<1)|(1<<5)
Если нужно установить или сбросить какой-то конкретный бит, пользуйтесь логическими сложением и умножением соответственно.
В приложении с 13-й страницы почитайте.
Re: Научите писать под AVR
Добавлено: Пн сен 15, 2014 14:43:13
Engineer_Keen
Есть еще удобные команды SBR/CBR, которые на самом деле замаскированные ORI/ANDI, т.е. это как раз и есть наложение масок.
Сбросить например младшие 2 бита можно так
поставить в 1 так
Остальные биты естественно сохраняются как были...
Re: Научите писать под AVR
Добавлено: Пн сен 15, 2014 18:56:14
СКАЗОЧНИК
Спасибо, друзья! ))) То, ЧТО надо!!!
Re: Научите писать под AVR
Добавлено: Вс окт 12, 2014 17:24:38
СКАЗОЧНИК
Прошу прощения, ребят... у меня очередной вопрос.
Хочу организовать большую переменную 32 бита, т.е. 4 байта.. Желательно в оперативке, потому что буду ее заполнять с одного конца нулями и единицами методом сдвига. Надо чтобы автоматом сдвигалось дальше в следующий байт. Как это сделать?
Но это еще не все. Потом эту переменную надо сравнить с ранее записанной во Флеш (кстати, во флеш можно сразу записать одну переменную в 32 бита?). Так вот, как сравнить две большие переменные?
З.Ы. либо разбить все это на 4 байта и сравнивать по отдельности, но тоже как? Как заполнить 4 отдельных байта нулями и единицами последовательно сдвигая в следующий байт?
Все, спасибо, не надо. Я вроде, сам понял.... Извините...
Re: Научите писать под AVR
Добавлено: Пн окт 13, 2014 09:28:26
Gudd-Head
Во флэш можно залить что угодно.
Сравнивать большие переменные побайтно.
Сдвиг сквозь байты проще всего через перенос.
Re: Научите писать под AVR
Добавлено: Пн окт 13, 2014 09:43:03
mail_robot
блин, как здорово что для нормальных программистов придумали С++

Re: Научите писать под AVR
Добавлено: Пн окт 13, 2014 14:27:31
СКАЗОЧНИК
mail_robot писал(а):как здорово что для нормальных программистов придумали С++
Для Тини13 писать на С++, все равно, что на самолете парковаться около дома... Да и не дает он понимания работ контроллера. Реально на ассемблере фундамент лучше закладывается. Для будущих проектов на больших МК, можно и на С переехать, однако уже понимая, что и где он как сделает...
Gudd-Head писал(а):Сдвиг сквозь байты проще всего через перенос.
Спасибо, вот это уже и сообразил. Зря вопрос задал. Все оказывается проще, чем можно себе представить. Просто голова иногда совсем отключается.
Зато есть другой вопрос. )
Флаг регистра SREG Z - устанавливается, в команде cpi, когда точно равно? Или когда равно или больше? Просто мне надо одним условием определить точно ли переменная равна заданному числу... Подразумеваю, что синонимы команд должны быть точны - (breq метка) и (brbs SREG_Z, метка).