реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> bit set, C
i.dmitry
сообщение Jul 22 2007, 09:14
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 35
Регистрация: 8-07-07
Пользователь №: 28 963



Правильно ли я понял:
1)
Код
TIMSK = (1 << OCIE2);

2)
Код
TIMSK |= (1 << OCIE2);

----------
В первом случае установится только бит OCIE2, остальные будут нулями.
Во втором случае все биты кроме OCIE2 останотся неизменными, а этот бит станет единицей.
----------
Правильно?

-dmitry.
Go to the top of the page
 
+Quote Post
alux
сообщение Jul 22 2007, 09:54
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Совершенно верно.
В апноте avr035 все подробно описано.

http://www.gaw.ru/html.cgi/txt/app/micros/avr/AVR035.htm
даже русским языком написано.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 22 2007, 18:40
Сообщение #3


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(i.dmitry @ Jul 22 2007, 12:14) *
Во втором случае все биты кроме OCIE2 останотся неизменными, а этот бит станет единицей.
Если строго, то не "останутся неизменными", а "в них запишется то, что из них прочиталось".
Обычно это одно и то же. Но в регистрах, где есть биты, сбрасываемые записью "1", при такой операции эти биты будут сброшены.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
_artem_
сообщение Jul 22 2007, 19:03
Сообщение #4


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



в iar mожно еще так :

PORTA_Bit4 = 1;


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
AndreyKeil
сообщение Jul 22 2007, 19:21
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 96
Регистрация: 16-11-05
Из: г.Екатеринбург
Пользователь №: 10 930



Все станет ясно, если посмотреть дизассемблер.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 22 2007, 19:45
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(_artem_ @ Jul 22 2007, 22:03) *
в iar mожно еще так :
PORTA_Bit4 = 1;

Не стоит пользоваться. Крайне сомнительное расширение sad.gif, ибо:
1. Не переносима;
2. Неявное чтение может либо просто быть лишним, либо даже вредным, если из регистра не читается записанное значение, либо регистр содержит зарезервированные биты, либо операция чтения имеет побочные эффекты.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 22 2007, 19:52
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Вообще говоря результат действия 1 << OCIE2 зависит от того, какое число сопоставлено символьному имени OCIE2. Выражение вида "1<<x" означает "сдвинуть число 1 на x разрядов влево", т.е. в сторону старших разрядов. Справа (в младший разряд) при таком сдвиге дописывается нуль.
Насколько я понимаю OCIE2 это седьмой (если счет от нуля) бит в регистре TIMSK. Если имени OCIE2 сопоставлено число 7
Код
#define OCIE2 7

то результат операции
Код
TIMSK |= (1<<OCIE2);

что эквивалентно
Код
TIMSK = TIMSK |(1<<OCIE2);

а макроподстановка даст выражение
Код
TIMSK = TIMSK|(1<<7);

будет верным - в регистре TIMSK будет установлен седьмой бит (счет от нуля).
Если же символьному имени OCIE2 сопоставлена битовая маска регистра TIMSK (что чаще всего и используют в хидерах компиляторов)
Код
#define OCIE2 0x80

то результат будет неадекватным. Т.к. в результате макроподставноки получится выражение
Код
TIMSK = TIMSK|(1<<128);

которое будет означать "совершить операцию побитного сложения содержимого регистра TIMSK с числом 1, сдвинутым влево на 128 бит (0x80=128), и записать результат в TIMSK".
Так что i.dmitry перед использованием символьного обозначения убедитесь в его значении!
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jul 22 2007, 20:17
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(ReAl @ Jul 22 2007, 21:40) *
Если строго, то не "останутся неизменными", а "в них запишется то, что из них прочиталось".
Обычно это одно и то же. Но в регистрах, где есть биты, сбрасываемые записью "1", при такой операции эти биты будут сброшены.


Если хотите говорить строго, то или будьте точны или не будьте так категоричны. smile.gif
Сказанное Вами правильно при работе с регистрами на которые не распространяются команды SBI, CBI (в частности регистра TIMSK). И возможно, это справедливо для некоторых компиляторов. Скажем команда
PORTA |= (1<<5);
компилятором IAR компильнётся в
SBI PORTA,5
что, очевидно, не затронет остальные биты.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Jul 22 2007, 21:30
Сообщение #9


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(SasaVitebsk @ Jul 22 2007, 20:17) *
Сказанное Вами правильно при работе с регистрами на которые не распространяются команды SBI, CBI (в частности регистра TIMSK). И возможно, это справедливо для некоторых компиляторов. Скажем команда PORTA |= (1<<5); компилятором IAR компильнётся в SBI PORTA,5 что, очевидно, не затронет остальные биты.

