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

 
 
> Осторожно цикл 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
Ответов
Rst7
сообщение May 18 2008, 09:16
Сообщение #2


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

Группа: Модераторы
Сообщений: 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
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 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



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

 


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


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