Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AVR204
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
ILYAUL
Всем привет!

Месяца два назад звонил знакомый с вопросом по этому произведению фирмы Atmel. Тогда я не придал этому значения- просто дал рабочий код , но мыслишка осталась.
Разбирая по папкам данные на компе- порядок наводил, наткнулся на AVR204 и решил взглянуть поближе на сей код.
И хотя в описании алгоритма работы есть строчки: Add $03 to result byte2 и т.д. в коде я этого не вижу. Регистр tmp16a (судя по коду) всегда содержит 0 или я что-то не понял

Весь код:

Код
;***************************************************************************
;*
;* "bin2BCD16" - 16-bit Binary to BCD conversion
;*
;* This subroutine converts a 16-bit number (fbinH:fbinL) to a 5-digit
;* packed BCD number represented by 3 bytes (tBCD2:tBCD1:tBCD0).
;* MSD of the 5-digit number is placed in the lowermost nibble of tBCD2.
;*
;* Number of words    :25
;* Number of cycles    :751/768 (Min/Max)
;* Low registers used    :3 (tBCD0,tBCD1,tBCD2)
;* High registers used  :4(fbinL,fbinH,cnt16a,tmp16a)    
;* Pointers used    :Z
;*
;***************************************************************************

;***** Subroutine Register Variables

.equ    AtBCD0    =13;address of tBCD0
.equ    AtBCD2    =15;address of tBCD1

.def    tBCD0    =r13;BCD value digits 1 and 0
.def    tBCD1    =r14;BCD value digits 3 and 2
.def    tBCD2    =r15;BCD value digit 4
.def    fbinL    =r16;binary value Low byte
.def    fbinH    =r17;binary value High byte
.def    cnt16a    =r18;loop counter
.def    tmp16a    =r19;temporary value

;***** Code

bin2BCD16:
    ldi    cnt16a,16                  ;Init loop counter    
    clr    tBCD2;clear result (3 bytes)
    clr    tBCD1        
    clr    tBCD0        
    clr    ZH;clear ZH (not needed for AT90Sxx0x)
bBCDx_1:lsl    fbinL;shift input value
    rol    fbinH;through all bytes
    rol    tBCD0;
    rol    tBCD1
    rol    tBCD2
    dec    cnt16a;decrement loop counter
    brne    bBCDx_2;if counter not zero
    ret    ;   return

bBCDx_2:ldi    r30,AtBCD2+1;Z points to result MSB + 1
bBCDx_3:
    ld    tmp16a,-Z                  ;get (Z) with pre-decrement
;----------------------------------------------------------------
;For AT90Sxx0x, substitute the above line with:
;
;    dec    ZL
;    ld    tmp16a,Z
;
;----------------------------------------------------------------
    subi    tmp16a,-$03;add 0x03
    sbrc    tmp16a,3                  ;if bit 3 not clear
    st    Z,tmp16a;store back
    ld    tmp16a,Z                  ;get (Z)
    subi    tmp16a,-$30;add 0x30
    sbrc    tmp16a,7                  ;if bit 7 not clear
    st    Z,tmp16a                ;store back
    cpi    ZL,AtBCD0                  ;done all three?
    brne    bBCDx_3;loop again if not
    rjmp    bBCDx_1
Sergey_Aleksandrovi4
Десятая команда снизу subi tmp16a,-$03;add 0x03

В AVR нет встроенной инструкции "Сложение РОН с константой", поэтому используют "Вычитание константы из РОН" - вычитают из регистра константу с противоположным знаком, что эквивалентно сложению.
По поводу данной аппноты не скажу, а вот по умножению/делению 16 битных чисел со знаком и без в своё время повторял, работало без нареканий. Так что сомнения в работоспособности приведённого кода излишние.
ILYAUL
Цитата(Sergey_Aleksandrovi4 @ Apr 20 2011, 14:09) *
Десятая команда снизу subi tmp16a,-$03;add 0x03

В AVR нет встроенной инструкции "Сложение РОН с константой", поэтому используют "Вычитание константы из РОН" - вычитают из регистра константу с противоположным знаком, что эквивалентно сложению.
По поводу данной аппноты не скажу, а вот по умножению/делению 16 битных чисел со знаком и без в своё время повторял, работало без нареканий. Так что сомнения в работоспособности приведённого кода излишние.