Известно, что для аврок нового поколения команда sbi pinb,1 изменяет состояние пина на противоположное.

Отсюда вопрос, как сказать такое си компилятору? Должно быть что-то типа PINB |= (1<<1); или я не прав?


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 22 2007, 21:45
Сообщение #10


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(=GM= @ Jul 23 2007, 00:30) *
Известно, что для аврок нового поколения команда sbi pinb,1 изменяет состояние пина на противоположное.

Что за AVRки нового поколения? укажите хотя бы модель мк, в котором вы такое видели.

PINB это входной порт вообще-то..
команда SBI - сокращение от Set Bit IO (она по идее не может делать CLR, она только SET)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 22 2007, 22:07
Сообщение #11


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(SasaVitebsk @ Jul 22 2007, 22:17) *
Если хотите говорить строго, то или будьте точны или не будьте так категоричны. smile.gif
Давайте договоримся: прежде, чем указывать мне на то, что я должен быть точен - как минимум сами делайте то, что делаю я - проверяйте достоверность своих утверждений.

Цитата(SasaVitebsk @ Jul 22 2007, 22:17) *
Сказанное Вами правильно при работе с регистрами на которые не распространяются команды SBI, CBI (в частности регистра TIMSK). И возможно, это справедливо для некоторых компиляторов. Скажем команда
PORTA |= (1<<5);
компилятором IAR компильнётся в
SBI PORTA,5
что, очевидно, не затронет остальные биты.
Блажен, кто верует. Продолжайте дальше в том же духе, только не тащите в свою веру остальных.
Не "не затронет", а "запишет в них то, что в них было". Для PORTA эти два утверждения эквивалентны, а вот для ACSR...

Пишем маленькую функцию (тут atmega64, но на atmega8515 это тоже проверялось в железе):
Код
#define AC_MINUS E,3,L
void sbi_test(void)
{
    dbg_putstr_P(dbg_always, PSTR("SBI RMW behavior test\n"));
    DRIVER(AC_MINUS,OUT);
    OFF(AC_MINUS);
    ACSR = _BV(ACBG);
    _delay_us(100); // let bandgup on
    ACSR |= _BV(ACI); // clr interrupt flag
    dbg_printf_P(dbg_always, PSTR("Initial ACSR = 0x%02X\n"), ACSR);
    ON(AC_MINUS);
    _delay_us(2); // AC propagation delay
    dbg_printf_P(dbg_always, PSTR("AC- toggled, ACSR = 0x%02X\n"), ACSR);
    ACSR |= _BV(ACIE);
    dbg_printf_P(dbg_always, PSTR("ACSR |= _BV(ACIE),  ACSR = 0x%02X\n"), ACSR);
}

