Написал примерный код когда этот нюанс возникает.
Допустим нужно сосчитать данные с порта, сначала старший нибл ,
потом младший в некую временную переменную по четырёхбитному интерфейсу.
Потом необходимо проанализировать её значение (в коде наличие установки битика),
если определённый битик установлен, то повтор цикла иначе выход.
Отлаживал с АВР Студией, код ИАР 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