Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Ключевое слово "Volatile"
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
RollForRepair
Доброго времени суток.

Написал программу в CodeVisionAVR, смотрю изменение значений переменных в Протеусе. Переменные, за которыми я слежу, являлись типом "long int". В какой-то момент я решил сделать их просто int, т.к. значения в проге вполне вписываются и без приставки long. Внезапно в протеусе появляется такая надпись на месте значения переменной - Item (2 bytes at 0xFFFF0504) not within memory block (0x00000460 bytes), и изменилась запись адреса - R-64252:R64251 . При этом программа работает нормально, просто не получается следить за значениями переменных. Вот скриншот.

http://i.imgur.com/0WM63lR.jpg ([img] почему-то не работает, приходится оставлять в виде ссылки)

Погуглив, я нашёл решение данной проблемы - добавить ключевое слово Volatile перед int. Это помогло, но мне хотелось бы разобраться до конца :
  • Что означает запись на месте значения переменной?
  • Почему этой проблемы не было с long int?
  • Что делает слово Volatile в данном случае?
  • Ну и как бонусный вопрос, есть ли способ выводить значения переменных типа float? (у меня это D, U, Uprop ...)


Буду благодарен за помощь.
slavokhire5
вероятнее всего переменная не отображалась в протеусе, т.к. CVAvr ее оптимизировал (убил за ненадобностью) в том месте, где вы ее пытались смотреть. volatile сказал компилятору, что нужно оптимизировать осторожнее sm.gif

100 раз подумайте, перед тем, как использовать в AVR переменные типа float - огромное потребление ресурсов.
Сергей Борщ
Цитата(RollForRepair @ Nov 16 2015, 11:25) *
Погуглив, я нашёл решение данной проблемы - добавить ключевое слово Volatile перед int.
Это лечение симптомов, а не причины. volatile существует для другого. В данном случае оно сделало вашу маленькую быструю программу больше и медленнее.
Цитата(RollForRepair @ Nov 16 2015, 11:25) *
Что означает запись на месте значения переменной?
Никогда не работал с вашим компилятором, но смею предположить, что это означает, что ваша переменная хранится в регистрах, а не в ОЗУ. Поэтому отладчик не может ее отобразить. Убедиться в этом можно, рассмотрев внимательно дизасемблерный код в местах обращения к этой переменной.
Цитата(RollForRepair @ Nov 16 2015, 11:25) *
Почему этой проблемы не было с long int?
Если первое предположение верно, то раньше эта переменная в регистры не помещалась и компилятор был вынужден разместить ее в ОЗУ.
Цитата(RollForRepair @ Nov 16 2015, 11:25) *
Что делает слово Volatile в данном случае?
То же, что и в любом другом случае - говорит компилятору, что значение переменной может измениться в любой момент неизвестным ему образом и что любая запись в эту переменную влияет на "наблюдаемое поведение" программы. Это запрещает оптимизацию обращений к переменной. С этим ключевым словом компилятор обязан выполнить любое действие с этой перемееной именно так и в том порядке, в котором оно описано в программе. Если вы написали a = 1; a++; то компилятор обязан сначала записать в переменную 1, потом прочитать из этой переменной ее содержимое, увеличить его на 1 и записать результат обратно. Он уже не имеет права соптимизировать эти действия и записать в переменную a сразу значение 2, потому что volatile говорит, что во-первых между a=1 и a++ значение a могло измениться (например, если это отраженный на память регистр ввода или между этими действиями произошло прерывание, обработчик которого изменил переменную) и что обе записи могли на что-то влиять (опять же, если это отраженный на память регистр вывода или же между этими выражениями произошло прерывание, которое должно было считать из a первое значение)
Цитата(RollForRepair @ Nov 16 2015, 11:25) *
Ну и как бонусный вопрос, есть ли способ выводить значения переменных типа float?
Это надо искать в документации или спрашивать у службы техподдержки вашего компилятора и отладчика. Вы ведь их честно купили?
RollForRepair
Цитата(Сергей Борщ @ Nov 16 2015, 12:28) *
...

Большое спасибо за подробный ответ!

