Перейти к содержанию

Язык СИ для микроконтроллеров


Рекомендуемые сообщения

Это слово говорит компилятору, что переменная может внезапно измениться.
Во-первых, это не "слово", а квалификатор, старайтесь выражаться техническим языком. А во вторых, он запрещает компилятору выполнять какие-либо оптимизации с этим объектом.

По этому без него :

цикл становился бесконечным, потому что он даже и не хотел смотреть на условие в while.

Почитайте, тут более подробно всё расписано - http://www.pic24.ru/...le_for_chainiks

Вообще, достаточно было вбить в поисковик "volatile", и сразу же вылезает куча ссылок с описанием.

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Это слово говорит компилятору, что переменная может внезапно измениться.
Во-первых, это не "слово", а квалификатор, старайтесь выражаться техническим языком. А во вторых, он запрещает компилятору выполнять какие-либо оптимизации с этим объектом.

По этому без него :

цикл становился бесконечным, потому что он даже и не хотел смотреть на условие в while.

Почитайте - http://www.pic24.ru/doku.php/osa/articles/volatile_for_chainiks

https://msdn.microsoft.com/ru-ru/library/2e6a4at9.aspx

Volatile - это ключевое слово, как и было мною написано несколькими постами выше.

На счет оптимизации, почитал, согласен.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

квалификатор volatile вообщето говорит компилятору о том, что переменная связана с периферийным модулем и может изменяться независимо (асинхронно). То есть, если в обычной ситуации компилятор просто копирует переменную в регистр и оттуда ее юзает все время с одним и тем же значением (в пределах блока), то квалификатор volatile при любом обращении к имени этой переменной заставляет компилятор вставлять в код повторное чтение этой переменной. Поэтому ваш код и заработал правильно собственно говоря.

подобные эффекты наблюдаются кстати в самых экзотических ситуациях. К примеру в современнейшем контроллере STM32 в библиотеке HAL модуля UART не все флаги волатильны, и это вызывает порой весьма трудно вылавливаемые глюки на колбэках.

у переменных с квалификатором volatile есть еще одно свойство. Если программа и железка одновременно пытаются изменить значение этой переменной, то победит железяка.

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

Особенности хранения литиевых аккумуляторов и батареек

Потеря емкости аккумулятора напрямую зависит от условий хранения и эксплуатации. При неправильном хранении даже самый лучший литиевый источник тока с превосходными характеристиками может не оправдать ожиданий. Технология, основанная на рекомендациях таких известных производителей литиевых источников тока, как компании FANSO и EVE Energy, поможет организовать правильный процесс хранения батареек и аккумуляторов. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

квалификатор volatile вообщето говорит компилятору о том, что переменная связана с периферийным модулем и может изменяться независимо (асинхронно). То есть, если в обычной ситуации компилятор просто копирует переменную в регистр и оттуда ее юзает все время с одним и тем же значением (в пределах блока), то квалификатор volatile при любом обращении к имени этой переменной заставляет компилятор вставлять в код повторное чтение этой переменной. Поэтому ваш код и заработал правильно собственно говоря.

Ну вот именно про это я и сказал в своём сообщении #1224. Может не техническим языком в некоторых местах, но мысли ведь были провальными?

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

у переменных с квалификатором volatile есть еще одно свойство. Если программа и железка одновременно пытаются изменить значение этой переменной, то победит железяка.

Совершенно не понятно, о каких соревнованиях Вы говорите, и причём тут volatile. Приведите пример.

Что-то мне подсказывает, что Вы путаете это всё дело с атомарным доступом. volatile не гарантирует атомарного доступа к переменным, он просто запрещает самовольничать оптимизатору. Не путайте всё это дело.

А при доступе к объекту несколькими потоками, победит не конкретно кто-то, а последний изменивший его.

Ссылка на комментарий
Поделиться на другие сайты

if ((flag&(1<<PREVSTATE))==(flag&(1<<stateIR)))

На момент исполнения команды flag имеет значение 0x07, но почему-то компилятор шагает сразу на else...

Почему?

PREVSTATE - второй бит, stateIR - нулевой.

Изменено пользователем Tokes
Ссылка на комментарий
Поделиться на другие сайты

Вообще не пойму. А если оба флага нулевые - получиться конструкция "если ноль AND ноль" ?

А вообще работает, как необходимо, да, спасибо. Можно разжевать что тут происходит?

Ссылка на комментарий
Поделиться на другие сайты

конструкция выполняется если выражение истинно(истинно не значит равно единице, внимательно вдумайтесь).

Изменено пользователем Viktor26

Не знаеш как? Спроси у Google'а !!!

Ссылка на комментарий
Поделиться на другие сайты

Вообще не пойму. А если оба флага нулевые

вы не флаги сравниваете, а переменные

первая 0b00000100

вторая 0b00000001

как по вашему они равны?

применяя && вы сравниваете биты

0b00000100 = true

0b00000001 = true

true == true = 1

Ссылка на комментарий
Поделиться на другие сайты

