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

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

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

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


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


Все забыл...

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

31

Не хотел создавать новую тему, так как эта наиболее подходящая, хотя можно переименовать "Сломал мозг".
Если не сложно, вправьте извилины обратно  :hobo:
Вся суть такая, из переменной LONG надо выдрать младшие два байта в переменную WORD и 1 младший байт из двух старших в переменную Byte.
Выглядит это так:

Код:
Dim L As Long
Dim W as Word
Dim B As Byte

L=320000          'Раскроим это значение
W=Highw(L)       'Временно возьмём старшие байты из Long
B=Low(W)         'Возьмём младший байт из двух старших Long
W=Loww(L)       'Возьмём младший байт Long


В итоге:
Long=320000
Word=57856
Byte=4

Как это разобрать то? 4 раза по 57856 = 231424  :tired:

Отредактировано Ev3658 (2017-12-14 19:41:55)

0

32

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

Не хотел создавать новую тему, так как эта наиболее подходящая, хотя можно переименовать "Сломал мозг".

Вот тут не про похожее ? ;)
Битовые операции в ВASCOM.

0

33

Тоже чёт нипонял что нуно...
яб сделал через оверлей. Например, число занимает 6 байт. 123456. через оверлей доступны любее байты и слова и даже биты. )))

0

34

-NMi- написал(а):

Тоже чёт нипонял что нуно...

Есть у человека переменная типа Long, содержащая байты L1, L2, L3 и L4.
Ему требуется байты L3 и L4 перенести в переменную типа Word...
Вот как бы и все... ;)

0

35

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

Вот тут не про похожее ?
Битовые операции в ВASCOM.

Почти.
Может чего подскажите и может быть кому будет полезно разобраться.
Вся суть такая: Сделать управление двумя осями на аппаратном уровне, то-есть движение от точки А до точки Б сразу по двум осям одновременно.
Алгоритм вот такой:
http://sg.uploads.ru/t/pF4cm.jpg

Использовал все таймеры Xmega256A3.

Первый таймер TCF0 задаёт скорость перемещения
Дальше на каждую ось идут по два таймера на редукцию для наклонного движения по кривой. То-есть рисование кривой линии, вот тут у меня запарка. Подробно о таймерах TCE0 и TCE1.
Так как на мотор нужно подать импульс, я прибавляю значение к TCE0 + 100, а значения выхода OCxA=50, если такое сделать и на TCD0 и TCD1 - оси будут двигаться одновременно в такт.
Программно реализовать редукцию Xmega не потянет, частота на двигатели порой под 200кгц надо.

Дальше таймер TCC0 - ось X (TCC1-ось Z) считает кол-во импульсов (1 импульс=1 микрону = 0.001мм), но так как мне надо считать большее расстояние, я задействовал прерывание в котором есть 1 байт и который просто вычетая дохожу до нужной точки.

Вот кусок таймеров с системами события:

Код:
'Обязательно выходы OCA на выход, в отличии от картинки использовал выходы B

Puls1 Alias Porte.1                                         'Выход импульсов перемещения X
Config Puls1 = Output
Puls2 Alias Portd.1                                         'Выход импульсов перемещения Z
Config Puls2 = Output
'===================== Главный тактовый таймер и его событие - Скорость перемещения
Config Tcf0 = Normal , Prescale = 0 , Event_delay = Enabled
Speed Alias Tcf0_per
Config Event_system = Dummy , Mux0 = Tcf0_ovf               'Событие тактового таймера

'===================== Таймеры перемещения
Config Tce0 = Normal , Prescale = 0 , Event_source = E0 , Compareb = Enabled , Event_delay = Enabled
Config Tcd0 = Normal , Prescale = 0 , Event_source = E0 , Compareb = Enabled , Event_delay = Enabled
Tce0_ccb = 10
Tcd0_ccb = 10

Config Event_system = Dummy , Mux1 = Tce0_ovf               'Событие для старшего редукционного таймера X
Config Event_system = Dummy , Mux2 = Tcd0_ovf               'Событие для старшего редукционного таймера Z

Config Tce1 = Normal , Prescale = E1 , Event_source = E1 , Event_delay = Enabled
Config Tcd1 = Normal , Prescale = E2 , Event_source = E2 , Event_delay = Enabled