Цитата(slavokhire5 @ Nov 16 2015, 12:27) *
...100 раз подумайте, перед тем, как использовать в AVR переменные типа float - огромное потребление ресурсов.

А какой тип данных мне использовать, если целочисленным не обойтись? (Мне надо умножить разность целочисленных переменных на коэффициент от 0 до 1, то есть результат будет нецелочисленный)
CrimsonPig
Цитата(RollForRepair @ Nov 16 2015, 10:34) *
А какой тип данных мне использовать, если целочисленным не обойтись? (Мне надо умножить разность целочисленных переменных на коэффициент от 0 до 1, то есть результат будет нецелочисленный)


Fixed point ?
sigmaN
А тут недавно, в соседней ветке, мне вполне аргументированно объяснили, что ежели по быстродействию и объему памяти с плавучкой всё работает, то есть ли смысл мучить себя Fixed point?
И вы знаете, я вынужден был согласиться, хотя и тоже являюсь ярым противником использования float на любых процах без FPU, а уж тем более на AVR.
Так что не заморачивайте новичку голову. Лучше уговорите его слезть пораньше с CodeVisionAVR rolleyes.gif
RollForRepair
Цитата(sigmaN @ Nov 17 2015, 03:16) *
А тут недавно, в соседней ветке, мне вполне аргументированно объяснили, что ежели по быстродействию и объему памяти с плавучкой всё работает, то есть ли смысл мучить себя Fixed point?
И вы знаете, я вынужден был согласиться, хотя и тоже являюсь ярым противником использования float на любых процах без FPU, а уж тем более на AVR.
Так что не заморачивайте новичку голову. Лучше уговорите его слезть пораньше с CodeVisionAVR rolleyes.gif


Ну, я уже начитался плохого про диалектные фишки CVAVR - мол, запись " PORTB.7 = 1; " не сработает на других компиляторах. На что посоветуете перейти? Сейчас я тренируюсь на Atmega8, однако рано или поздно надо будет переходить на PIC, связано с работой. Я думал о переходе на AVR Studio.
sigmaN
Вот именно на скачанную с сайта атмел студию и переходите. Там довольно развитая IDE с отладкой, симулятором и продвинутым редактором кода.
В качестве компилятора для AVR там используется GNU GCC с нормальным, настоящим языком С, а можно и даже С++ использовать при желании.
_Pasha
Цитата(sigmaN @ Nov 17 2015, 03:16) *
А тут недавно, в соседней ветке, мне вполне аргументированно объяснили, что ежели по быстродействию и объему памяти с плавучкой всё работает, то есть ли смысл мучить себя Fixed point?
И вы знаете, я вынужден был согласиться, хотя и тоже являюсь ярым противником использования float на любых процах без FPU, а уж тем более на AVR.
Так что не заморачивайте новичку голову. Лучше уговорите его слезть пораньше с CodeVisionAVR rolleyes.gif

поддержу.
1. выдираем плавучую часть алгоритма.
2. запускаем симулятор
3. энджой.


Цитата(RollForRepair @ Nov 17 2015, 16:01) *
Ну, я уже начитался плохого про диалектные фишки CVAVR - мол, запись " PORTB.7 = 1; " не сработает на других компиляторах. На что посоветуете перейти? Сейчас я тренируюсь на Atmega8, однако рано или поздно надо будет переходить на PIC, связано с работой. Я думал о переходе на AVR Studio.

можете не блуждать в поисках а написать "диалектную" прокладку, - выделить для себя любимое подмножество фич и добиться его работы на разных компиляторах и разных архитектурах: CV, IAR, GCC, (xc8/16 раз уж на пиках потом будете)
и ничего страшного, если более элегантное PORTB.7 = 1; заменится на горбатенькое, но рабочее и переносимое #define set_bit(port,bit,value) тратата
sigmaN
Всяко можно сделать переносимый на все три или сколько там их есть компилятора код.
Но мне кажется новичку лучше начинать со стандартных нормальных сей и потом уже разбираться с причудами остальных компиляторов если того потребует его проект.
Я например за всю жизнь ни разу не столкнулся с необходимостью вникать в диалект кодэвижнАВР. А вот знание Си необходимо постоянно, на какие бы я камни не пересаживался.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.