WinAvr в вопросах и ответах
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
Переходит не по очереди 357,358, 370 а в произвольном порядке. Как на дизасме все идет, а ни как в листинге Си. То есть очередность команд нарушается. Сначала присваивается значение переменной, потом идет (не известно почему) InvBit(test), потом возвращается назад и потом только по очереди.
Как зачем мне голова?! Я ей ем!!!
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
Код: Выделить всё
1) _rfid_i = 0x08;
do{
2) _rfid_i--;
3) _rfid_j = 0x08;
4) _byte_key = *((unsigned char *)&_rfid_to_sent_array + _rfid_i - 1);
do{
_rfid_j--;
if((_byte_key & 0x80) == 0x80) {ClrBit(TEST); NOP;}
else {SetBit(TEST); NOP;}
InvBit(TEST);
NOP;
_byte_key = _byte_key << 1;
}
}
А получается что он делает:
Код: Выделить всё
1)_rfid_i = 0x08;
2) _rfid_j = 0x08;
3) InvBit(TEST);
4) _rfid_i--;
5) _rfid_j = 0x08;
А потом в начало на do{...} и потом все подряд уже идет - как надо.
Как зачем мне голова?! Я ей ем!!!
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: WinAvr в вопросах и ответах
судя по всему, вас вводит в смущение работа оптимизатора. кроме этого, неизвестно, как там определены ваши переменные и что с ними происходит, поэтому оптимизатор может кое-что сделать по-своему, не нарушив при этом общей логики программы.
отключите оптимизацию, и вы увидите, что порядок исполнения "правильный". кажущийся неправильным порядок исполнения оптимизированного кода приведет к правильному результату - бояться не стоит. а если программа у вас работает не так, как надо - это означает, что вы где-то допустили ошибку.
отключите оптимизацию, и вы увидите, что порядок исполнения "правильный". кажущийся неправильным порядок исполнения оптимизированного кода приведет к правильному результату - бояться не стоит. а если программа у вас работает не так, как надо - это означает, что вы где-то допустили ошибку.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
Самое интересное, что с любой оптимизацией и "чистым" мейкфайлом ни чего не меняется. Проблема "уходит", когда из тела функции выкидываю все циклы и тогда все идет как надо. Вообще это функция выплевывания кода карточки EM-marine в порт... Простейшая вроде бы задача когда все готово и остается только вывести результат.... Но вот такой затык произошел...
Еще как вариант, возможно ли, что такое возникает от неправильного (ну или еще какого-то) определения и пользования указателей? Хотя тогда причем тут циклы?... Я в недоумении...
Ах да, Из-за этих "оптимизаций" компилятора половина кода на выдаче съедается.... Т.е. начинается обработка функции, код начинает скакать, но потом видимо попадает в нужное место и все идет пучком.
P.S. Запрещаю все прерывания на время выполнения функции..
Полностью со всеми используемыми переменными функция выглядит так:
Сильно не бить если где накосячил, у меня глаз замылен совсем...
Еще как вариант, возможно ли, что такое возникает от неправильного (ну или еще какого-то) определения и пользования указателей? Хотя тогда причем тут циклы?... Я в недоумении...
Ах да, Из-за этих "оптимизаций" компилятора половина кода на выдаче съедается.... Т.е. начинается обработка функции, код начинает скакать, но потом видимо попадает в нужное место и все идет пучком.
P.S. Запрещаю все прерывания на время выполнения функции..
Полностью со всеми используемыми переменными функция выглядит так:
Код: Выделить всё
volatile unsigned char _rfid_timer_owf = 0x00; //переполнение таймера произошло N -раз
unsigned char _byte_key = 0; //побайтное чтение из ключа
unsigned char _rfid_i = 0, _rfid_j = 0, _rfid_k = 0; //глобальные счетчики
#define _rfid_def_timer 0xFF00; //стартовое значение таймера до переполнения 16 us при 16 МГц
#define Timer_CS TCCR3B = _BV(CS30) //предделитель на 1 (start)
#define Timer_Def TCNT3 = _rfid_def_timer //0xFFFF = ~30.02 us owerflow для freq = 7.3728 MHz
#define Timer_TOIE_ON TIMSK = _BV(TOIE3) //разрешить прерывание по переполнению
#define Timer_TOIE_OFF TIMSK &= ~TOIE3 //запретить прерывание по переполнению
#define Timer_Start {Timer_Def; Timer_CS;_rfid_timer_owf = 0x00; NOP;} //присваиваю начальное значение таймера, обнуляю счетчик переполнений таймера и пускаю таймер
#define Timer_Stop TCCR3B = 0x00 //предделитель на 0 (stop)
#define _rfid_mod_time ((_rfid_time[0] + _rfid_time[1]) >> 1)
#define _rfid_white_delay {while(_rfid_timer_owf < _rfid_mod_time){if(_rfid_timer_owf == _rfid_mod_time) _rfid_timer_owf = 0;}}
void EEPROM_Read_Long(unsigned int addr, unsigned char * new_value){
i = 8;
do{
i--;
*(new_value+i) = EEPROM_Read_Byte((unsigned int)(addr+i));
}while(i > 0);
NOP;
}
void RFID_Sent_Key(void){
Timer_TOIE_OFF; //запретить прерывание по переполнению
cli();
EEPROM_Read_Long((unsigned int)&_rfid_to_sent_EEPROM, (unsigned char *)&_rfid_to_sent_array); //записываю адрес ключа в еепром
sei(); //разрешаю все прерывания
Timer_TOIE_ON; //разрешить прерывание по переполнению
Timer_Start; //запускаю счетчик на переполнение
_rfid_i = 0x08;
do{
_rfid_i--;
_rfid_j = 0x08;
_byte_key = *((unsigned char *)&_rfid_to_sent_array + _rfid_i - 1);
do{
_rfid_j--;
if((_byte_key & 0x80) == 0x80) {ClrBit(TEST); NOP;}
else {SetBit(TEST); NOP;}
_rfid_white_delay;
InvBit(TEST);
NOP;
_rfid_white_delay;
_byte_key = _byte_key << 1;
}while(_rfid_j > 0x00);
}while(_rfid_i > 0x00);
Timer_TOIE_OFF; //запретить прерывание по переполнению
}
Сильно не бить если где накосячил, у меня глаз замылен совсем...
Последний раз редактировалось MOHOXPOM Вт июн 22, 2010 12:23:07, всего редактировалось 1 раз.
Как зачем мне голова?! Я ей ем!!!
Re: WinAvr в вопросах и ответах
лень вникать, но что сразу бросается в глаза:
...
#define Timer_TOIE_ON TIMSK = _BV(TOIE3) //разрешить прерывание по переполнению
если прерывание единственное, то ничего страшного (надо TIMSK |= _BV(TOIE3))
#define Timer_TOIE_OFF TIMSK ^= _BV(TOIE3) //запретить прерывание по переполнению
не запретить а "проинвертировать"
надо: TIMSK &= ~_BV(TOIE3)
...
void RFID_Sent_Key(void){
получается, что здесь разрешаем...
Timer_TOIE_OFF; //запретить прерывание по переполнению
...
здесь опять разрешаем...
Timer_TOIE_ON; //разрешить прерывание по переполнению
...
здесь запрещаем
Timer_TOIE_OFF; //запретить прерывание по переполнению
}
...
#define Timer_TOIE_ON TIMSK = _BV(TOIE3) //разрешить прерывание по переполнению
если прерывание единственное, то ничего страшного (надо TIMSK |= _BV(TOIE3))
#define Timer_TOIE_OFF TIMSK ^= _BV(TOIE3) //запретить прерывание по переполнению
не запретить а "проинвертировать"
надо: TIMSK &= ~_BV(TOIE3)
...
void RFID_Sent_Key(void){
получается, что здесь разрешаем...
Timer_TOIE_OFF; //запретить прерывание по переполнению
...
здесь опять разрешаем...
Timer_TOIE_ON; //разрешить прерывание по переполнению
...
здесь запрещаем
Timer_TOIE_OFF; //запретить прерывание по переполнению
}
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
Ну вы правы прерывание не единственное, так что надо ^ делать. Отключение, включение а потом снова отключение из-за того, что тот же таймер работает на обработку приема кода. И тайминги новые заводить не было смысла.
Как зачем мне голова?! Я ей ем!!!
Re: WinAvr в вопросах и ответах
MOHOXPOM писал(а):Ну вы правы прерывание не единственное, так что надо ^ делать. Отключение, включение а потом снова отключение из-за того, что тот же таймер работает на обработку приема кода. И тайминги новые заводить не было смысла.
Ваш первый "вызов" макро Timer_TOIE_OFF как раз ВКЛЮЧАЕТ прерывание.
операция XOR, она-же "исключающее ИЛИ", т.е. оператор "^" в Си в данном случае просто меняет 0 на 1 и наоборот.
Если надо установить бит - пишем: <РЕГИСТР> |= <НУЖНЫЙ БИТ, СДВИНУТЫЙ КУДА НАДО>, т.е. по "ИЛИ", не "портя" остальные биты.
если надо сбросить бит - пишем: <РЕГИСТР> &= ~ <СДВИНУТЫЙ БИТ, КУДА НАДО>.
В Вашем примере, как я написал изначально, Timer_TOIE_OFF просто меняет разрешение на запрещение прерывания при каждом "вызове", и наоборот. т.е. в Вашем случае:
func(){
Timer_TOIE_OFF; // включили прерывание
Timer_TOIE_OFF; // выключили прерывание
Timer_TOIE_OFF; // включили прерывание
Timer_TOIE_OFF; // выключили прерывание
...
}
не путайте битовые ИЛИ - |, И - & и ИСКЛЮЧАЮЩЕЕ ИЛИ - ^.
еще вопрос: а зачем куча NOP'ов?
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
Ну в принципе, я использую сначала ON и потом OFF. Так что один раз ставлю бит, а потом его инвертирую. А NOPы округляют задержку до 17.5 us при данном значении кварца и устаканивается значение в порту. Т.е. следующее действие при работе с портом хоть как сразу не даст его изменить. Ну примерно так:
default PB0 = 0
1) Set PB0 - NOP - Clr PB0
будет 0 - 1 - (держим такт) - 0
2) Set PB0 - Clr PB0
будет 0 - 1 - 0
и тут оптимизация пройдет... и PB0 останется без изменений, т.е. = 0
default PB0 = 0
1) Set PB0 - NOP - Clr PB0
будет 0 - 1 - (держим такт) - 0
2) Set PB0 - Clr PB0
будет 0 - 1 - 0
и тут оптимизация пройдет... и PB0 останется без изменений, т.е. = 0
Как зачем мне голова?! Я ей ем!!!
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
Но проблема этим не решилась и решиться не могла...
Вопрос еще. Как организовать задержку в функции на несколько переполнений таймера? Может есть отточенное решение? А то я через while() делаю в теле функции, который сравнивает значение каунтера декрементируемого в обработчике прерывания по переполнению счетчика.
Вопрос еще. Как организовать задержку в функции на несколько переполнений таймера? Может есть отточенное решение? А то я через while() делаю в теле функции, который сравнивает значение каунтера декрементируемого в обработчике прерывания по переполнению счетчика.
Как зачем мне голова?! Я ей ем!!!
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: WinAvr в вопросах и ответах
не понял... вы хотите сказать, что участок кодаMOHOXPOM писал(а):2) Set PB0 - Clr PB0
будет 0 - 1 - 0
и тут оптимизация пройдет... и PB0 останется без изменений, т.е. = 0
Код: Выделить всё
PORTB |= _BV(PB0);
PORTB &= ~_BV(PB0);этого не может быть, т.к. PORTB определен в WinAVR как volatile, поэтому никогда не будет затронут оптимизатором.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: WinAvr в вопросах и ответах
я все пытаюсь сказать, что нужно написать вот так:
а не так, как в приведенном исходном тексте:
а то получается, что Timer_TOIE_OFF первым вызовом РАЗРЕШАЕТ прерывание
Код: Выделить всё
#define Timer_TOIE_ON TIMSK |= _BV(TOIE3); //разрешить прерывание по переполнению
#define Timer_TOIE_OFF TIMSK &= ~_BV(TOIE3); //запретить прерывание по переполнению
а не так, как в приведенном исходном тексте:
Код: Выделить всё
#define Timer_TOIE_ON TIMSK = _BV(TOIE3) //разрешить прерывание по переполнению
#define Timer_TOIE_OFF TIMSK ^= _BV(TOIE3) //запретить прерывание по переполнению
а то получается, что Timer_TOIE_OFF первым вызовом РАЗРЕШАЕТ прерывание
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
Да поменял уже говорю. В предыдущем посте описал.
Как зачем мне голова?! Я ей ем!!!
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
ARV писал(а):не понял... вы хотите сказать, что участок кода
В симуляторе и при трассировке в протеусе получаются иногда очень интересные и разные варианты
Код: Выделить всё
DDRB = 0xFF; NOP;
PORTB = 0xFF; NOP;
PORTB = 0x00; NOP;
PORTB = 0xFF; NOP;
PORTB = 0x00; NOP;
Ну или
Код: Выделить всё
DDRB = 0xFF;
PORTB = 0xFF;
PORTB = 0x00;
PORTB = 0xFF;
PORTB = 0x00;
Иногда возникают трудности без нопов. Попробуйте просимулировать оба варианта и посмотретьна состояния портов в обоих случаях. Я на этом запнулся когда опрос и выдачу с одного порта делал. Теперь я лучше такт пропущу, но то что хотел точно в порту будет.
Как зачем мне голова?! Я ей ем!!!
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: WinAvr в вопросах и ответах
уважаемый МОНОХРОМ! я не стану маяться ерундой, проверяя в симуляторе то, в чем уверен на 100% - не первый день работаю с WinAVR и никогда не сталкивался с тем, чтобы работа с портом искажалась оптимизатором или чем-либо еще! думаю, и никто не сталкивался с этим. на всякий случай, сообщите, какая версия WinAVR у вас? у меня 20100110, но и с тремя предыдущими никаких проблем не было!
кстати, на счет порядка исполнения строк. в протеусе вчера сам видел чудо: есть static-функция, которая вызывается при очень хитром условии из глубины основного цикла. однако в протеусе при пошаговом выполнении я вижу. что содержимое этой функции "выполняется" едва ли не самым первым, еще до входа в главный цикл. тем не менее переменные, которые эта функция изменяет, остаются неизменными, а просмотр ассемблерных команд показывает, что на самом деле исполняются НЕ ЭТИ операторы. то есть из-за работы оптимизатора произошло такое сильное перемешивание ассемблерных команд, что сопоставить им строку в исходнике на Си не вышло - и строка программы выводится отладчиком неверно. разумеется, все сигналы программа выдает правильно, хотя по отладчику этого не заметно. бывали случаи и неожиданного исполнения цикла while не с первого оператора, а откуда-то из середины - тем не менее все работает верно, это особенность работы отладчика после оптимизатора.
кстати, на счет порядка исполнения строк. в протеусе вчера сам видел чудо: есть static-функция, которая вызывается при очень хитром условии из глубины основного цикла. однако в протеусе при пошаговом выполнении я вижу. что содержимое этой функции "выполняется" едва ли не самым первым, еще до входа в главный цикл. тем не менее переменные, которые эта функция изменяет, остаются неизменными, а просмотр ассемблерных команд показывает, что на самом деле исполняются НЕ ЭТИ операторы. то есть из-за работы оптимизатора произошло такое сильное перемешивание ассемблерных команд, что сопоставить им строку в исходнике на Си не вышло - и строка программы выводится отладчиком неверно. разумеется, все сигналы программа выдает правильно, хотя по отладчику этого не заметно. бывали случаи и неожиданного исполнения цикла while не с первого оператора, а откуда-то из середины - тем не менее все работает верно, это особенность работы отладчика после оптимизатора.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- MOHOXPOM
- Встал на лапы
- Сообщения: 108
- Зарегистрирован: Вт мар 18, 2008 08:25:31
- Откуда: Красноярск
- Контактная информация:
Re: WinAvr в вопросах и ответах
Вот! Спасибо за ответ. Попробую переписать по другому, так как и на выходе тоже не то что должно быть. Вернее не все 
А на счет исполнения по портам я и не спрашивал
Всем спасибо за ответы на мой бред 
А на счет исполнения по портам я и не спрашивал
Как зачем мне голова?! Я ей ем!!!
Re: WinAvr в вопросах и ответах
Товарищи, прошу не сильно кидать в меня подручными предметами, но вопрос такой - как рассчитать время (в тактах), затрачиваемое на выполнение участка кода на С? Есть ли какие-нибудь данные относительно того, за сколько тактов выполняется, скажем, присваивание, вызов подпрограммы, и постоянны ли эти значения вообще? Или просто надо анализировать дизассемблированный листинг, и другого пути нет?
Разница между теорией и практикой на практике гораздо больше, чем в теории.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: WinAvr в вопросах и ответах
разумеется, кроме анализа ассемблерного листинга ничего не поможет
кроме протеуса или другого отладчика
только надо быть осторожным, т.к. точки останова не всегда ставятся в начале какого-то оператора 
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Callous
- Встал на лапы
- Сообщения: 115
- Зарегистрирован: Вс апр 20, 2008 16:54:13
- Откуда: Украина, Чернигов
Re: WinAvr в вопросах и ответах
столкнулся я с такой загогулиной, программа измеряет 4 напряжения преобразует и выводит на 7-сегментный индикатор. в дебагере все работает так как надо. в протеусе когда симулируется то в переменной adc[] значения располагаются 3-0-1-2 а должны так 0-1-2-3 (номера-каналы АЦП), соответственно значения преобразуются не правильно и наиндикатор выводится ересь. Итак вопрос: это глюки протеуса и в железе все будет ОК или я налагал в проге. Критика программы очень уместна, так как мне кажется она написана через Ж, так что советы как написать ее компактней, оптимальней и просто красивее очень даже не помешают.
WinAVR-20090313.
WinAVR-20090313.
- Вложения
-
- 8.c
- (2.42 КБ) 393 скачивания
Последний раз редактировалось Callous Пн июл 05, 2010 23:45:23, всего редактировалось 1 раз.
- Aheir
- Модератор
- Сообщения: 4517
- Зарегистрирован: Пн апр 03, 2006 11:43:25
- Откуда: Санкт - Петербург
- Контактная информация:
Re: WinAvr в вопросах и ответах
Код - вложением! Правила читаем, нет? 
Оптимизм х (Опыт + Знания) = const
- Callous
- Встал на лапы
- Сообщения: 115
- Зарегистрирован: Вс апр 20, 2008 16:54:13
- Откуда: Украина, Чернигов
Re: WinAvr в вопросах и ответах
ну где же многоуважаемый ARV???? 