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

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

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

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


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


Битовые операции в ВASCOM.

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

1

Не секрет, что при реализации проектов бывает, что удобно хранить несколько значений в одном байте: каждый бит хранит свою информацию.

Не так давно встала проблема реализации алгоритма. Есть восемь логических датчиков. Логично их состояние хранить в одном байте - каждый бит для одного датчика  При работе смотрим значение конкретного бита: при одном значении бита  - действие одно, при другом - другое. 

Если писать на BASCOM и для каждого датчика объявлять переменную типа bit, то не хватает памяти. Оказывается (при детальном анализе), что BASCOM для битовых переменных отводит целый (!) байт. Не экономно это...

В описаниях я не нашел подходящих команд, пришлось пользоваться ассемблером.
Может кто-то знает команды для работы с отдельными битами в BASCOM?

0

2

Т.е. если в коде написать:

Код:
Dim S As Byte
...
Set S.0
Reset S.1
S.2=1
IF S.0=1 Then Set S.7
...

То всё будет байтовое? Это ваще как?  :D Вроде бы норм генерит..

0

3

В этом коде, наверное, биты будут  сохранены в одном байте , в переменной под именем S.
Но вот когда  мы объявляем битовые переменные вот так

Код:
Dim S As Byte
Dim M As Byte

то для каждой переменной будет отведен отдельный байт: переменная S будет храниться в одном байте, а переменная М - в другом. Это явно не оптимальный вариант.
Может я что-то не так в настройках компилятора указал, но при симуляции и дизассемблировании кода с таким объявлением переменных это действительно так.

Теперь еще один момент. Например, мне надо поочередно перебрать все биты байта. Хочется, конечно, написать код вот так

Код:
For i=1 to 8
......
If S.i = 1 then какие-то действия
......
next i

В этом случае компилятор матерится и хочет явного указания номера бита и в цикле эту операцию у меня не получилось написать.
Была задумка сделать циклический сдвиг SHIFT'ом и смотреть на бит переноса (переполнения). Но как средствами васика посмотреть состояние этого бита для меня осталось загадкой.   Хотя вариант SREG.0 я почему-то не пробовал...

Отредактировано spin (2014-09-22 19:46:57)

0

4

А попробуйте так:

Код:
Dim S As Bit
Dim M As Bit

Сейчас в протеусе глянул, всё в один байт запихивает.

0

5

Прошу прощения. В предыдущем посте вкралась досадная ошибка. Думаю об одном, пишу другое :)

Код:
Dim S As Bit
Dim M As Bit

Именно этот код у меня и был на уме. У меня васик при генерации кода запихивает значения битов в разные байты. Проверял встроенным симулятором и дизассемблером.
Если не секрет - как в протеусе посмотреть адрес байта (ячейку) хранения переменных?

0

6

Если хотите мониторить биты, то проще жёстко прописывать каждый бит в байте (пример RDW)  и далее моннитор:

Код:
for a=1 to 8
if s.0 = 1 then set led else reset led
waitms 500
rotate s
next

0

7

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

Если не секрет - как в протеусе посмотреть адрес байта (ячейку) хранения переменных?

http://se.uploads.ru/t/1qyXm.jpg

0

8

Хороший вариант с применением ROTATE. Я упустил из виду этот оператор.
Хотя вышел из ситуации примерно таким же образом, только посредством оператора SHIFT. Сначала сдвигаю байт, потом ассемблерной вставкой проверяю бит переноса и передаю управление на определенную метку. Недостаток этого метода в том, что сдвиг надо делать над копией значения переменной, поскольку при сдвиге теряются значения некоторых битов.
Спасибо за скрин.

0

9

Всё же оптимальнее использовать rotate, т.к. данные обрабатываются последовательно (не в произвольной форме) и не портят содержимое (главное не забывать проворачивать по 8 раз).

0

10

да всё зависит от задачи. Вот примерно, если появилась ошибка, узнаём код ошибки по длине ипульса.

Код:
if s<>0
for a=1 to 8
set led
if s.0 = 1 then waitms 600 else waitms 200
reset led
waitms 500
rotate s
next
end if

0

11

Подскажите, по битовым операциям
Есть такое
PORTC=0
PORTC=255
Однако в порту C задействованы только старшие 4 бита, вот к ним и нужно применять вышеописанное. Как это сделать не изменяя младшие 4 бита.
Операции Reset PORTC.5 и SET PORTC.5 и т.д. не прокатывает, нужна одновременная запись.

