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

 
 
> Осторожно цикл do - while, обратите внимание, интерессный момент
sKWO
сообщение May 12 2008, 10:27
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Написал примерный код когда этот нюанс возникает.
Допустим нужно сосчитать данные с порта, сначала старший нибл ,
потом младший в некую временную переменную по четырёхбитному интерфейсу.
Потом необходимо проанализировать её значение (в коде наличие установки битика),
если определённый битик установлен, то повтор цикла иначе выход.
Отлаживал с АВР Студией, код ИАР 5.10А - полная, атмега8535
Код
// TWI Bit Rate Register (TWBR) объявлен как System_Flags
// К сожалению в меге 8535 нету GPIO регистров, поэтому такое решение
#define System_Flags TWBR  
#define DATA_SHIFT 0       // Коефиц сдвига данных
#define DATA_MASK 0x0f     // Маска данных
enum
    {
        BUSY_TIMEOUT_FLAG = (1 << 0),// таймаут ожидания
        _fail             = (1 << 1),// Cбой
        busy_bit          = (1 << 7)//
    };

void Port_check(void) { // ожидаем готовности
volatile uint8_t temp =0;
    do {
        System_Flags &= ~BUSY_TIMEOUT_FLAG;
        // строб упущен
        temp |= ((PINC << ( 4 - DATA_SHIFT)) & 0xF0);
        // строб упущен
        temp |= ((PINC >> DATA_SHIFT) & DATA_MASK);
        if (temp &(busy_bit)) System_Flags |= BUSY_TIMEOUT_FLAG;
                #ifdef _TIMER_ESCAPE_
        // аварийный выход по таймеру
        if (TIFR & (1<<TOV2)) break;
                #endif
    } while (System_Flags & BUSY_TIMEOUT_FLAG);
    if (System_Flags & BUSY_TIMEOUT_FLAG)
        System_Flags |= _fail;
        else System_Flags &= ~_fail;
}
int main( void ){for(;;){
Port_check();}}

При вызове функции Port_check в цыкле единожды считанные значения заносятся в
конкретном примере в регистр №17, и не изменяются при зацикливании!!!!
Хотя в отладчике видно что рабочий регистр №16 считывает значения но не обновляет
регистр №17. Зацикливание поизводится когда в отладчике проимитировать установление
битика3 PINC. Уровень оптимизации не имеет значение. Такой же вариант происходит
если вместо переменной temp использовать регистр №24, только код хуже.
Код
// Доступ к регистру 24
#define r24 (*(char*)24) // Это только для примера!

Выходит переменная и (или) регистр в цыкле не обновляются!!!!
в цикле проверяется только флаг BUSY_TIMEOUT_FLAG.
Вариант рабочей функции, без локальной переменной
Код
void Port_check(void) { // ожидаем готовности
    do {
        System_Flags &= ~BUSY_TIMEOUT_FLAG;
                // строб упущен
// нужно просто анализировать бит7 который мы получаем после первого строба
                if (((PINC << ( 4 - DATA_SHIFT)) & 0xF0) &busy_bit)
                System_Flags |= BUSY_TIMEOUT_FLAG;
                // строб упущен
        // аварийный выход по таймеру упущен
    } while (System_Flags & BUSY_TIMEOUT_FLAG);
    if (System_Flags & BUSY_TIMEOUT_FLAG)
        System_Flags |= _fail;
        else System_Flags &= ~_fail;
}

варианты откомпилированного кода с листингами прикрепляю
Прикрепленные файлы
Прикрепленный файл  RAB.rar ( 18.5 килобайт ) Кол-во скачиваний: 32
Прикрепленный файл  NERAB.rar ( 19.33 килобайт ) Кол-во скачиваний: 30
 


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 10)
diper
сообщение May 12 2008, 10:40
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 94
Регистрация: 12-11-05
Из: Росиия, Нижний Новгород
Пользователь №: 10 750



...не вникая в суть вопроса: volatile ?
Go to the top of the page
 
+Quote Post
sKWO
сообщение May 12 2008, 10:56
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(diper @ May 12 2008, 13:40) *
...не вникая в суть вопроса: volatile ?

