Цитата(SasaVitebsk @ Jul 22 2007, 22:17)

Если хотите говорить строго, то или будьте точны или не будьте так категоричны.

Давайте договоримся: прежде, чем указывать мне на то, что я должен быть точен - как минимум сами делайте то, что делаю я - проверяйте достоверность своих утверждений.
Цитата(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-ка.
Ой как долго можно такой глюк ловить