Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Работа с байтами многобайтовой переменной


Работа с байтами многобайтовой переменной

Сообщений 1 страница 30 из 31

1

Есть оператор, который может разложить на старший  и младший байт.

HIGH() Возвращает старший байт двухбайтной переменной
HIGHW() Выделить старшие два байта четырехбайтовой переменной
LOW() Возвращает младший байт двухбайтной переменной
LOWW() Выделить младшие два байта четырехбайтовой переменной


А как обратно то их запихнуть?

У меня есть массив с байтами, из него бы запихнуть в Single
То-есть как-то так:
Dim S As Single
Dim D(4) As Byte

S=D(все биты)
Или проще:
S=D(4)
S=S*D(3)
S=S*D(2)
S=S*D(1)
Но тут отрицательное/положительное и ещё чего-то надо, был у кого опыт составления многобайтовой переменной из однобайтовых?

+1

2

Можно сделать так

Код:
Dim S As Single
Dim D(4) As Byte At S Overlay

Но результат будет совсем не тот что ожидается. Переменная типа Single с плавающей точкой и просто так байты туда записать нельзя.

0

3

А если Integer - тут какой-то крайний бит (наверно первый) отвечает за отрицательное и положительное.
Наверно проще через циклы по битам приравнять, но почему-то уверен, что можно изменять как-то отдельный байт в многобайтной переменной.

0

4

Знак - да, обычно крайний бит отвечает за знак.
С синглом не знаю, каждый изобретает свой формат точности. :) надо конкретно разбирать

0

5

RDW написал(а):

Знак - да, обычно крайний бит отвечает за знак.С синглом не знаю, каждый изобретает свой формат точности.  надо конкретно разбирать

А "туда-сюда" при помощи текстовых функций ?
Дольше, громоздко, зато наглядно... ;)

0

6

оЙ...Оёёёй... ну я ещё тот колхозник, прям все догадались, что мучаю DTH-22  :D
Ща, допилю и поделюсь.
А так перелистал разные справочники и ничего не нашел, зато данные по операторам обновил, стал чуток умнее  :flirt:

+1

7

А я вчера вечером боролся с таким пультом:

http://www.ba3ar.kz/pics/1_82.jpg

В инете нашел исходники, которые не без глюка, но хорошо работают. Подправил и покромсал на инклуды чтобы типа либы юзать. Там опять вовсе не rc5. :( Искал пульт спецом под эту встроенную функцию баскома и опять облом.

0

8

Ev3658 написал(а):

оЙ...Оёёёй... ну я ещё тот колхозник, прям все догадались, что мучаю DTH-22  
Ща, допилю и поделюсь.
А так перелистал разные справочники и ничего не нашел, зато данные по операторам обновил, стал чуток умнее

http://yadi.sk/d/cZJj1RSV4Huce

0

9

RDW написал(а):

Подправил и покромсал на инклуды чтобы типа либы юзать.

У самого такие есть, пока не пробовал. Можете кодом поделиться?

0

10

radan написал(а):

кодом поделиться

Да, вот.
Пример собран на Дуне Нано.
"либа" сама пересчитывает параметры под декларированный кварц (пробовал: 8МГц и 18.432МГц - работает).
Использует Таймер0 и INT1. Резервирование память установлен от балды (от другого проекта копипаст), можно поиграться (если надо).
Под ХМегу перенастраивать не пробовал...

+1

11

RDW
Спасибо, нужное дело.

0

12

Ev3658 написал(а):

А так перелистал разные справочники и ничего не нашел, зато данные по операторам обновил, стал чуток умнее

Тоже решил поумнеть... ;)
Полистал, подумал, наваял такой код:

Код:
Dim a As Single
Dim s As String*20

a = 12345
s = Bin(a)
Print s
a = -12345
s = Bin(a)
Print s
a = 456321
s = Bin(a)
Print s
a = -456321
s = Bin(a)
Print s
a = 45.6321
s = Bin(a)
Print s
a = -45.6321
s = Bin(a)
Print s
End

В результате получаем:
http://se.uploads.ru/t/07IAN.jpg
Дальше - можно текстовыми функциями корячить любой бит и обратным преобразованием получить Single.

Корячим, переставляем, пытаемся увидеть, что получилось... ;)

Код:
Dim a As Single
Dim s As String*32
Dim d As String*32

a = 12345
s = Bin(a)
Print a
Print s

d = Right(s, 16) + Left(s, 16)
a = Val(d)

