|
Какова логика работы компилятора Atmel studio |
|
|
|
Mar 31 2018, 15:07
|
Группа: Участник
Сообщений: 14
Регистрация: 22-02-18
Пользователь №: 101 921

|
Добрый день!!! Решил вот опробовать Atmel studio 7. Столкнулся со следующими странностями: Если в поле условия оператора if вставить любую логическую операцию, то компилятор отказывается выполнять её и просто пропускает. Если к примеру выполню необходимую операцию, запишу в переменную и переменную вставлю в поле условия, то работает как надо. Раньше писал код в Code Vision? там так делать можно было. Можно ли в студии так делать или прийдется каждый раз использовать промежуточную переменную? Написал простой код для примера: Код #define F_CPU 8000000 #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h>
unsigned char r;
int main(void) { DDRB=0b11111111; PORTB=0b00000000; DDRC=0b00000000; PORTC=0b00000001; DDRD=0b00000000; PORTD=0b00000000; ACSR=0x80; //------------------------------------------------ while (1) { if(~(PINC|0b11111110)) //если bit 0 порта С равен нулю, то выполнить условие { PORTB=0xFF; } r=(~(PINC|0b11111110)); } } Дизасемблер показывает: Код 00000013 CLR R1 Clear Register 00000014 OUT 0x3F,R1 Out to I/O location 00000015 LDI R28,0x5F Load immediate 00000016 LDI R29,0x04 Load immediate 00000017 OUT 0x3E,R29 Out to I/O location 00000018 OUT 0x3D,R28 Out to I/O location --- No source file ------------------------------------------------------------- 00000019 LDI R18,0x00 Load immediate 0000001A LDI R26,0x60 Load immediate 0000001B LDI R27,0x00 Load immediate 0000001C RJMP PC+0x0002 Relative jump 0000001D ST X+,R1 Store indirect and postincrement 0000001E CPI R26,0x61 Compare with immediate 0000001F CPC R27,R18 Compare with carry 00000020 BRNE PC-0x03 Branch if not equal 00000021 RCALL PC+0x0003 Relative call subroutine 00000022 RJMP PC+0x0015 Relative jump 00000023 RJMP PC-0x0023 Relative jump --- C:\STUDIOmk\transmitter\transmitter\Debug/.././main.c ---------------------- { DDRB=0b11111111; 00000024 SER R24 Set Register 00000025 OUT 0x17,R24 Out to I/O location PORTB=0b00000000; 00000026 OUT 0x18,R1 Out to I/O location DDRC=0b00000000; 00000027 OUT 0x14,R1 Out to I/O location PORTC=0b00000001; 00000028 LDI R24,0x01 Load immediate 00000029 OUT 0x15,R24 Out to I/O location DDRD=0b00000000; 0000002A OUT 0x11,R1 Out to I/O location PORTD=0b00000000; 0000002B OUT 0x12,R1 Out to I/O location ACSR=0x80; 0000002C LDI R24,0x80 Load immediate 0000002D OUT 0x08,R24 Out to I/O location PORTB=0xFF; 0000002E SER R25 Set Register if(~(PINC|0b11111110)) //если bit 0 порта С равен нулю, то выполнить условие 0000002F IN R24,0x13 In from I/O location а PORTB=0xFF; 00000030 OUT 0x18,R25 Out to I/O location r=(~(PINC|0b11111110)); 00000031 IN R24,0x13 In from I/O location 00000032 ORI R24,0xFE Logical OR with immediate 00000033 COM R24 One's complement 00000034 STS 0x0060,R24 Store direct to data space 00000036 RJMP PC-0x0007 Relative jump --- No source file ------------------------------------------------------------- 00000037 CLI Global Interrupt Disable 00000038 RJMP PC-0x0000 Relative jump
|
|
|
|
|
Mar 31 2018, 17:20
|
Местный
  
Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846

|
Цитата(mozg12342 @ Mar 31 2018, 18:07)  Код if(~(PINC|0b11111110)) //если bit 0 порта С равен нулю, то выполнить условие Для проверки бита нужно использовать оператор "логическое И" (&). А для логического отрицания - оператор "!". В вашем исполнении условие всегда истинно, поэтому компилятор его выкидывает.
--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
|
|
|
|
|
Mar 31 2018, 22:32
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Цитата(mozg12342 @ Mar 31 2018, 17:07)  Можно ли в студии так делать или прийдется каждый раз использовать промежуточную переменную? Причина не в переменной. По стандарту языка компилятор перед выполнением операции расширяет байт до целого нулями. Которые после инвертирования превращаются в "непредвиденные" единицы.
|
|
|
|
|
Apr 1 2018, 12:33
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(dimka76 @ Mar 31 2018, 22:54)  Код if( (PINC & (1 << 0)) == 0 ) //если bit 0 порта С равен нулю, то выполнить условие Код if( (PINC & 0x01) ^ 0x01 ) . . . //если bit 0 порта С равен нулю, то выполнить условие Код if( (PINC & 0x10) ^ 0x10 ) . . . //если bit 7 порта С равен нулю, то выполнить условие //если bit 7 bit 4 порта С равен нулю, то выполнить условие Код #define IS_BIT_NULL(PORT, BIT_MASK) ( (PORT & BIT_MASK) ^ BIT_MASK )
|
|
|
|
|
Apr 1 2018, 14:33
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(adnega @ Apr 1 2018, 17:30)  может, маска "bit 7" равна 0x80 ? Вах ! подловили "двоечника"  Цитата . . . Зачем себя путать, отказываясь от (((PINC >> n) & 1) == 0/1) ? Когда надо "просчитать" несколько битов сразу (в одном условии), использовать сдвиг можно, но менее компактно. IMHO. Если маски изначально забиты в виде имен-макросов, то ошибки маловероятны. ps для проверки одного бита на 1 достаточно if( PINC & ONE_BIT_MASK ) . . . . . на 0 if( ~PINC & ONE_BIT_MASK ) . . . . . естественно, эти выражения несовместимы с лог. операторами && итд.
|
|
|
|
|
Apr 1 2018, 14:45
|
Группа: Участник
Сообщений: 14
Регистрация: 22-02-18
Пользователь №: 101 921

|
Цитата(Harvester @ Mar 31 2018, 18:20)  Для проверки бита нужно использовать оператор "логическое И" (&). А для логического отрицания - оператор "!". В вашем исполнении условие всегда истинно, поэтому компилятор его выкидывает. Моя логика такая: если бит 0 порта С равен еденице, то 0b00000001 поразрядное или 0b11111110 __________ 0b11111111 поразрядное отрицание __________ 0b00000000 если бит 0 порта С равен нулю то 0b00000000 поразрядное или 0b11111110 __________ 0b11111110 поразрядное отрицание __________ 0b00000001
Сообщение отредактировал mozg12342 - Apr 1 2018, 15:04
|
|
|
|
|
Apr 1 2018, 14:50
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(k155la3 @ Apr 1 2018, 17:33)  Вах ! подловили "двоечника"  Ага. В пределах байта это сразу бросилось в глаза, а вот в 32 битной маске уже без листочка и ручки не смогу. Цитата(k155la3 @ Apr 1 2018, 17:33)  Когда надо "просчитать" несколько битов сразу (в одном условии), использовать сдвиг можно, но менее компактно. IMHO. В боевом коде выглядит довольно компактно и понятно Код if(TIM3->SR & (1 << TIM_SR_CC1IIF)) Конечно же никаких магический чисел быть не должно. Цитата(k155la3 @ Apr 1 2018, 17:33)  Если маски изначально забиты в виде имен-макросов, то ошибки маловероятны. Я везде использую не маски, а номера битов. Да, в условиях появляется лишние (1 <<, зато инициализация удобная Код TIM3->CCMR1 = 0 | (OC_MODE_PWM1 << TIM_CCMR1_OC1M) | (OC_MODE_PWM1 << TIM_CCMR1_OC2M); TIM3->CCER = (1 << TIM_CCER_CC1E); TIM3->DIER = 0 | (1 << TIM_DIER_CC1IE) | (0 << TIM_DIER_CC2IE) | (1 << TIM_DIER_UIE);
|
|
|
|
|
Apr 1 2018, 14:53
|
Группа: Участник
Сообщений: 14
Регистрация: 22-02-18
Пользователь №: 101 921

|
Цитата(dimka76 @ Mar 31 2018, 20:54)  Код if( (PINC & (1 << 0)) == 0 ) //если bit 0 порта С равен нулю, то выполнить условие Прекрасно!!! эта комбинация работает!, ровно как и комбинация if(~PINC&(1<<0)). А я видимо немного на мудрил. Хотя по логике и на бумаге вроде все верно Спасибо!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|