Вы , несколько заблуждаетесь по поводу subi tmp16a,-$03 . Регистр tmp16a описан в def как временный регистр - в который должны передоваться последовательно данные из tBCD0 - tBCD3 и производится необходимые действия . Весь вопрос и состоит в том , что в этот регистр данные из tBCD0 - tBCD3 , согласно приведённому коду НИКОГДА не попадут. А то что нет прямого сложения- известный факт
rx3apf
Цитата(ILYAUL @ Apr 20 2011, 15:56) *
Весь вопрос и состоит в том , что в этот регистр данные из tBCD0 - tBCD3 , согласно приведённому коду НИКОГДА не попадут.

Как так ? А это что:
CODE
bBCDx_3:
ld tmp16a,-Z ;get (Z) with pre-decrement

???
ILYAUL
Цитата(rx3apf @ Apr 20 2011, 16:04) *
Как так ? А это что:
CODE
bBCDx_3:
ld tmp16a,-Z ;get (Z) with pre-decrement

???

Я уверен , что Вы сами ответите на свой вопрос . Я ради интереса проиммулировал его. Два абсолютно независимых от друг друга кода в одном аппноуте. Могу добавить по всему коду свои комменты , но что бы не сбивать независимую оценку пока этого не сделал .
rx3apf
Цитата(ILYAUL @ Apr 20 2011, 16:11) *
Я уверен , что Вы сами ответите на свой вопрос . Я ради интереса проиммулировал его. Два абсолютно независимых от друг друга кода

Какие-такие "два независимых кода" ? tmp16a загружается из RAM по адресу, определяемому Z, с предекрементом. Z адресует аккумулятор BCD. Все в точности как задумано.
ILYAUL
Цитата(rx3apf @ Apr 20 2011, 16:16) *
Какие-такие "два независимых кода" ? tmp16a загружается из RAM по адресу, определяемому Z, с предекрементом. Z адресует аккумулятор BCD. Все в точности как задумано.

Ладно хорошо начнём:
Код
;***************************************************************************
;*
;* "bin2BCD16" - 16-bit Binary to BCD conversion
;*
;* This subroutine converts a 16-bit number (fbinH:fbinL) to a 5-digit
;* packed BCD number represented by 3 bytes (tBCD2:tBCD1:tBCD0).
;* MSD of the 5-digit number is placed in the lowermost nibble of tBCD2.
;*
;* Number of words    :25
;* Number of cycles    :751/768 (Min/Max)
;* Low registers used    :3 (tBCD0,tBCD1,tBCD2)
;* High registers used  :4(fbinL,fbinH,cnt16a,tmp16a)    
;* Pointers used    :Z
;*
;***************************************************************************

;***** Subroutine Register Variables

.equ    AtBCD0    =13;address of tBCD0    Какой нах адрес - простой счётчик
.equ    AtBCD2    =15;address of tBCD1   В дальнейшем used  ZL
[sub]Это не комментируется - стандарт[/sub]
.def    tBCD0    =r13;BCD value digits 1 and 0
.def    tBCD1    =r14;BCD value digits 3 and 2
.def    tBCD2    =r15;BCD value digit 4
.def    fbinL    =r16;binary value Low byte
.def    fbinH    =r17;binary value High byte
.def    cnt16a    =r18;loop counter
.def    tmp16a    =r19;temporary value

;***** Code

bin2BCD16:
    ldi    cnt16a,16                 ;Init loop counter    Присваиваем 0x10 счётчику
    clr    tBCD2;clear result (3 bytes)
    clr    tBCD1        
    clr    tBCD0        
    clr    ZH;clear ZH (not needed for AT90Sxx0x) Я даже не вспомню у когого AVR- SRAM ( свободная от всех дополнительных регистров начнётся с 0)
При эммуляциии вместо этого сделал  так
Ldi ZH,high(0x200)

bBCDx_1:
    lsl    fbinL;shift input value
    rol    fbinH;through all bytes
    rol    tBCD0;
    rol    tBCD1
    rol    tBCD2
    dec    cnt16a;decrement loop counter
    brne    bBCDx_2;if counter not zero                                      Вот отсюда всё и начинается
Как мы помним -счётчик 16 , естественно он не равен Zero поэтому , дружно , xxxeм на bBCDx_2:
    ret   ;   return

bBCDx_2:ldi    r30,AtBCD2+1;Z points to result MSB + 1 ,-