Xredl Alias Tce0_per    'Младший байт редуктора X
Zredl Alias Tcd0_per    'Младший байт редуктора Z
Xredh Alias Tce1_per   'Старший байт редуктора X
Zredh Alias Tcd1_per   'Старший байт редуктора Z
'===================== Таймеры подсчёта микронов
Config Event_system = Dummy , Mux3 = Tce1_ovf               'Событие для счёта микрон (импульсов) X
Config Event_system = Dummy , Mux4 = Tcd1_ovf               'Событие для счёта микрон (импульсов) Z
Config Tcc0 = Normal , Prescale = E3 , Event_source = E3
Config Tcc1 = Normal , Prescale = E4 , Event_source = E4

Xmm Alias Tcc0_per 'регистр микронов X (до 65535)
Zmm Alias Tcc1_per 'регистр микронов Z (до 65535)


'===================== Прерывания таймеров

Dim Hx As Byte    'Для увеличения разрядности таймера счёта X
Dim Hz As Byte    'Для увеличения разрядности таймера счёта Z

On Tcc0_ovf Pozx:                                           'Прерывание по позиции X
On Tcc1_ovf Pozz:                                           'Прерывание по позиции  Z


Enable Interrupts
Do
...
...
...
...
Loop

If Xh = 0 Then 'останавливаем импульсы X
   Tce0_ctrla = 0
   Tce0_cnt = 0
   Disable Tcc0_ovf
   Else                        'Если чего, уменьшаем
    Decr Xh
End If

Return


Pozz:

If Zh = 0 Then    'останавливаем импульсы Z
    Tcd0_ctrla = 0
    Tcd0_cnt = 0
     Disable Tcc1_ovf
    Else                  'Если чего, уменьшаем
     Decr Zh
End If

Return

Так вот, чтоб запустить эту адскую таймерную машину, нужно (приписываю тип данных в имя переменной образно)

LongX=11000 - переместится по X на 11000
LongZ=99000 - переместится по Z на 99000

Редукцию рассчитываю так:
Single=LongZ / longX       (900.099975585)
Single=Single*100
LongRedX=Single + 100   (1000)
longResZ=100                  (100)   ( - нужно для осцилятора и так-же повысить точность для рассчёта с плавающей запятой)

Дальше пихаем редукию как на картинке:

TCE0=LowW(longRedX)   
TCE1=HigW(LongRedX)   

TCD0=LowW(longRedZ)
TCD1=HigW(LongRedZ)

Пихаем нужное кол-во импульсов:
TCC0=LowW(LongX)             = 11000
ByteX=Low( HighW(LongX) ) = 0

TCC1=LowW(LongZ)             = 33464
ByteZ=Low( HighW(LongZ) ) = 1

Обнуляем таймеры:

Код:
   Tcd0_cnt = 0
   Tce0_cnt = 0                                            
   Tcd0_cnt = 0                                            
   Tce1_cnt = 0                                           
   Tcd1_cnt = 0                                            
   Tcc0_cnt = 0                                             
   Tcc1_cnt = 0 

                                           

Разрешаем прерывания и запускаем главные таймеры:

Код:
Enable Tcc0_ovf , Med
Enable Tcc1_ovf , Med
Speed = 4
Config Tce0 = Pwm , Prescale = E0 , Event_source = E0 , Compareb = Enabled
Config Tcd0 = Pwm , Prescale = E0 , Event_source = E0 , Compareb = Enabled
Config Tcf0 = Normal , Prescale = 1 , Event_delay = Enabled       'Запуск главного тактового таймера

Вот тут то и проблема, как бы два двигателя должны придти с разной скоростью к моменту остановки вместе (вместе остановится), но нефига подобного), почему-то никак не получается сделать, чтоб останавливались вместе, ну никак не получается, чего-то в голове не так, походу она сломалась  %-)

Отредактировано Ev3658 (2017-12-14 21:12:46)

0

36

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

-NMi- написал(а):

    Тоже чёт нипонял что нуно...

Есть у человека переменная типа Long, содержащая байты L1, L2, L3 и L4.
Ему требуется байты L3 и L4 перенести в переменную типа Word...
Вот как бы и все... ;)

Ну и что сложного? ОВЕРЛЕЙ тебе ПОМОЖЕТ. Забей в симуляторе или дебаггере адрес хранения твоей переменной и выкури где находятся нужные тебе байты или слова. Задача элементарная.

0

37

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

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

После первого прочтения вашей проблемы идей пока не возникло, тем более, что с XMega не копался...