нет, volatile это просто указать компилятору чтобы он переменную не оптимизировал, дабы показать что уровень оптимизации здесь непричём


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
rezident
сообщение May 12 2008, 11:44
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(sKWO @ May 12 2008, 16:56) *
нет, volatile это просто указать компилятору чтобы он переменную не оптимизировал, дабы показать что уровень оптимизации здесь непричём
volatile это запрет для компилятора оптимизировать обращение к переменной. Т.е. значение переменной типа volatile он обязан обновлять каждый раз, когда к ней происходит обращение. Что в вашем случае и не происходит.
Go to the top of the page
 
+Quote Post
diper
сообщение May 12 2008, 12:04
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 94
Регистрация: 12-11-05
Из: Росиия, Нижний Новгород
Пользователь №: 10 750



"...Хотя в отладчике видно что рабочий регистр №16 считывает значения но не обновляет регистр №17..." явный признак того что компилятор что то выкинул и нужен volatile.
Go to the top of the page
 
+Quote Post
sKWO
сообщение May 12 2008, 12:25
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(rezident @ May 12 2008, 14:44) *
volatile это запрет для компилятора оптимизировать обращение к переменной. Т.е. значение переменной типа volatile он обязан обновлять каждый раз, когда к ней происходит обращение. Что в вашем случае и не происходит.

Впринципе я это и имел ввиду, не оптимизировал переменную а обращение к ней, дабы компилятор
небыл не вчём уверен и каждый раз считывал её значение в цикле

Цитата(diper @ May 12 2008, 15:04) *
"...Хотя в отладчике видно что рабочий регистр №16 считывает значения но не обновляет регистр №17..." явный признак того что компилятор что то выкинул и нужен volatile.

я ещё для примера сказал что пробовал вместо локальной переменной исспользовал 24-й регистр,
суть дела таже.


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 12 2008, 12:47
Сообщение #7


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Компилятор сделал то, что Вы хотели. Ошибка у Вас.

Код
volatile uint8_t temp =0;
    do {


замените на

Код
volatile uint8_t temp;
    do {
          temp=0;


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
sKWO
сообщение May 15 2008, 11:31
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(Rst7 @ May 12 2008, 15:47) *
Компилятор сделал то, что Вы хотели. Ошибка у Вас.
замените на
Код
volatile uint8_t temp;
    do {
          temp=0;

Спасибо, так действительно работает, а то начал грешить на компилятор, но и с CV такая же засада была. никак немог додуть где налажал.


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 18 2008, 09:16
Сообщение #9


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Спасибо, так действительно работает


Не за что. Но в следующий раз - ищите ошибку у себя потщательнее wink.gif

Кстати, volatile перед temp там не нужно, это локальная переменная, применение этого модификатора только резко ухудшит выходной код.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
sKWO
сообщение May 19 2008, 10:47
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(Rst7 @ May 18 2008, 12:16) *
Не за что. Но в следующий раз - ищите ошибку у себя потщательнее wink.gif
Кстати, volatile перед temp там не нужно, это локальная переменная, применение этого модификатора только резко ухудшит выходной код.

Согласен,volatile перед temp ненужно. Просто код писал без книги (взяли почитать), а с этим циклом никогда раньше не работал, так приблизительно по памяти и посмотрел ваш пост №87 ну и написал не особо заморачиваясь. Цикл не заработал как надо , думал оптимизация, но она как уже известно тут непричём. Другого компилятора под рукой небыло а версия новая, не проверенная мной, вот и такая штука

PS: у Вас всё правильно

Сообщение отредактировал sKWO - May 19 2008, 10:49


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
defunct
сообщение May 24 2008, 20:32
Сообщение #11


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(sKWO @ May 19 2008, 13:47) *
Согласен,volatile перед temp ненужно.

В добавок к удалению volatile, еще хорошо бы во избежание других глюков порт читать единожды.
да и вместо жутких конструкций с "4 - DATA_SHIFT" не проще ли применить макрос

Код
#define  SWAP( x )  ((char)((x) << 4) | ((x) >> 4))
..
        temp =  PINC;
        temp = SWAP(temp);
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


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


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