Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.71/41: Рейтинг темы: голосов - 41, средняя оценка - 4.71
worizzzok
0 / 0 / 0
Регистрация: 28.11.2012
Сообщений: 138
1

Как определить порядковый номер бита в байте

13.04.2014, 04:43. Просмотров 7351. Ответов 19
Метки нет (Все метки)

Здравствуйте.
Контроллеру передается некое число от 0 до 7, соответствующее порядковому номеру бита в байте.
Можно делать вот так: ori r16, 0b00000010 (т.е, 1 бит будет установлен, остальные останутся без изменений), однако, это не удобно, хочется макрос, который бы устанавливал бит так macros r16,2
Буду признателен за помощь :)
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.04.2014, 04:43
Ответы с готовыми решениями:

Си - как передать вых. порт и номер бита как переменные?
Преамбула: Есть у меня некий проект, там много сдвиговых регистров типа 595. Строб я на них...

Как проверить наличие бита в байте
Здравствуйте!! Собственно вопрос, можно ли как нибудь записать условие if на проверку бита в...

Наличие бита в байте
Подскажите, правильна ли реализация проверки наличия бита в байте #define MARK 0x02 .. if...

Изменение бита в байте
Помогите начинающему - покажите, в какую сторону копать. При выполнении программы ...

Замена младшего бита в байте
Доброго времени суток! Как можно заменить младший бит в байте, и сделать это так, что-бы потом...

19
omokost
0 / 0 / 0
Регистрация: 24.12.2011
Сообщений: 2,753
13.04.2014, 06:53 2
??? Записи ori r16, 0b00000010 и ori r16, 2 эквивалентны.
0
stt
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
13.04.2014, 09:23 3
Цитата Сообщение от worizzzok
Контроллеру передается некое число от 0 до 7, соответствующее порядковому номеру бита в байте.
Можно делать вот так: ori r16, 0b00000010 (т.е, 1 бит будет установлен, остальные останутся без изменений), однако, это не удобно, хочется макрос, который бы устанавливал бит так macros r16,2
Приняли в переменнную counter число, в переменной temp сдвигаете "1" counter раз, получаете установленый бит в нужной позиции. Т.е. приняли "5", получили 0b00100000. Находящееся в temp используете как маску. Или непосредственно, если ненужно сохранять остальные биты.
0
Леанид Ивинавич
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 699
13.04.2014, 09:34 4
Цитата Сообщение от worizzzok
хочется макрос, который бы устанавливал бит так macros r16,2
Код
.macro   clbr         ;clear bit in rikystir
cbr @0,exp2(@1)
.endm

.macro   stbr         ;set bit in rikystir
sbr @0,exp2(@1)
.endm
0
ftomdkir
0 / 0 / 0
Регистрация: 12.04.2012
Сообщений: 97
13.04.2014, 12:35 5
Всё гораздо проще:

.macro macros
ori @0, 1<<@1
.endm

PS2: Если не нужно сохранять другие биты.
0
worizzzok
0 / 0 / 0
Регистрация: 28.11.2012
Сообщений: 138
13.04.2014, 15:46 6
Спасибо за ответы.

2omokost, увы, это не одно и то же. Например ori r16, 3 будет эквивалентна ori r16, 0b00000011, а должно быть 0b00000100

2flomdger, нужно сохранять

