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

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

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

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


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


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

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

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


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