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

 
 
> Осторожно цикл 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



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

 


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


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