0

12

Geolog
Может так?
DDRС= &B00000000
DDRС= &B11110000

0

13

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

Geolog
Может так?
DDRС= &B00000000
DDRС= &B11110000


Так ведь с помощью этого мы только настраиваем выход-вход порта
Не прокатывает

Отредактировано Geolog (2014-10-24 12:11:15)

0

14

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

Подскажите, по битовым операциям
Есть такое
PORTC=0
PORTC=255
Однако в порту C задействованы только старшие 4 бита, вот к ним и нужно применять вышеописанное. Как это сделать не изменяя младшие 4 бита.
Операции Reset PORTC.5 и SET PORTC.5 и т.д. не прокатывает, нужна одновременная запись.

Маска по "1"

переменная  = переменная Xor &B_XXXX_0000   '  Где XXXX - Ваше значение

  $asm
    lds R16 , {Переменная}
    ori R16 , &B_XXXX_0000      ' Первые 4 бита не меняются
    sts {Переменная} , R16
  $end asm

Маска по "0"

переменная  = переменная AND &B_XXXX_1111    '  Где XXXX - Ваше значение

  $asm
    lds R16 , {Переменная}
    andi R16 , &B_XXXX_1111     ' Первые 4 бита не меняются 
    sts {Переменная} , R16
  $end asm

Отредактировано sasha_1973 (2014-10-24 12:16:41)

0

15

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

Маска по "1"

переменная  = переменная Xor &B_XXXX_0000

Маска по "0"

переменная  = переменная AND &B_XXXX_1111

Спасибо
По маске можно как из вариантов, думал уже про них.
A если остальные биты используются как отдельные битовые переменные.
Возможно ли взять по адресу порта текущее состояние порта сделать маску и обратно записать
Александр, за ассемблерный код спасибо, стараюсь где возможно тоже ассемблер вставлять

Отредактировано Geolog (2014-10-24 12:21:08)

0

16

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

Возможно ли взять по адресу порта текущее состояние порта сделать маску и обратно записать

Конечно можно:

!in R16 , pinc   ' 1 такт
!ori R16 , &B_XXXX_0000      ' Первые 4 бита не меняются
!out portc , R16   ' 1 такт

!lds R16 , pinc   ' 2 такта
!ori R16 , &B_XXXX_0000      ' Первые 4 бита не меняются
!sts portc , R16    ' 2 такта

Первый вариант быстрее

0

17

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

Конечно можно:

!in R16 , pinc   ' 1 такт
!ori R16 , &B_XXXX_0000      ' Первые 4 бита не меняются
!out portc , R16   ' 1 такт

!lds R16 , pinc   ' 2 такта
!ori R16 , &B_XXXX_0000      ' Первые 4 бита не меняются
!sts portc , R16    ' 2 такта

Первый вариант быстрее

То что надо
СПАСИБО!
добавил себе в копилку

0

18

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

То что надо
СПАСИБО!

На ЗДОРОВЬЕ !

0

19

Прошу помощи, не знаю как сложить две 8 битные переменные в одну 16 битную
типа:

Код:
DIM W As Word
Dim B1 As Byte, B2 as Byte
Low(W)=B1
HIGH(W)=B2

Само собой так не прокатит ))) Но может есть какой простой и быстрый алгоритм объединения в одну?

0

20

Код:
DIM W As Word
Dim B1 As Byte At W Overlay
Dim B2 as Byte At W+1 Overlay

+1

21

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

DIM W As Word Dim B1 As Byte, B2 as Byte Low(W)=B1 HIGH(W)=B2

почему? внешне всё верно!
вроде и в коде я так же делал

0

22

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

Прошу помощи, не знаю как сложить две 8 битные переменные в одну 16 битную
типа:
Код:

DIM W As Word
Dim B1 As Byte, B2 as Byte
Low(W)=B1
HIGH(W)=B2

Само собой так не прокатит ))) Но может есть какой простой и быстрый алгоритм объединения в одну?

А так чем не устраивает?
W = MAKEINT(B1 ,B2)

Или
W = (256 * B2) + B1

Отредактировано sva-don (2017-07-10 14:15:06)

0

23

Зачем лишний код генерить, оверлеи же есть, в разы всё упрощается.

0

24

