Свежие обсуждения
Микроконтроллеры

Странное поведение cvavr при инициализации переменных

1 2

Скомпилировал как обычно программу в cvavr 1.25.9, запустил в симуляторе (vmlab) и, ... последний завалил меня сообщениями о нарушении регистра SREG (бит Z: Zero Flag); также симулятор отметил строки с нарушениями, это оказались операции логического сравнения, например: if(j==72) {j=0;} и т.п. и программа запускалась "через раз". Ещё оказалось, что значение переменной, например, j в момент выполнения логической операции почему-то неизвестно и после, SREG - становится испорченным. В программе переменные инициализированы у меня, как обычно делаю, при их объявлении, но получалось, что инициализации при компиляции не происходило. Всё пришло в норму, когда инициализировал переменные в функции main. Так и не понял, почему так стало, ведь переменные же обычно удобнее инициализировать сразу при их объявлении?

 

Компилятор может оптимизировать в том числе и выделение памяти под переменные. Т.е. до момента использования память под них может быть и не выделена, соответственно они не проинициализированны.

 

Digital: Всё пришло в норму, когда инициализировал переменные в функции main.
Ну и правильно. А у вас как было?
...вы говорите про глобальные переменные или локальные?
Если про глобальные, то компилятор под них отводит либо регистры, либо область ОЗУ. В свойствах проекта надо поиграться флажками.

 

Про глобальные. В общем если галочку "Automatic register allocation" снять (случайно например ), то так получается. Но и с установленной, если переменных много, то SREG нет-нет, да испортится ( в симуляторе по крайней мере). Получается что в main (а не сразу при объявлении) инициализировать глобальные переменные вернее, тогда симулятор не ругается вообще (на одной и той же программе пробовал). Наверное такая особенность cvavr, буду знать теперь .

 

Digital: Получается что в main (а не сразу при объявлении) инициализировать глобальные переменные вернее
Честно говоря, непонятное утверждение.
Зачем вобще их инициализировать? Ведь для чего нужны глобальные переменные? Чтобы передавать какие-то значения из одной функции в другую, пользуясь переменной, как средством передачи. Находясь в любой точке программы вы можете положить туда число, которое всегда можно считать из другой любой точки программы. Именно для этого они и нужны. Хотя в большинстве случаев можно обойтись и без них. Для этого ваши функции должны быть не "void Функция (void)", а уметь принимать и возвращать численные значения, например "char функция (char x)". В каждой функции объявляется своя собственная переменная (локальная), которая работает только внутри этой функции. Конечно могут быть и исключения. Например прерывания. Функцию прерывания вы не вызываете из программы. Прерывания возникают под влиянием каких-то других, независимых от программы факторов. Вот тут-то и могут пригодиться глобальные переменные опять же для того, чтобы воспользоваться в обработчике прерывания каким-то числом, сформированным в других функциях.
//*****************************************************************
Теперь ваш случай. Присваивать глобальной переменной какое-то значение до объявления главной функции вообще бессмысленно, т. к. переменная это всего навсего "вагон". Заполнять этот вагон углем или песком или еще чем-нибудь мы будем решать по ходу программы и по мере необходимости. Другими словами, глобальные переменные не нуждаются в начальной инициализации!
Если же вы хотите проинициализировать переменную и не менять ее по ходу программы вообще, то это уже будет не переменная, а константа. Константы действительно объявляются и им присваивается значение вне главной или каких-либо других функций. В контроллерах константы заносятся во флеш-память. Чтобы компилятор отличил константу от переменной надо писать например так: flash unsigned char x = 0x12;

 

Zandy: Зачем вобще их инициализировать?
Ну вроде как по умолчанию, если не указать явно они будут равны нулю, но этого не происходило, я так понял из-за отключенной в cvavr "Automatic register allocation".

Zandy: Вот тут-то и могут пригодиться глобальные переменные опять же для того, чтобы воспользоваться в обработчике прерывания каким-то числом, сформированным в других функциях.
Есть такое В обработчике выбирается то или иное значение полученное из while(1) - основного цикла программы.

Zandy: Если же вы хотите проинициализировать переменную и не менять ее по ходу программы вообще, то это уже будет не переменная, а константа.
Такое тоже имеется, но сделал как bit, т.к. значение или 0 или 1.

 

Мне вот что не понятно. Когда есть нарушение SREG, то cvavr размещает переменные по каким-то адресам или смещениям, непонятно где в общем? См. 1.jpg (34kb). А когда всё нормально, то вот так, с явным указанием регистров (2.jpg 36.5kb).

 

2.jpg

 

Digital: Такое тоже имеется, но сделал как bit, т.к. значение или 0 или 1.
Тут имел ввиду, что 0 или 1 прописываются один раз, в зависимости от того, нужен прямой или инверсный сигнал на выходе.

 

А вы знаете, что битовые переменные (записанные, например, как bit х ) доступны только в главной функции? Ни в каких других функциях их использовать нельзя.