где в ZL ( мы же помним что R30 = ZL) пишем 0x0F+1 = 0x10
В итоге получаем адрес 0x10 (аппноут) , ну в моём случае 0x210
И что же мы имеем по этим адресам - да не XXXя не имеем , хорошо , что у меня макрос память чистит всю, во момент включения , так , что я 00
Так , что мы загрузим tmp16A? 0x00

И с этого момента программа делится на два , абсолютно независимых куска , где то что-то там сдвигается , где то к 0 прибавляется 3 или 0x30
И всё это красиво и не зависимо крутится

bBCDx_3:
    ld    tmp16a,-Z                 ;get (Z) with pre-decrement
;----------------------------------------------------------------
;For AT90Sxx0x, substitute the above line with:
;
;    dec    ZL
;    ld    tmp16a,Z
;
;----------------------------------------------------------------
    subi    tmp16a,-$03;add 0x03
    sbrc    tmp16a,3                 ;if bit 3 not clear
    st    Z,tmp16a;store back
    ld    tmp16a,Z                 ;get (Z)
    subi    tmp16a,-$30;add 0x30
    sbrc    tmp16a,7                 ;if bit 7 not clear
    st    Z,tmp16a               ;store back
    cpi    ZL,AtBCD0                 ;done all three?
    brne    bBCDx_3;loop again if not
    rjmp    bBCDx_1
aaarrr
Цитата(ILYAUL @ Apr 20 2011, 16:54) *
Ладно хорошо начнём:

Вам знакомо понятие предекремента?
rx3apf
Цитата(ILYAUL @ Apr 20 2011, 16:54) *
Ладно хорошо начнём:
......
.equ AtBCD0 =13;address of tBCD0 Какой нах адрес - простой счётчик
...

В итоге получаем адрес 0x10 (аппноут) , ну в моём случае 0x210
И что же мы имеем по этим адресам - да не XXXя не имеем , хорошо , что у меня макрос память чистит всю, во
...

Собственно, на этом можно и закончить. Учите архитектуру AVR, и особое внимание обратите на распределение адресного пространства. Аппликуха корявая, да. И AVRASM корявый, да. Но все работоспособно (если чуть-чуть подумать).

Цитата(aaarrr @ Apr 20 2011, 17:00) *
Вам знакомо понятие предекремента?

Тут все еще хуже...
ILYAUL
Цитата(aaarrr @ Apr 20 2011, 17:00) *
Вам знакомо понятие предекремента?

Вы что считаете , что я не могу посчитать 15+1 и что такое преддекремент мне известно. Посмотрите присвоение equ AtBCD2 Мы говорим о том , что ATMEL с этим аппноутом накосячил.

Цитата(rx3apf @ Apr 20 2011, 17:02) *
Собственно, на этом можно и закончить. Учите архитектуру AVR, и особое внимание обратите на распределение адресного пространства. Аппликуха корявая, да. И AVRASM корявый, да. Но все работоспособно (если чуть-чуть подумать).


Тут все еще хуже...

Уже подумал и исправил, дома лежит рабочий вариант- приду выгружу. Хотя как Вы видите из начала темы , я использую другой алгоритм
aaarrr
Цитата(ILYAUL @ Apr 20 2011, 17:25) *
Вы что считаете , что я не могу посчитать 15+1 и что такое преддекремент мне известно. Посмотрите присвоение equ AtBCD2 Мы говорим о том , что ATMEL с этим аппноутом накосячил.

Ничего не накосячил: 15 - это адрес регистра r15 (tBCD2).
rx3apf
Цитата(ILYAUL @ Apr 20 2011, 17:25) *
Вы что считаете , что я не могу посчитать 15+1 и что такое преддекремент мне известно. Посмотрите присвоение equ AtBCD2 Мы говорим о том , что ATMEL с этим аппноутом накосячил.

Нисколько. Странное на первый взгляд присвоение - это из-за кривизны самого AVRASM. Логика же программы совершенно правильная.
ILYAUL
Цитата(aaarrr @ Apr 20 2011, 17:32) *
Ничего не накосячил: 15 - это адрес регистра r15 (tBCD2).

.def tBCD2 =r15;BCD value digit 4
а это тогда что?
И с каких пор , назначение абстрактной переменной привязано к регистру .equ AtBCD2 =15 , а если я напишу .equ AtBCD2=24 - это что 24 регистр,
rx3apf
Цитата(ILYAUL @ Apr 20 2011, 17:37) *
.def tBCD2 =r15;BCD value digit 4
а это тогда что?