-NMi- настойчиво предлагает использовать оверлей для "переноса" нужных значений.
Лично мне этот путь не совсем понятен, т.к. ни разу не приходилось в него вникать.
И я этого не стесняюсь... ;)

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

0

38

Задача у меня вроде как простая.
Есть два двигателя с блоками управления, обычный  импульс сигнала заставляет переместится на 1 деление из 10 000 делений энкодера, то-есть 10 000 импульсов = 1 обороту вала.
Нужно сделать синхронное управление положением двух двигателей.
Все наверно знают что такое токарный станок, там одна ось длинная (Z), другая которая с резцом короткая (X).
Нужно отработать моторами задание, к примеру по X на 10мм, а по Z на 300мм. - вот тут у меня запарка, ведь ось X надо двигаться на 300/10= 30 раз меньше.
Тут-то я и использовал по два таймера на 1 ось после тактового таймера, 32 битной редукции вполне должно хватить.
Правда появилась проблема точности редукции, ведь там порой при делении плавающая запятая появляется.
По этому начальное значение счёта редукции приравниваю к 100, это даёт возможность x00 - два значения после запятой брать в расчёт.
К примеру 310/30=10.333 - умножаем на 100 и получаем 1033 для таймера, в итоге редукция по X 100, а по Z 100+1033=1133. - но это не работает ((((.

Добавлено спустя 13 минут 5 секунд:

Попил чаю.
Добавлено спустя 13 минут 5 секунд:

Ну я и косячнул. Ведь вывод на импульсы взял с таймера младших байтов и если редукция больше 16 бит, то будут лишние импульсы.  :idea:

Отредактировано Ev3658 (2017-12-14 23:09:14)

0

39

Мне кажется или я форумом ошибся?
***
Elementary Data Types

· Bit (1/8 byte). A bit can hold only the value 0 or 1. A group of 8 bits is called a byte.
· Byte (1 byte).  Bytes are stores as unsigned 8-bit binary numbers ranging in value from 0 to 255.
· Integer (two bytes). Integers are stored as signed sixteen-bit binary numbers ranging in value from -32,768 to +32,767.
· Word (two bytes). Words are stored as unsigned sixteen-bit binary numbers ranging in value from 0 to 65535.
· Dword(fout bytes). Dwords are stored as unsigned 32-bit unsigned numbers ranging in value from 0 to 4294967295
· Long (four bytes). Longs are stored as signed 32-bit binary numbers ranging in value from -2147483648 to 2147483647.
· Single. Singles are stored as signed 32 bit binary numbers. Ranging in value from 1.5 x 10^–45 to 3.4 x 10^38
· Double. Doubles are stored as signed 64 bit binary numbers. Ranging in value from 5.0 x 10^–324 to 1.7 x 10^308
· String (up to 254 bytes). Strings are stored as bytes and are terminated with a 0-byte. A string dimensioned with a length of 10 bytes will occupy 11 bytes.
***
Ущипните меня... но:
в байте (как ни странно) восемь бит или два ниббла.
в слове вроде два байта...
в двойном слове два слова или четыре байта и тд...
неужели не понятен принцип оверлеев??

0

40

-NMi- написал(а):

Мне кажется или я форумом ошибся?
...
неужели не понятен принцип оверлеев??

Если это ко мне, то отвечу... ;)

Форумом вы не ошиблись, вы на месте. ;)

Принцип оверлеев лично мне непонятен по причине неиспользования его впрямую.
Просто банально не вникал за ненадобностью (пока).
Равно как и не использовал (пока) ни разу минимум треть команд и операторов Bascom...

Вы же тоже не сможете объяснить, почему для "машки" лучше деревянной рукоятки ничего не придумали... ;)
А, вроде и слова знакомые... ;)

Отредактировано Nord (2017-12-15 08:42:47)

0

41

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

Нужно отработать моторами задание, к примеру по X на 10мм, а по Z на 300мм. - вот тут у меня запарка, ведь ось X надо двигаться на 300/10= 30 раз меньше.

А если по Х надо 8мм, а по Z - 420мм ?
Кратность уже на 10...
ИМХО, надо сначала продумать, как адекватно привязать эту самую "кратность"...

0

42

Записать 1 байт в одну из двух байтов переменной Word или в один из четырёх байтов в Long - то да, путь идёт через  Overlay
Если считать на выбор байт из Word, то тут операторы Low и High
Но вот на выбор из 4х 1 байт из переменной Long не получится, нужно сперва считать два байта в Word через Loww и Highw и после уже Low и  High