Обрабатываю нажатие кнопок по таймеру в прерывании. Т.е. при нажатии кнопки выставляю флаг, который уже в программе обрабатываю. Так вот работа с битами занимает очень много времени, что критично, для прерывания.http://s7.uploads.ru/t/Zk5gv.png
knl-'это флаг, kn_l -это пин.
Это скрин с протеуса, дизасемблер. Можно ли как то оптимизировать сей процесс? Или сразу флаг обозначить как байт. Получается быстрей.

0

25

Случайно кто то не прлбовал запустить дислей с восьмибитной шиной данных вставленный в модуль ардуино уно? Там конструктивно 8 бит данных дисплея попадают на 6 пинов порт.D и два пина порт.В
В программе данные объявляются так
Data_lcd Alias Portd и если на проводах подсоединить 8 бит данных на PORTD то всё работает. Может кто подскажет возможно ли как то в баскоме сконфигурировать так  чтоб 6 бит из Data_lcd относились к PORTD.2 до 7 а 2 бита к PORDB.0 и 1?

0

26

Я не раз уже говорил на форуме, что байтовые операции работают в разы быстрее. Битовые можно использовать, если мало очень памяти, но как-то параноидально.

0

27

Конфигурировать можно

Код:
Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Portc.7 , Rs = Portc.6

Нужно указать требуемые выводы.

0

28

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

Я не раз уже говорил на форуме, что байтовые операции работают в разы быстрее. Битовые можно использовать, если мало очень памяти, но как-то параноидально.

Всё правильно. НО!

Код:
     in r26,pind                                            'загружаем состояние порта D в регистр
   andi r26,56                                              ' накладываем маску &B00111000
   sts {ai},r26                                             ' полученный результат присваиваем переменной AI
 

и далее проверять переменную Аi, намного быстрее, но

Код:
if knl=0 then....
else if knr = 0 then ... и.т.д.


гораздо приятнее и читабильнее, особенно, когда данную конструкцию хочешь использовать во многих проектах. Тут наоборот, не упёртость, а найти золотую середину.

0

29

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

Конфигурировать можно

Если это мне отвечали то такая конфигурация для либы баскома и дисплеев с контроллером  HD44780.
У меня дисплей вот такой https://ru.aliexpress.com/item/Free-Shi … 84364.html
С ардуиной он запустился. На баскоме код работает но если выделить под 8 бит данные PORTD и подкинуть к плате ардуино уно этот дисплей на проводах. А хочется запустить дисплей без кроссплаты просто вставив его в плату как он запускается в ардуине.  Для простых проектов связка модуля ардуино уно + графический дисплей удобная штука.
В библиотеке UTFT такая конфигурация

Код:
if (display_model==ILI9341_UNO || display_model==ILI9327_UNO)
{
	cport(PORTB,      0xFC);    // сбрасываем в 0 младшие 2 бита порта B
	sport(PORTB, VH & 0x03);    // устанавливаем значение младших 2 битов порта B
	cport(PORTD,      0x03);    // сбрасываем в 0 старшие 6 битов порта D
	sport(PORTD, VH & 0xFC);    // устанавливаем значение старших 6 битов порта D
	if(!LCD_Write_1byte_Flag){pulse_low(P_WR, B_WR);}
	cport(PORTB,      0xFC);    // сбрасываем в 0 младшие 2 бита порта B
	sport(PORTB, VL & 0x03);    // устанавливаем значение младших 2 битов порта B
	cport(PORTD,      0x03);    // сбрасываем в 0 старшие 6 битов порта D
	sport(PORTD, VL & 0xFC);    // устанавливаем значение старших 6 битов порта D
	pulse_low(P_WR, B_WR);
}
else if (display_model==ILI9341_MEGA)

Я не пойму как можно на баскоме назначить 2 младших бита порта В и 6 битов порта D чтоб на них одним байтом выставлять данные.

Data_lcd = &HFF вот такая команда выставить все 8 бит данных в единицу но по разным портам.
Если сделать так то работает.
Config Portd = Output
Data_lcd Alias Portd   
Но так пины на плате не совпадают с портами мега328.

0

30

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

гораздо приятнее и читабильнее, особенно, когда данную конструкцию хочешь использовать во многих проектах. Тут наоборот, не упёртость, а найти золотую середину.

А если вообще расширить сознание, то заменив/приняв бит за байт, мы получаем а-ж 256 состояний, порой в проекте это сильно помогает расширить функционал.  :idea:

0

Похожие темы


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