Понял, а я думал, что выражение

(flag&(1<<PREVSTATE))

в скобках уже даёт true or false. Понял, спасибо большое ещё раз!

Да, а вот если оба будут 0b00000000 = это же false. А false && false даст true?

Изменено пользователем Tokes
Ссылка на комментарий
Поделиться на другие сайты

опишите переменную flag как структуру битовых полей и пользуйтесь ее битами на прямую....

А как это сделать в Atmel studio 6.2?

Помогите пожалуйста оптимизировать следующую конструкцию:

unsigned char flag, a, b;
#define PREVSTATE 2
#define stateIR 0

int main(void){
   while(1){    
flag=PINB;
a=0;
b=0;
if ((flag&(1<<PREVSTATE))>0)
a=1;
if ((flag&(1<<stateIR))>0)
b=1;

if (a==
PORTB|=0b00000001;
else
PORTB|=0b00000010; 
   }
}

И если есть что почитать на тему "как не разбазаривать целый байт под одно значение true or false в СИ для контроллеров в Atmel Studio" - подскажите где.

Ссылка на комментарий
Поделиться на другие сайты

struct bitfield{
 char bit_0 :1;
 char bit_1 :1;
 char bit_2 :1;
 char bit_3 :1;
 char high :4;
};

Оптимизировать? Убрать сравнение или заменить по рецепту Виктора

if( flag & (1<<PREVSTATE) )
if( (flag & (1<<PREVSTATE)) != 0 )

Для Си разницы нет, true это любое ненулевое число.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

То есть 1 байт под 1 - 8 переменных, в зависимости от их размера. В моем примере 4 однобайтных и 1 четырехбайтная. Вот только avr-gcc с ними плохо умеет работать, с битовыми масками гораздо лучше.

union un{
char byte;
struct{
 char b0:1;
 char b1:1;
 char b2:1;
 char b3:1;
 char bh:4;
}b;
};
1) st.b.b3 = st.b.b0;
2) if(st.byte & (1<<0)) st.byte |= (1<<3); else st.byte &=~(1<<3);

Первое разворачивается в битовую магию

  st.b.b3 = st.b.b0;
 3c:    98 2f	       mov    r25, r24
 3e:    97 95	       ror    r25
 40:    99 27	       eor    r25, r25
 42:    97 95	       ror    r25
 44:    99 0f	       add    r25, r25
 46:    99 0b	       sbc    r25, r25
 48:    90 fb	       bst    r25, 0
 4a:    83 f9	       bld    r24, 3

Второе в прыжки

  if(st.byte & (1<<0)) st.byte |= (1<<3); else st.byte &=~(1<<3);
 4c:    80 ff	       sbrs    r24, 0
 4e:    02 c0	       rjmp    .+4	      ; 0x54 <__SREG__+0x15>
 50:    88 60	       ori    r24, 0x08    ; 8
 52:    01 c0	       rjmp    .+2	      ; 0x56 <__SREG__+0x17>
 54:    87 7f	       andi    r24, 0xF7    ; 247

Когда для этого достаточно

BST r24,0
BLD r24,3

Вот только avr-gcc об этих инструкциях не знает :-(

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

наверное поэтому в библиотеках я еще не встречал использование битфиелдов. Проще задефэйнить однобайтовый тип (для удобства чтения) и набор масок к нему. И местами это окажется очень даже удобно и привычно. А битфиелды считаю просто модный фЕтиш для экономистов на спичках

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

Помогите пожалуйста оптимизировать следующую конструкцию:

unsigned char flag, a, b;
#define PREVSTATE 2
#define stateIR 0

int main(void){
while(1)
{
  flag=PINB;
  switch (flag&((1<<PREVSTATE)|(1<<stateIR))) {
   case 0:
   case (1<<PREVSTATE)|(1<<stateIR):
     PORTB|=0b00000001;
   break;
   default:
     PORTB|=0b00000010;
}
}

union un{
char byte;
struct{
char b0:1;
char b1:1;
char b2:1;
char b3:1;
char bh:4;
}b;
};
1) st.b.b3 = st.b.b0;
2) if(st.byte & (1<<0)) st.byte |= (1<<3); else st.byte &=~(1<<3);

Первое разворачивается в битовую магию

Второе в прыжки

а это?

st.b.b3=0;
if(st.b.b0) st.b.b3=1;

Ссылка на комментарий
Поделиться на другие сайты

Нет бы проверить и выложить дизассемблерный код.

Тут он начинает сходить с ума и использовать bst / bld совсем не по делу

  st.b.b3=0;
 3c:    87 7f	       andi    r24, 0xF7    ; 247
 if(st.b.b0)st.b.b3=1;
 3e:    80 ff	       sbrs    r24, 0
 40:    03 c0	       rjmp    .+6	      ; 0x48 <__SREG__+0x9>
 42:    9f ef	       ldi    r25, 0xFF    ; 255
 44:    90 fb	       bst    r25, 0
 46:    83 f9	       bld    r24, 3

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...