Print a
Print d

Однако тут начинаются грабли...
При попытке обратного преобразования a = Val(d) в симуляторе вместо числа пишет NAN.
При попытке a = BinVal(d) возможно преобразование, если только А будет типа Byte...

Истина где-то рядом... ;)

Отредактировано Nord (2017-02-20 19:59:32)

0

13

Ev3658 написал(а):

А как обратно то их запихнуть?

У меня есть массив с байтами, из него бы запихнуть в Single

Код:
dim j as word
dim tmp as single

j = Varptr(tmp)                                           'Указатель на переменную single
 For i = 1 to 4
   Out J , D(i)                                              'В массиве D лежат ваши 4 байта которые нужно "запихать" в single. В цикле FOR можно задать любой индекс массива 
                                                                 'чтобы выделить именно ваши 4 байта.
   Incr J
 Next                                                         'Результат работы: в переменной tmp будет число single

Как то так. :dontknow:

Отредактировано sva-don (2017-02-21 09:22:05)

+1

14

Доброго времени суток!
Благодаря 1-ому посту познакомился с операторами HIGH() и LOW(). Ev3658, благодарю!
Мне это нужно для подготовки и засылки агентов данных в блок ASM, и дальнейших расчетов. Танцы в симуляторе дали единственный вариант с нужным результатом:

Код:
     Dim Y As String * 2
     X = 2489
     Y = Hex(High(X))                   ' -> 09
     Y = Hex(Low(X))                    ' -> b9

где Y - только String! Хотя в скупой справке Баскома о стрингах ни слова.
Симулятор симулятором..., но в реальном коде, при попытке сплавить эти данные в регистр, они примутся?
И, понимаю, что не в тему, но может кто-то надоумит в следующих моментах:
1) Баском (2.0.7.5) упорно ругается 222-ой ошибкой на строку:
     !LDI R16 , Y
Заносить готовые HEX-данные в регистр, с последующей обработкой и результатом - без проблем! А переменную (даже с объявлением через .def) не дает. Что не так? КАК отправлять переменную в регистр?
2) Конечный результат разнесен в 3-х регистрах. С директивой STS могу вынести за ASM-блок все три байта, объединить, "превратить" в число... Но, может быть, в Ассемблере имеется что-то короче для получения конечного (числового) результата из нескольких регистров?

Отредактировано Lavad (2017-06-12 22:05:05)

0

15

Lavad написал(а):

Танцы в симуляторе дали единственный вариант с нужным результатом:

Код:
Dim Y As String * 2    
X = 2489     
Y = Hex(High(X))                   ' -> 09     
Y = Hex(Low(X))                    ' -> b9

Точно нужно именно это?
Что требуется? Разделить двухбайтную переменную,  на две однобайтных?

0

16

Каким образом вы пытаетесь строковую переменную стринг запихать в числовую переменную/формат и на выходе получить число? Так не бывает.
Про стринг в баскоме очень много рассказано: https://avrhelp.mcselec.com/index.html?dim.htm

0

17

Пётр написал(а):

Точно нужно именно это?

Это лишь для конвертации десятичного числа в 16-ричное. На сколько понял, регистры работают с 16-ричными данными.

RDW написал(а):

Каким образом вы пытаетесь строковую переменную стринг запихать в числовую переменную/формат...

Отправлять пытался ВСЕ форматы (и Ворды, и Байты, и Лонги, ...). Во всех случаях получал 222-ую ошибку.
Вот рабочий код, но с ручной подстановкой данных. Он работает.

Код:
Dim tmp1 As Byte
Dim tmp2 As Byte
    'data = 16 [$0010] 1-ый множитель
    'koef = 2489 [$09B9] 2-ой множитель
    'temp = 39824 [$9B90] -> ожидаемый результат
