Неправильное поведение контроллера с переменной в глобальной области видимости
- Войдите на сайт для отправки комментариев
Добрый день.
Сразу говорю, что код выкладывать не буду. Если только кусками.
Суть проблемы: Я задаю переменную в глобальной области видимости. Потом инкрементирую её в функции вызванной по внешнему прерыванию. Она становиться равной 3 (условно). Потом я сравниваю её во втором внешнем прерывании и она становиться равной -1. Происходит это конкретно в момент вызова второго внешнего прерывания. (До момента обращения к переменной). После выхода из второго прерывания переменная по прежнему равна -1 и ей снова можно инкрементировать, но от -1. Вот такой странный ресет переменной.
Условия.
Среда: Arduino IDE 1.6.11
Плата: MEGA 2560
P.S. Бился над задачей около двух недель. В самом начале переменная ещё просто обнулялась. Но я уже менял во всем скетче типы переменных. И много чего делал.
Выход я конечно придумал. Для работы со значением во втором прерывании я делаю дополнительную переменную в которой передаю значение. Но считаю это решение костылём.
Моё мнение. Компилятор не правильно задаёт область видимости переменной и во втором прерывании не позволяет прочесть значение переменной, а инрементирует его заново. И потом возвращает его переменной как истинное.
Конечно, может это особенность архитектуры AVR, не позволять двум прерываниям работать с одной переменной.
Я прошу совета ГУГУ С++
Сразу говорю, что код выкладывать не буду. Если только кусками.
сразу говорю - иди впень... кусками
Моё мнение. Компилятор не правильно задаёт область видимости переменной и во втором прерывании не позволяет прочесть значение переменной, а инрементирует его заново. И потом возвращает его переменной как истинное.
Ну у вас 2 пути:
1 идиотское - поменять копилятор в среде.
2 реальное - поменять свое мнение. И пользоваться тем компилятором который есть и всех устраивает.
volatile ?
Сразу говорю, что код выкладывать не буду.
И не надо.
Моё мнение. Компилятор не правильно
Мнение о "неправильности компилятора" высказывают (высказывали и будут высказывать) горе-программисты во все времена. В 1982 перед входом в комнату дежурной смены ВЦКП СУ в Томске даже висела вывеска: "Да, у нас фортран не работает, и что?"
может это особенность архитектуры AVR, не позволять двум прерываниям работать с одной переменной.
Это особенность Вашей секретной программы. Разбирайтесь.
Все переменные, которые пользуются И изменяются в прерываниях обязаны объявляться как volatile. Врочем, вам уже про это намекнули..
А в основной программе ещё скобками запрета прерываний окружена.
Сначала предположил что это инкрементируется байт, но обнаружив -1, уже думаю что там int, а стало быть, да - надо окружать запретом прерываний - @see "атомарное чтение".
Сначала предположил что это инкрементируется байт, но обнаружив -1, уже думаю что там int, а стало быть, да - надо окружать запретом прерываний - @see "атомарное чтение".
Переменная глобальная, т.е. volatile. Тип long.
С "атомарным чтением" ни разу не сталкивался но суть понял. Похоже это и есть причина по которой программа работает не правильно. (Хотя можно и на комилятор сослаться, что он не понял, что переменная должна обрабатываться атомарно.)
Arhat109-2 Я с лету не нашел материал для обучения по этой теме. Можешь дать ссылку для изучения этого вопроса?
Volatile значит не глобальная, а вольная, независимая, изменяющая значение без контроля программы. Например любой входной регистр. Если обращении к такой переменной не атомарно ( = несколько байт ) то прерывание может поменять часть переменной и после прерывания результат будет иметь неопределённое значение. Поэтому в основной программе перед обращением к такой переменной надо запретить прерывания, после обращения снова разрешить.
Глобальной может быть любая переменная. Всё зависит от места и вида объявления.
Компилятор предупреждает о возможном изменении переменной, но не считает это ошибкой. От вас это предупреждение спрятали, что бы не заморачивать начинающих.
Arhat109-2, nik182 Большое спасибо
Я перешел на однобайтовые переменные в критичных местах и применил Volatile. Заработало. Так же применил экранирование прерываний.
Я перешел на однобайтовые переменные в критичных местах и применил Volatile. Заработало. Так же применил экранирование прерываний.
УРА! Автор все же решил не менять компилятор в среде Ардуино, а так же не начал переписывать синтаксис языка Си.
Угроза обновления прошла мимо. Аплодисменты TC от благодарных пользователей Ардуино.
Автор все же решил не менять компилятор в среде Ардуино, а так же не начал переписывать синтаксис языка Си.
я запретил.