Вот что нагенерил avr-gcc, прошу обратить внимение на на строку для ACSR |= _BV(ACIE), она там старательно выделена.
CODE
00002804 <sbi_test>:
#define AC_MINUS E,3,L
void sbi_test(void)
{
2804: 60 ed ldi r22, 0xD0 ; 208
2806: 72 e0 ldi r23, 0x02 ; 2
2808: 80 e0 ldi r24, 0x00 ; 0
280a: 0e 94 6d 2a call 0x54da ; 0x54da <dbg_putstr_P>
dbg_putstr_P(dbg_always, PSTR("SBI RMW behavior test\n"));
DRIVER(AC_MINUS,OUT);
280e: 13 9a sbi 0x02, 3 ; 2
OFF(AC_MINUS);
2810: 1b 9a sbi 0x03, 3 ; 3
ACSR = _BV(ACBG);
2812: 80 e4 ldi r24, 0x40 ; 64
2814: 88 b9 out 0x08, r24 ; 8
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
2816: 85 ef ldi r24, 0xF5 ; 245
2818: 8a 95 dec r24
281a: f1 f7 brne .-4 ; 0x2818 <sbi_test+0x14>
_delay_us(100); // let bandgup on
ACSR |= _BV(ACI); // clr interrupt flag
281c: 44 9a sbi 0x08, 4 ; 8
dbg_printf_P(dbg_always, PSTR("Initial ACSR = 0x%02X\n"), ACSR);
281e: 88 b1 in r24, 0x08 ; 8
2820: 99 27 eor r25, r25
2822: 9f 93 push r25
2824: 8f 93 push r24
2826: 89 eb ldi r24, 0xB9 ; 185
2828: 92 e0 ldi r25, 0x02 ; 2
282a: 9f 93 push r25
282c: 8f 93 push r24
282e: 1f 92 push r1
2830: 0e 94 d9 29 call 0x53b2 ; 0x53b2 <dbg_printf_P>
ON(AC_MINUS);
2834: 1b 98 cbi 0x03, 3 ; 3
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
2836: 84 e0 ldi r24, 0x04 ; 4
2838: 8a 95 dec r24
283a: f1 f7 brne .-4 ; 0x2838 <sbi_test+0x34>
_delay_us(2); // AC propagation delay
dbg_printf_P(dbg_always, PSTR("AC- toggled, ACSR = 0x%02X\n"), ACSR);
283c: 88 b1 in r24, 0x08 ; 8
283e: 99 27 eor r25, r25
2840: 9f 93 push r25
2842: 8f 93 push r24
2844: 8d e9 ldi r24, 0x9D ; 157
2846: 92 e0 ldi r25, 0x02 ; 2
2848: 9f 93 push r25
284a: 8f 93 push r24
284c: 1f 92 push r1
284e: 0e 94 d9 29 call 0x53b2 ; 0x53b2 <dbg_printf_P>
ACSR |= _BV(ACIE);


2852: 43 9a sbi 0x08, 3 ; 8 <<<================================== SBI !!!


dbg_printf_P(dbg_always, PSTR("ACSR |= _BV(ACIE), ACSR = 0x%02X\n"), ACSR);
2854: 88 b1 in r24, 0x08 ; 8
2856: 99 27 eor r25, r25
2858: 9f 93 push r25
285a: 8f 93 push r24
285c: 8a e7 ldi r24, 0x7A ; 122
285e: 92 e0 ldi r25, 0x02 ; 2
2860: 9f 93 push r25
2862: 8f 93 push r24
2864: 1f 92 push r1
2866: 0e 94 d9 29 call 0x53b2 ; 0x53b2 <dbg_printf_P>
286a: 8d b7 in r24, 0x3d ; 61
286c: 9e b7 in r25, 0x3e ; 62
286e: 0f 96 adiw r24, 0x0f ; 15
2870: 0f b6 in r0, 0x3f ; 63
2872: f8 94 cli
2874: 9e bf out 0x3e, r25 ; 62
2876: 0f be out 0x3f, r0 ; 63
2878: 8d bf out 0x3d, r24 ; 61
287a: 08 95 ret

А вот что получено на терминалке.
Цитата
SBI RMW behavior test
Initial ACSR = 0x40
AC- toggled, ACSR = 0x70
ACSR |= _BV(ACIE), ACSR = 0x68
Т.е. команда SBI не только установила бит 3 (ACIE), но и сбросила бит 4 (ACI).
Если же вместо
ACSR |= _BV(ACIE);
написать
ACSR = (ACSR & ~_BV(ACI)) | _BV(ACIE);
то бит ACIE взводится, но бит ACI не сбрасывается.

Так кто из нас неоправданно категоричен?


Цитата(defunct @ Jul 22 2007, 23:45) *
Что за AVRки нового поколения? укажите хотя бы модель мк, в котором вы такое видели.

PINB это входной порт вообще-то..
команда SBI - сокращение от Set Bit IO (она по идее не может делать CLR, она только SET)
Ой, да для многих уже. Хоть бы atmega48/88/168. Посмотрите для них картинку 10.2 - структуру порта, там триггер в PORT через инвертор может получить своё состояние себе на вход при записи "1" в PIN (элемент И на управление мультиплексором и стробом записи).

=GM=, а вот в свете RMW (Read-Modify-Write) сути команды sbi, см. мой ответ SasaVitebsk, я бы её не использовал с такой целью. Лучше запись PINB = (1 << 1) - так Вы гарантированно запишете 1-ку только в один триггер (а если захотите - то инвертируете группу ног).
Кстати, интересно - проверьте (мне лень макетку с мегой48 доставать). Если SBI и на PIN* себя ведёт так же, как и на ACSR (странно будет, если по-другому) то после SBI PINB,... на порту B переключится на противоположное состояние PULL-UP-ов на тех входах, на которых в этот момент была 1-ка.
Ой как долго можно такой глюк ловить smile.gif


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
CD_Eater
сообщение Jul 22 2007, 23:43
Сообщение #12


Частый гость
**

Группа: Новичок
Сообщений: 173
Регистрация: 3-09-04
Из: Moscow
Пользователь №: 595



Цитата из ДШ мега48
Some of the Status Flags are cleared by writing a logical one to them. Note that, unlike most other AVRs, the CBI and SBI instructions will only operate on the specified bit, and can therefore be used on registers containing such Status Flags. The CBI and SBI instructions work with registers 0x00 to 0x1F only.
И такое поведение команд CBI и SBI свойственно для всех АВРок, начиная с тини13, то есть, все выпущенные за последние 3 года модели. Неужели некоторые уже 3 года не читали даташитов? А вера здесь не при чём.

А атмегу64 и 8515 выбросьте, пожалуйста. Им не место на столе эмбеддера.

Цитата
Посмотрите для них картинку 10.2 - структуру порта, там триггер в PORT через инвертор может получить своё состояние себе на вход при записи "1" в PIN (элемент И на управление мультиплексором и стробом записи).

Цитата
Кстати, интересно - проверьте (мне лень макетку с мегой48 доставать). Если SBI и на PIN* себя ведёт так же, как и на ACSR (странно будет, если по-другому) то после SBI PINB,... на порту B переключится на противоположное состояние PULL-UP-ов на тех входах, на которых в этот момент была 1-ка.
Выход триггера PORT соединён с ножкой микросхемы через повторитель (см. ту самую схему), поэтому внешний потенциал на ножке никак не может повлиять на операции с этим триггером.
В случае, когда ножка работает как вход, то запись 1 в PINB приведёт к инверсии соответствующего бита PORTB. Разница лишь в том, что в режиме выхода этот порт определяет уровень на ножке выхода, а в режиме входа - подтяжку. Поэтому в режиме входа запись единички в PINB будет инвертировать пул-апы. Ничего удивительного. Собственно, это следует из ДШ. Никакого глюка тут нет.

Сообщение отредактировал CD_Eater - Jul 23 2007, 00:10
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 23 2007, 04:32
Сообщение #13


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(CD_Eater @ Jul 23 2007, 01:43) *
Неужели некоторые уже 3 года не читали даташитов?
Да легко. Некоторые вон плохо себе представляют, как и где в С автоматические переменные создаются и что они не есть угрозой для реентрабельности - и ничего, живут и часто их интересно послушать.

Цитата
А атмегу64 и 8515 выбросьте, пожалуйста. Им не место на столе эмбеддера.

Ну с с выбросом меги8515 действительно можно согласиться, пусть даже она самим атмелом в устаревшие не записана, а что с мегой162 будем делать? Ей-то замены пока нет, хоть ей и больше 3 лет.
А почему меге64/128 не место - я не пойму. Личная неприязнь?

Цитата
Поэтому в режиме входа запись единички в PINB будет инвертировать пул-апы. Ничего удивительного. Собственно, это следует из ДШ. Никакого глюка тут нет.
Тут нет, я ещё не настолько туп.
Глюк был бы, если бы SBI для этого кристалла было RMW с байтом. К счастью, этого нет в новых кристаллах. Тем лучше.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
add
сообщение Jul 23 2007, 06:52
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 345
Регистрация: 10-10-05
Пользователь №: 9 459



Цитата
Ну с с выбросом меги8515 действительно можно согласиться,

Цитата
Им не место на столе эмбеддера

Выступлю в защиту м8515! Что вам там в ней не нравится? Нормальный кристал! Ног дофига. Цена приличная для серийки. Ну нету АЦП, не во всех задачах он и нужен!


--------------------
Если задачу можно решить, то не надо тревожиться. А если нельзя решить, то тревожиться бесполезно.
Go to the top of the page
 
+Quote Post
_artem_
сообщение Jul 23 2007, 09:26
Сообщение #15


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



Цитата(zltigo @ Jul 22 2007, 22:45) *
Не стоит пользоваться. Крайне сомнительное расширение sad.gif , ибо:
1. Не переносима;
2. Неявное чтение может либо просто быть лишним, либо даже вредным, если из регистра не читается записанное значение, либо регистр содержит зарезервированные биты, либо операция чтения имеет побочные эффекты.


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

подытоживая три варианта которые я применяю для GPIO:

Код
if(val == 0)
    PORTA &= (~(1<<PA4));
else
    PORTA |= (1<<PA4);


или

PORTA = (PORTA & (~(1<<PA4))) | ((val == 0? 0:1) << PA4 )

или

PORTA_Bit4 = (val == 0? 0:1);


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 15:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01522 секунд с 7
ELECTRONIX ©2004-2016