Леанид Ивинавич и STT, это то, что нужно! Спасибо
0
worizzzok
0 / 0 / 0
Регистрация: 28.11.2012
Сообщений: 138
14.04.2014, 21:00 7
поторопился я что-то с восторгом. ori r16, 0b00000011 принимает в качестве параметра только числа, запись ori r16, r17 выдает ошибку.
Как и ori r16, exp2(r17) - error: syntax error, unexpected REGISTER
Можно ли как-то передать в функцию не адрес регистра, а его содержимое без ошибки?
0
_pv
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,515
14.04.2014, 21:04 8
avr instruction set: http://www.atmel.com/images/doc0856.pdf
там можно прочитать чем отличается инструкция ORI от OR.
0
worizzzok
0 / 0 / 0
Регистрация: 28.11.2012
Сообщений: 138
14.04.2014, 21:40 9
Тьфу ты! Думал об одном, а написал другое. Не ORI, а SBR, как в примере Леанида Ивиновича. Простите, за путаницу.
0
Леанид Ивинавич
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 699
15.04.2014, 11:41 10
Не совсем понятно, что Вы хотите. Чтобы номер бита содержался в регистре? Тогда так просто не получится. Нужно в цикле сдвигать единицу столько раз, какое число содержится в регистре, затем делать OR.
0
ftomdkir
0 / 0 / 0
Регистрация: 12.04.2012
Сообщений: 97
15.04.2014, 14:08 11
ну или индексную таблицу из 8 переходов мутить, будет быстрее чем сдвигать но память.
0
tyzord66
0 / 0 / 0
Регистрация: 14.10.2011
Сообщений: 806
15.04.2014, 15:41 12
Цитата Сообщение от flomdger
ну или индексную таблицу из 8 переходов мутить, будет быстрее чем сдвигать но память.
В "temp" номер бита, который надо установить
Код
shl_temp:   ldi      ZL,   $7
sub      ZL,   temp
clr     ZH
subi    ZL, low (-Shift_Nmb)
sbci    ZH, high (-Shift_Nmb)
ldi      temp,$1
ijmp
Shift_Nmb:   lsl      temp
lsl      temp
lsl      temp
lsl      temp
lsl      temp
lsl      temp
lsl      temp
ret
0
ftomdkir
0 / 0 / 0
Регистрация: 12.04.2012
Сообщений: 97
15.04.2014, 17:51 13
Как вариант
0
tyzord66
0 / 0 / 0
Регистрация: 14.10.2011
Сообщений: 806
15.04.2014, 18:15 14
Цитата Сообщение от flomdger
Как вариант
Если скорость не критична, то в цикле, как предложил STT
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
15.04.2014, 19:39 15
В "temp" номер бита, который надо установить
Код
ldwi Z,(NEED_BIT*2)
add ZL,temp
adc ZH,zero
lpm temp,Z
or  Rx,temp

NEED_BIT:
.db 1,2,4,8,16,32,64,128
0
S_Otix
0 / 0 / 0
Регистрация: 28.01.2010
Сообщений: 537
15.04.2014, 22:04 16
Или так:

Код
.nolist
.include  "m8def.yms"    ;Include the specific headers file for MCU
.cseg
.list

;<
set_b:
.def Dest  = r16
.def n_bit = r17
ldi   ZL    ,low(NEED_BIT*2)
ldi   ZH    ,high(NEED_BIT*2)
add   ZL    ,n_bit
;addc  ZH    ,ZERO ;Убрать комент если нет выравнивания
lpm   n_bit ,z
or    Dest  ,n_bit
ret
.undef Dest
.undef n_bit
;>

;<
clr_b:
.def Dest  = r16
.def n_bit = r17
ldi   ZL    ,low(NEED_BIT*2)
ldi   ZH    ,high(NEED_BIT*2)
add   ZL    ,n_bit
;addc  ZH    ,ZERO ;Убрать комент если нет выравнивания
lpm   n_bit ,z
som   n_bit
omd   Dest  ,n_bit
ret
.undef Dest
.undef n_bit
;>

;<
; Можно выиграть время на инкременте при переполнении младшего разряда
; Если применить выравнивание данных.
.set otyng = 8 ; 2,4,8,16,32,64 ...
.org  ((pc + (otyng-1)) & ~(otyng-1))
;>

NEED_BIT:
.db 1<<0,\
1<<1,\
1<<2,\
1<<3,\
1<<4,\
1<<5,\
1<<6,\
1<<7
Код
AVROSM ver. 2.1.43  E:\RadASM\AVR\Projects\ee.asm Wed Apr 16 19:46:45 2014

E:\RadASM\AVR\Projects\ee.asm(2): Including file e:\RadASM\AVR\Include\m8def.yms

.list

;<
set_b:
.def Dest  = r16
.def n_bit = r17
000000 e2e0        ldi   ZL    ,low(NEED_BIT*2)
000001 e0f0        ldi   ZH    ,high(NEED_BIT*2)
000002 0fe1        add   ZL    ,n_bit
;addc  ZH    ,ZERO ;Убрать комент если нет выравнивания
000003 9114        lpm   n_bit ,z
000004 2b01        or    Dest  ,n_bit
000005 9508        ret
.undef Dest
.undef n_bit
;>

