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

 
 
2 страниц V   1 2 >  
Closed TopicStart new topic
> Какова логика работы компилятора Atmel studio
mozg12342
сообщение Mar 31 2018, 15:07
Сообщение #1





Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
Harvester
сообщение Mar 31 2018, 17:20
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(mozg12342 @ Mar 31 2018, 18:07) *
Код
if(~(PINC|0b11111110))      //если bit 0 порта С равен нулю, то выполнить условие

Для проверки бита нужно использовать оператор "логическое И" (&). А для логического отрицания - оператор "!".
В вашем исполнении условие всегда истинно, поэтому компилятор его выкидывает.


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
k155la3
сообщение Mar 31 2018, 18:51
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



А если внимательно почитать warn, то скорее всего там есть упоминание об это факте.
Go to the top of the page
 
+Quote Post
dimka76
сообщение Mar 31 2018, 19:54
Сообщение #4


developer
****

Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032



Код
if( (PINC & (1 << 0)) == 0 )      //если bit 0 порта С равен нулю, то выполнить условие


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
aiwa
сообщение Mar 31 2018, 22:32
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(mozg12342 @ Mar 31 2018, 17:07) *
Можно ли в студии так делать или прийдется каждый раз использовать промежуточную переменную?

Причина не в переменной. По стандарту языка компилятор перед выполнением операции расширяет байт до целого нулями. Которые после инвертирования превращаются в "непредвиденные" единицы.



Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 1 2018, 07:02
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (aiwa @ Apr 1 2018, 00:32) *
Которые после инвертирования превращаются в "непредвиденные" единицы.
Да там и до расширения после "ИЛИ" единиц хватает.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
k155la3
сообщение Apr 1 2018, 12:33
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 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 )
Go to the top of the page
 
+Quote Post
adnega
сообщение Apr 1 2018, 14:30
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(k155la3 @ Apr 1 2018, 15:33) *
Код
if( (PINC & 0x10) ^ 0x10 ) . . .   //если bit 7 порта С равен нулю, то выполнить условие

может, маска "bit 7" равна 0x80 ?
Зачем себя путать, отказываясь от (((PINC >> n) & 1) == 0/1) ?
Go to the top of the page
 
+Quote Post
k155la3
сообщение Apr 1 2018, 14:33
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(adnega @ Apr 1 2018, 17:30) *
может, маска "bit 7" равна 0x80 ?

Вах ! подловили "двоечника" sm.gif
Цитата
. . . Зачем себя путать, отказываясь от (((PINC >> n) & 1) == 0/1) ?

Когда надо "просчитать" несколько битов сразу (в одном условии), использовать сдвиг можно, но менее компактно. IMHO.
Если маски изначально забиты в виде имен-макросов, то ошибки маловероятны.

ps
для проверки одного бита на 1 достаточно
if( PINC & ONE_BIT_MASK ) . . . . .

на 0
if( ~PINC & ONE_BIT_MASK ) . . . . .

естественно, эти выражения несовместимы с лог. операторами && итд.
Go to the top of the page
 
+Quote Post
mozg12342
сообщение Apr 1 2018, 14:45
Сообщение #10





Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
adnega
сообщение Apr 1 2018, 14:50
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(k155la3 @ Apr 1 2018, 17:33) *
Вах ! подловили "двоечника" sm.gif

Ага. В пределах байта это сразу бросилось в глаза, а вот в 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);
Go to the top of the page
 
+Quote Post
jcxz
сообщение Apr 1 2018, 14:50
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(mozg12342 @ Apr 1 2018, 17:45) *
Моя логика такая:

Прочитайте про типы данных в языке си. И про приведения (расширения) типов.
и про типы операций, что такое "побитовое И", а что такое "побитовое ИЛИ".
Go to the top of the page
 
+Quote Post
adnega
сообщение Apr 1 2018, 14:53
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(mozg12342 @ Apr 1 2018, 17:45) *
поразрядное и

Это называется "или".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Apr 1 2018, 14:53
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(adnega @ Apr 1 2018, 17:50) *
В боевом коде выглядит довольно компактно и понятно
Код
    if(TIM3->SR & (1 << TIM_SR_CC1IIF))

Скобки-то зачем? Приоритет операций никто не отменял.
Go to the top of the page
 
+Quote Post
mozg12342
сообщение Apr 1 2018, 14:53
Сообщение #15





Группа: Участник
Сообщений: 14
Регистрация: 22-02-18
Пользователь №: 101 921



Цитата(dimka76 @ Mar 31 2018, 20:54) *
Код
if( (PINC & (1 << 0)) == 0 )      //если bit 0 порта С равен нулю, то выполнить условие

Прекрасно!!! эта комбинация работает!, ровно как и комбинация if(~PINC&(1<<0)). А я видимо немного на мудрил. Хотя по логике и на бумаге вроде все верно
Спасибо!
Go to the top of the page
 
+Quote Post

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

 


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


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