А это сам регистр, в котором набирается BCD. Просто нельзя записать ldi ZL,low(r15), приходится вот так изгаляться...
Цитата
И с каких пор , назначение абстрактной переменной привязано к регистру .equ AtBCD2 =15 , а если я напишу .equ AtBCD2=24 - это что 24 регистр,

Да прочитайте, в конце концов, даташит на любой кристалл, там, где описывается распределение адресного пространства, и не позорьтесь.
ILYAUL
Цитата(rx3apf @ Apr 20 2011, 17:34) *
Нисколько. Странное на первый взгляд присвоение - это из-за кривизны самого AVRASM. Логика же программы совершенно правильная.

Простите какая ,тут логика и причём здесь AVRASM , если в temp регистр не передаётся число , он проходит весь цикл и проверяет BCD0-BCD3 а в Sram по этим адресам 00, после сдвига нет записи в sram- откуда темпу данные брать?!
rx3apf
Цитата(ILYAUL @ Apr 20 2011, 17:43) *
Простите какая ,тут логика и причём здесь AVRASM , если в temp регистр не передаётся число , он проходит весь цикл и проверяет BCD0-BCD3 а в Sram по этим адресам 00, после сдвига нет записи в sram- откуда темпу данные брать?!

Еще раз - где Вы тут увидели доступ к SRAM ? В своем примере, адресуя 210 hex ? Ну, тогда извините, сами и виноваты. А если в примере от Atmel - все правильно. Я не знаю, сколько раз Вам нужно повторить, чтобы Вы прочитали даташит ?
aaarrr
Цитата(ILYAUL @ Apr 20 2011, 17:43) *
Простите какая ,тут логика и причём здесь AVRASM , если в temp регистр не передаётся число , он проходит весь цикл и проверяет BCD0-BCD3 а в Sram по этим адресам 00, после сдвига нет записи в sram- откуда темпу данные брать?!

Прочитайте наконец в даташите, что находится в адресах 0-31. Тогда и вопросы отпадут.
ILYAUL
Цитата(rx3apf @ Apr 20 2011, 17:40) *
А это сам регистр, в котором набирается BCD. Просто нельзя записать ldi ZL,low(r15), приходится вот так изгаляться...


Это значит , что бы вмечто того , что бы писать R15 я могу написать ldi tBCD2,12 и asm присвоит R15 значение 0x0C

Цитата(rx3apf @ Apr 20 2011, 17:40) *
Да прочитайте, в конце концов, даташит на любой кристалл, там, где описывается распределение адресного пространства, и не позорьтесь.

И причём здесь адресное пространство?
.equ Поясните мне , как это влияет на адресное пространство и каким боком сдандартнное присвоение абстрактному имени в AVRASM когого-то значения влияет на адресное пространство
rx3apf
Цитата(ILYAUL @ Apr 20 2011, 17:53) *
Это значит , что бы вмечто того , что бы писать R15 я могу написать ldi tBCD2,12 и asm присвоит R15 значение 0x0C

Да ну ?

Цитата
И причём здесь адресное пространство?
Поясните мне , как это влияет на адресное пространство и каким боком сдандартнное присвоение абстрактному имени в AVRASM когого-то значения влияет на адресное пространство

Лично я уже устал объяснять очевидные вещи. Запасаюсь попкорном и буду молча смотреть на эту клоунаду. И все же намекну в последний раз - пример от Atmel совершенно корректен, работает так, как задумывалось. Вне зависимости от Ваших представлений...
ILYAUL
Цитата(aaarrr @ Apr 20 2011, 17:47) *
Прочитайте наконец в даташите, что находится в адресах 0-31. Тогда и вопросы отпадут.

да, кажется понял. С толку сбило ld
Извините!
ae_
Цитата(ILYAUL @ Apr 20 2011, 22:53) *
И причём здесь адресное пространство?

Код
LDI ZL,5
LDI ZH,0
LD R16,Z

Этот код делает тоже самое, что и MOV R16,R5
РОН тоже входят в адресное пространство и к ним можно обращаться косвенной адресацией через индексные регистры.
ILYAUL
Коллеги!

Только не бейте сильно , я совсем забыл о таком способе адресации к регистрам. Вылетело из головы.
КАЮСЬ! КАЮСЬ и ещё раз КАЮСЬ!!!!! Ну извитете!!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.