!.def dataL = R4    ; $10 - младший разряд
!.def dataH = R5    ; $00 - старший разряд
!.def koefL = R2    ; $B9 - младший разряд
!.def koefH = R3    ; $09 - старший разряд
!.def tmp1 = R16   ; $90 - младший разряд
!.def tmp2 = R17   ; $9B - старший разряд
!ldi R24 , $10
!mov R4 , R24
!ldi R24 , $00
!mov R5 , R24
!ldi R24 , $b9
!mov R2 , R24
!ldi R24 , $09
!mov R3 , R24
!clr tmp2                 ; очищаем старший разряд R18
!mul dataL , koefL    ; умножаем младшие разряды => R4 * R2 => $09 * $13 = $AB => копируем в R0,R1
!mov tmp1 , R0        ; копируем R0 в мл. разр. результата R16 => $AB => R16
!mov tmp2 , R1        ; копируем R1 в ср. разр. результата R17 => $00 => R17
!mul dataH , koefL    ; умножаем старший на младший => R5 * R2 => $01 * $13 = $13 => копируем в R0,R1
!add tmp2 , R0         ; складываем R17 и R0 => $00 + $13 = $13 => R17
!mul dataL , koefH    ; умножаем младший на старший => R4 * R3 => $09 * $01 = $09 => копируем в R0,R1
!add tmp2 , R0         ; складываем R17 и R0 => $13 + $09 = 1C => R17
!mul dataH , koefH   ; умножаем старший на старший => R5 * R3 => $01 * $01 = $01 => копируем в R0,R1
!sts {tmp1} , tmp1
!sts {tmp2} , tmp2

Dim tmp4 As String * 6
Dim tmp5 As Word
tmp4 = Hex(tmp2)
tmp4 = tmp4 + Hex(tmp1)           ' $9B90
tmp5 = HexVal(tmp4)                  ' 39824

На его основе пытался подставлять переменную, предварительно отформатировав из числовой в 16-ричное и разделив по разрядам.

0

18

Ничего не понял, что нужно-то?
"конвертации десятичного числа в 16-ричное"?

0

19

RDW написал(а):

Ничего не понял, что нужно-то?...

1) сконвертировать 10-чное число в 16-ричное
2) разделить на разряды
3) присвоить переменным [например, dataL и dataH]
4) протолкнуть эти переменные в регистры
5) выполнить с ними операции [ASM-блок]
6) извлечь из ASM-блока результат
7) сконвертировать 16-ричное в 10-чное
Так более понятно? :-)

0

20

Нет, вы описали проделанную работу с непонятной целью.
Обычно цель выглядит так: "сконвертировать 10-ое число в 16-ое" или "раздробить десятичное/шестнадцатеричное  число на простые числа/знаки (для дальнейшего вывода)...
А то, что в большинстве случая есть готовые баскомовские операторы (для конвертации) и всякие более простые решения для разделения числа, для которых ненужно воротить огород...

0

21

Нет, вы описали проделанную работу с непонятной целью....

Конечная цель одна - немного разбавить код программы. Сейчас ее объем в районе 96-98%. Выполнить ASM-блок как функцию и в ней выполнять часто используемые операции из программы. ASM-вставка с перемножением 2-байтных чисел - это пока первая попытка. Складывать и вычитать, вроде, получается. На очереди - осмыслить деление.

Обычно цель выглядит так: "сконвертировать 10-ое число в 16-ое" или "раздробить десятичное/шестнадцатеричное  число на простые числа/знаки (для дальнейшего вывода)...

В моем представлении это, скорее, мелкие шаги для достижения цели.

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

Свои потуги я уже описал выше. Можете привести рабочие примеры с меньшими затратами кода?

Отредактировано Lavad (2017-06-13 15:33:00)

0

22

Lavad написал(а):

Это лишь для конвертации десятичного числа в 16-ричное. На сколько понял, регистры работают с 16-ричными данными.

Процессор ничего не знает о системах счисления. Он работает с "ноликами" и "единичками".
По моему вы совершено неправильно пытаетесь решить задачу.
Записывайте в регистры данные как есть без конвертирования.

Lavad написал(а):

Конечная цель одна - немного разбавить код программы. Сейчас ее объем в районе 96-98%.

Какой МК? Может взять другой с большим объемом памяти?

0

23

Пётр написал(а):

Процессор ничего не знает о системах счисления. Он работает с "ноликами" и "единичками".
...
Записывайте в регистры данные как есть без конвертирования.

О ноликах и единичках я в курсе, спасибо :-) А записывать "данные как есть" работает только лишь с однобайтовым значением. В симуляторе Баскома есть окно РОН, где наглядно показывает, в каком формате данные в регистрах - в 16-ричных. Только поэтому затеял конвертацию и разделение разрядов. Вот один из примеров, на которых познаю Ассемблер:

Код:
Dim c As Byte
$asm
  .def a = r16                               ' a -> кличка регистра R16
  .def b = r17                               ' b -> кличка регистра R17
  ldi a , 3                                ' присвоим регистру R16 значение 3
  ldi b , 3                                  ' присвоим регистру R17 значение 3
  add a , b                                  ' выполняем сложение a+b [6]
  inc r17                                    ' увеличим R17 на единицу [4]
  ;ldi r17 , 4                               ' присвоим регистру R17 значение 4
  add a , b                                  ' выполняем сложение a+b [10]
  inc b                                      ' увеличим R17 на единицу [5]
  ;ldi r17 , 5                               ' присвоим регистру R17 значение 5
  add a , b                                  ' выполняем сложение a+b [15]
  rol a                                      ' сдвиг влево (умножаем на 2)
  ;ldi r17 , 0.2                             ' <- проблема с дробным умножением
  ;fmul a , r17
  sts {c} , a
$end asm
c = c / 10                                 ' -> 3

Код работает. Но замените значение, например, регистра R16 на 300 (hex: 12C) и в него попадает лишь младший разряд 2C. Старший разряд пропадает из вычислений. Соответственно, конечный результат далек от верного.

Пётр написал(а):

Какой МК? Может взять другой с большим объемом памяти?

Atmega8. Начинал познавать мир контроллеров с него, ВСЕ имеющиеся разработки на нем, в данный момент под рукой нет с бОльшей памятью. Если честно, то в последнее время не раз задумывался о замене, но отталкивают 2 момента: 1) полностью переделывать плату и 2) заново знакомиться с другой машинкой.

0

24

AVR - 8 разрядные МК, а это значит, что все переменные больше одного байта в Баскоме - это синтетика, которую надо учитывать. Например все ваши преобразования канут в лепту, если начнёте выполнять параллельно задачи, например в прерывании (неким образом асинхронность процесса). Переменные просто будут рваться.

0

25

RDW написал(а):

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

Да, согласен, об этом уже начитался, в курсе. Какая бы ни была программа, регистры РОН постоянно в действии; один или несколько регистров всегда хранят данные, необходимые для вычислений и мое вмешательство (даже при отсутствии прерываний) устроит там кашу.
Мне бы, пока в симуляторе, научиться каким-то мелким шагам и азам. Сейчас я в тупике "как загрузить удобоваримую ПЕРЕМЕННУЮ в регистр" :-( Пока, кроме общей теории, тут ничем не "помогли".

0

26

Зачем вам вообще грузить переменные в регистр? Если вам интересен Ассемблер и очень критично к оптимизации кода - это одно дело, для остального - это ненужно.
Просто залезая в регистры, вам придется изучать всю архитектуру, т.к. там есть жесткие правила/разделения в адресации/использовании R00 - R31, скажу даже больше, влезая в них, вы можете нарушать логику работы основной программы, т.к. компилятор Баскома их может использовать.

0

27

Lavad написал(а):

В симуляторе Баскома есть окно РОН, где наглядно показывает, в каком формате данные в регистрах - в 16-ричных.

Повторюсь, процессор ничего не знает о системах счисления. Данные в шестнадцатеричном виде лишь для нашего удобства, но это не значит что они в том же виде в регистрах и переменных.

Примеры с ассемблерными вставками Вставки на ASM AVR (ассемблер)

+1

28

Пётр написал(а):

...Данные в шестнадцатеричном виде лишь для нашего удобства, но это не значит что они в том же виде в регистрах и переменных...

Спасибо за науку! Постараюсь не забыть :-)

Пётр написал(а):

...Примеры с ассемблерными вставками Вставки на ASM AVR (ассемблер)

А вот за это премного благодарен. Нашел и просимулировал ответ на свой вопрос.

Код:
Loadadr [переменная] , X
LD Rd,X+
LD Rd,X

Работает! Остается только как следует это пережевать и проглотить!

0

29

Lavad написал(а):

Если честно, то в последнее время не раз задумывался о замене, но отталкивают 2 момента: 1) полностью переделывать плату и 2) заново знакомиться с другой машинкой


Совпадают по выводам и корпусам:

Atmega8 (8 кб) = Atmega168P, PA (16 кб) = Atmega328P (32 кб)

из +++, кроме большей памяти, больше аппаратных средств.

Основные регистры совпадают.

Так, что макетку переделывать нет необходимости.

0

30

Lavad написал(а):

Loadadr [переменная] , X
LD Rd,X+
LD Rd,X


6 тактов

а так быстрее, 4 такта:

чтение из переменной:
!LDS Rx , {переменная}
!LDS Rx , {переменная + 1}

запись в переменную:
!STS {переменная} , Rx
!STS {переменная + 1} , Rx

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Работа с байтами многобайтовой переменной