W=Loww(L)  - считываем два нижних байта из переменной Long
B=Low(W) - Считываем один нижний байт из переменной Word

Иначе:
Dim L As Long

Dim W1 As Word At L Overlay
Dim W1 As Word At L+2 Overlay

Dim B1 As Byte AT L Overlay
Dim B2 As Byte AT L+1 Overlay
Dim B3 As Byte AT L+2 Overlay
Dim B4 As Byte AT L+3 Overlay

И после все переменные имеют нужные адреса и сразу выдают значение.

Отредактировано Ev3658 (2017-12-15 11:05:04)

0

43

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

Если считать на выбор байт из Word, то тут операторы Low и HighНо вот на выбор из 4х 1 байт из переменной Long не получится, нужно сперва считать два байта в Word через Loww и Highw и после уже Low и  High

Если скорость некритична, то можно тупо побитно переносить.

Dim A As Word
Dim B As Long

For C 8 To 23
    A.C-8 = B.C
Next C

В результате в А будут скопированы 2 и 3 байты из В...

Отредактировано Nord (2017-12-15 11:46:18)

0

44

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

из переменной LONG надо выдрать младшие два байта в переменную WORD и 1 младший байт из двух старших в переменную Byte

С этим нет проблем, если есть четкое представление, как баском хранит данные в LONG. LONG - хранение с знаком, надо понять с какой стороны используется бит и ещё бывает так, что в зависимости от числа данные могут быть инверсные, т.е. например -1 - это будет какой-нить #FFFFFFFF. Когда разберешься как хранит данные Лонг, уже дальше легко оверлеями и простыми логическими операциями и сдвигом привести к нужному виду.

0

45

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

А если по Х надо 8мм, а по Z - 420мм ?
Кратность уже на 10...
ИМХО, надо сначала продумать, как адекватно привязать эту самую "кратность"...


Сама идея была использовать таймеры.
Главный тактовый таймер - от него уже другие считают кратность и уже дальше выходит импульс который подсчитывается тоже аппаратно.
В Xmega мост между таймерами делается через систему событий, такая классная штука!!!!
Систем событий всего 7 и таймеров тоже.
Запускаем таймер с тактами от процессора, дальше настраиваем любой канал 0-7 на его переполнение и дальше берём любой таймер и настраиваем источник такта на канал события и Prescale тоже на канал события.

К примеру надо сделать так, чтоб два таймера считали от одного таймера:

Config Tcf0 = Normal , Prescale = 8   - Запускаем таймер от тактов процессора  / 8
Config Event_system = Dummy , Mux0 = Tcf0_ovf  - Берём канал события №0 и настраиваем срабатывание по переполнению таймера (можно и на _OCA _OCB _Err)
Tcf0_Per = 1000 - ограничиваем счёт таймера (если надо)

Настраиваем два таймера на счёт тактов события №0:
Config Tce0 = Normal , Prescale = E0 , Event_source = E0
Config Tce1 = Normal , Prescale = E0 , Event_source = E0

Tce0_Per=10000
Tce1_Per=1000

Вот тут и получаем редукцию (кратность), таймер Tce0 будет медленней переполнятся, чем таймер Tce1, а такт один и тот-же.

Если надо в кратность учесть плавающую запятую, то делаем минимальное переполнение 100 или 1000, то-есть мы всё равно получим значение о переполнении, но теперь можно будет хотя-бы пару знаков после запятой учесть в счёте:
Кратность = 3.4
Если просто, то будет так:
Tce0_Per= Кратность + 1 (= 4) (нельзя регистр PER делать нулём)
Tce1_Per=1
А если учесть запятую:
Tce0_Per= Кратность *100+1 (=34+1)
Tce1_Per=100

Да, забыл, если главный таймер с которого начинается счёт работает на запредельных скоростях, то нужно включить в нём задержку:
Config Tcf0 = Normal , Prescale = 1 , Event_delay = Enabled  - она нужна, чтоб передать информацию о переполнении

Для отключения таймеров нужно Prescale=0, но думаю проще будет сразу вбить в регистр CTRLA=0, то-есть Tcf0_CtrlA=0

Получить значение счёта можно из регистра CNT и записать его тоже - Tcf0_CNT.

0


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