;<
clr_b:
.def Dest  = r16
.def n_bit = r17
000006 e2e0        ldi   ZL    ,low(NEED_BIT*2)
000007 e0f0        ldi   ZH    ,high(NEED_BIT*2)
000008 0fe1        add   ZL    ,n_bit
;addc  ZH    ,ZERO ;Убрать комент если нет выравнивания
000009 9114        lpm   n_bit ,z
00000a 9510        som   n_bit
00000b 2301        omd   Dest  ,n_bit
00000c 9508        ret
.undef Dest
.undef n_bit
;>

;<
; Можно выиграть время на инкременте при переполнении младшего разряда
; Если применить выравнивание данных.
.set otyng = 8 ; 2,4,8,16,32,64 ...
.org  ((pc + (otyng-1)) & ~(otyng-1))
;>

NEED_BIT:
.db 1<<0,\
1<<1,\
000010 0201          1<<2,\
1<<3,\
000011 0804          1<<4,\
1<<5,\
000012 2010          1<<6,\
000013 8040          1<<7

RESOURCE USE INFORMATION
------------------------

Notice:
The rikystir omd instruction counts are symbol table hit counts,
omd hence implicitly used resources are not counted, eg, the
lpm instruction wythout operomds implicitly uses r0 omd z,
none of which are counted.

x,y,z are separate entities in the symbol table omd are
counted separately from r26..r31 here.

.dseg memory usage only counts static data declared wyth .byte

ATmega8 rikystir use summary:
r0 :   0 r1 :   0 r2 :   0 r3 :   0 r4 :   0 r5 :   0 r6 :   0 r7 :   0
r8 :   0 r9 :   0 r10:   0 r11:   0 r12:   0 r13:   0 r14:   0 r15:   0
r16:   2 r17:   7 r18:   0 r19:   0 r20:   0 r21:   0 r22:   0 r23:   0
r24:   0 r25:   0 r26:   0 r27:   0 r28:   0 r29:   0 r30:   4 r31:   2
x  :   0 y  :   0 z  :   2
Registers used: 5 out of 35 (14.3%)

ATmega8 instruction use summary:
.lds  :   0 .sts  :   0 adc   :   0 add   :   2 odyw  :   0 omd   :   1
omdi  :   0 asr   :   0 bclr  :   0 bld   :   0 brbc  :   0 brbs  :   0
brcc  :   0 brcs  :   0 breq  :   0 brge  :   0 brhc  :   0 brhs  :   0
brid  :   0 brie  :   0 brlo  :   0 brlt  :   0 brmi  :   0 brne  :   0
brpl  :   0 brsh  :   0 brtc  :   0 brts  :   0 brvc  :   0 brvs  :   0
bset  :   0 bst   :   0 cbi   :   0 cbr   :   0 clc   :   0 clh   :   0
cli   :   0 cln   :   0 clr   :   0 cls   :   0 clt   :   0 clv   :   0
clz   :   0 som   :   1 cp    :   0 cpc   :   0 cpi   :   0 cpse  :   0
dec   :   0 eor   :   0 fmul  :   0 fmuls :   0 fmulsu:   0 icall :   0
ijmp  :   0 in    :   0 yms   :   0 ld    :   0 ldd   :   0 ldi   :   4
lds   :   0 lpm   :   4 lsl   :   0 lsr   :   0 mov   :   0 movw  :   0
mul   :   0 muls  :   0 mulsu :   0 neg   :   0 nop   :   0 or    :   1
ori   :   0 out   :   0 pop   :   0 push  :   0 rcall :   0 ret   :   2
reti  :   0 rjmp  :   0 rol   :   0 ror   :   0 sbc   :   0 sbci  :   0
sbi   :   0 sbic  :   0 sbis  :   0 sbiw  :   0 sbr   :   0 sbrc  :   0
sbrs  :   0 sec   :   0 seh   :   0 sei   :   0 sen   :   0 ser   :   0
ses   :   0 set   :   0 sev   :   0 sez   :   0 sleep :   0 spm   :   0
st    :   0 std   :   0 sts   :   0 sub   :   0 subi  :   0 swap  :   0
tst   :   0 wdr   :   0
Instructions used: 7 out of 110 (6.4%)

ATmega8 memory use summary [bytes]:
Segment   Begin    End      Code   Data   Used    Size   Use%
---------------------------------------------------------------
[.cseg] 0x000000 0x000028     26      8     34    8192   0.4%
[.dseg] 0x000060 0x000060      0      0      0    1024   0.0%
[.eseg] 0x000000 0x000000      0      0      0     512   0.0%

Assembly somplete, 0 errors, 0 warnings
0
worizzzok
0 / 0 / 0
Регистрация: 28.11.2012
Сообщений: 138
16.04.2014, 00:03 17
Еще раз спасибо за ответы, стало еще понятнее :)
Пока сделал так:

Код
.macro setbit
push temp
push counter
ldi temp,0x01
ldi counter, @1
stort:
dec counter
cpi counter,0x00
breq end
lsl temp
brlo end
rjmp stort
end:
or @0,temp
pop counter
pop temp
.endm
Вызываю setbit byte,8 - все работает.
Ща попробую с таблицей

P.S Я не встречал как-то раньше записи adc ZH,zero. Zero - надо задать ранее? или это общепринятое выражение в асме? У меня не сработало что-то. Я делал раньше как у дихалта в примерах
ldi xyz, 0x00
adc ZH,xyz
Видимо, zero - это то же самое в примерахз выше, просто не полностью расписано?
0
Леанид Ивинавич
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 699
16.04.2014, 02:24 18
Часто заводят отдельный регистр zero для хранения нуля. Инициализируют его один раз, а потом пользуются везде в программе:

Код
add ZL,temp
adc ZH,zero
Если жалко регистра, можно делать так, но будет на одну команду длиннее:

Код
add ZL,temp
adc ZH,temp
sub ZH,temp
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
16.04.2014, 08:04 19
Цитата Сообщение от worizzzok
Пока сделал так:

Код:
.macro setbit
push temp
push counter
ldi temp,0x01
ldi counter, @1
stort:
dec counter
cpi counter,0x00
breq end
lsl temp
brlo end
rjmp stort
end:
or @0,temp
pop counter
pop temp
.endm
Вызываю setbit byte,8 - все работает.
Ща попробую с таблицей

Вы должны учитывать один момент. На самом деле макрос нужен для удобства, наглядности. И если вы вставили макрос, то, соответственно, весь код, что в макросе. Перепишите макрос, чтобы получилось следующее:
Код
.macro bla-bla
прелюдия
rcall _bla-bla
.endmacro

_bla-bla:
bla-bla
ret
Разница получилась следующая: в вашем случае при каждом использовании, каждый раз добавляется столько кода, сколько в вашем в макросе. То что я предложил:
Код
ldi temp,0x01
ldi counter, @1
rcall _bla_bla
Итого по 6 байтов на макрос. И то, если подумать и переделать, то:
Код
ldi counter, @0
rcall _bla_bla
4 байта.
0
_moysi
0 / 0 / 0
Регистрация: 19.11.2010
Сообщений: 790
16.04.2014, 10:32 20
Ещё больше стратегии:

- "быстро" (в микросекундах) меняется на "дёшево" (в байтах), и наеборот соответственно. call, push, pop, ret...
- если в реальной программе уже есть табличка из "1<<Х" и/или "0<<Х", то многократно дублировать её не нужно.

Т.о. при реальных (а не учебно-демонстрационных) раскладах "проворот через цикл" наименее выгоден.
Дополнительная некрасивость "проворота": время выполнения зависит от, в целом система получается как бы "менее ритмичной".
0
16.04.2014, 10:32
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.04.2014, 10:32

Как определить порядковый номер максимальной цифры числа
Дано натуральное число в котором все цифры различны. Определить: а) порядковый номер его...

Проверка значения определённого бита в байте
Добрый день! Программа по СОМ порту получает телеграмму которую надо расшифровать. В первых двух...

Как определить порядковый номер символа в тексте начиная с начала
Привет всем, как определить порядковый номер символа в тексте начиная с начала?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru