Помогите понять, что творит оптимизатор Си AVR
- Сообщения: 139
- Зарегистрирован: Чт фев 11, 2016 18:35:37
См. update предыдущего поста.
- Из овощей я больше всего люблю пельмени... © Соседский Мальчик
- Реклама
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Начинаем по второму кругу? Без схемы подключения говорить о необходимости изменении матрицы или знака нельзя. Это все равно что говорить что код обработки колесика мыши и обратной связи электродвигателя дают противоположный результат. Так что вместо того, чтобы повторять свои аргументы по второму кругу, приведите наконец схему и настройки, при которых это транспонирование нужно. Разумеется, речь идет только о файле библиотеки; main.c и файл протеуса не имеют к ней никакого отношения. Вот когда приведете, увидите, что ничего транспонировать не обязательно - правильно работает в обоих случаях.
Но это не лучшее решение с точки зрения оптимальности кода. Работу с указателями контроллер не слишком любит. Лучше было бы заставить функцию возвращать знаковое число и использовать его при расчетах:
Ну и, возможно, стоит попробовать табличный вариант. У L.O.D он более наглядный, чем у меня, правда полной реализации я не нашел, на всякий случай приведу как я ее вижу.
Достаточно передать ее в функцию по указателю:В прицнципе здесь должна увеличиться или уменьшиться переменная, передаваемая из основновной программы, но как это сделать пока что не знаю
Код: Выделить всё
void Encoder(signed char *pos){ //звездочка означает указатель на переменную, а не ее значение
...
*pos = 1; //для примера, присвоим переменной значение 1, но можете проводить и другие операции.
...
}
int main(){
signed char enc_pos;
Encoder(&enc_pos); //знак '&' означает адрес переменной. Это почти указатель, только изменяться не может.
...
}Код: Выделить всё
int Encoder(){
if(1)return 1; //условно говоря, это условие, при котором значение энкодера должно увеличиться.
if(2)return 0; //значение энкодера не менялось
if(3)return -1; //значение энкодера уменьшилось
}
int main(){
int enc_pos;
enc_pos = enc_pos + Encoder();
}Это не нужно. Объявите Encoder_State как локальную статическую переменную в функции Encoder и инициализируйте ее нужным значением// Это нужно для того чтобы получить первое значение состояния энкодера при пуске
Код: Выделить всё
void Encoder(){
static char Encoder_State = PINB & 0x03;
...Лучше внутри функций таким не злоупотреблять. Она может быть вызвана когда прерывания запрещены, а она их разрешит. Да и прерывание ее работы неопасно. Пусть себе прерывания возникают где-то в середине, они не помешают.asm("cli");
...
asm("sei");
Ну и, возможно, стоит попробовать табличный вариант. У L.O.D он более наглядный, чем у меня, правда полной реализации я не нашел, на всякий случай приведу как я ее вижу.
Спойлер
Код: Выделить всё
signed char EncTransIncs[4][4] = {
0, +1, -1, 0,
-1, 0, 0, +1,
+1, 0, 0, -1,
0, -1, +1, 0
};
signed char Encoder(){
static uint8_t last_state = PINB & 0x03; //предыдущее состояние энкодера
uint8_t cur_state = PINB & 0x03; //текущее состояние. При первом запуске они совпадают, потом last_state будет на один отсчет отставать
signed char res; //результат
res = EncTransIncs[ last_state ][ cur_state ];
last_state = cur_state;
return res;
}
int main(){
int enc_angle;
...
while(1){
enc_angle = enc_angle + Encoder();
}
}- Сообщения: 139
- Зарегистрирован: Чт фев 11, 2016 18:35:37
Да если бы по второму - уже раз пятый, кажется, Вы отказываетесь понять, что в коде ТСа порядок подключения каналов уже определен и менять этот порядок подключения, при подстановке Вашего кода, он разумеется не станет. А раз не станет, то очевидно, что получит противоположный своему результат.COKPOWEHEU писал(а):Начинаем по второму кругу? Без схемы подключения говорить о необходимости изменении матрицы или знака нельзя.
- Из овощей я больше всего люблю пельмени... © Соседский Мальчик
я обращаю внимание на несколько недочетов в ваших файликах:Мikа писал(а):Я писал я все это по полному подобию того, как вы говорили, но что-то не так.
1. в файл заголовка нет смысла выносить функции, которые никогда не понадобятся "снаружи" модуля. у вас это функция getEncoderState
2. функция, которая начинается с get, по своему смыслу должна что-то возвращать! она же даже начинается со слова "получить" - откуда же получать, если она ни параметров, ни результата не имеет?!
3. локальные, т.е. востребованные только внутри модуля, функции и [глобальные] переменные должны всегда объявляться с префиксом static
4. если вы пользуетесь avr-gcc, то используйте в нужных случаях заголовочник interrupt.h и определенные в нем макросы cli() и sei() вместо "ассемблерных" вставок. avr-gcc не прощает вольностей с ассемблерными вставками, но от версии к версии имеет свои нюансы, помнить которые сложнее, чем использовать "стандартные" макросы.
5. функция Encoder как бы по своей логике должна что-то вернуть в результате своей работы - но ничего не возвращает.
6. использование глобальных переменных для обмена данными между функциями - это ближе к плохому стилю, чем к хорошему - у вас это процветает.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Это вы отказываетесь понять, что у меня он НЕ определен. Как определите так и будет работать.L.O.D писал(а):Вы отказываетесь понять, что в коде ТСа порядок подключения каналов уже определен
Ну, ее смысл в получении начального значения для внутренней переменной, так что get кое-как натянуть можно. Автору, похоже, стоит ознакомиться с методом объявления переменных с их инициализацией. Ну и это не отменяет, что приставки get и set принято использовать для получения и установки какого-то значения, а не для инициализации.1. в файл заголовка нет смысла выносить функции, которые никогда не понадобятся "снаружи" модуля. у вас это функция getEncoderState
Внутри функции - точно нет, там у static'а своя область применения, а обычные локальные переменные в спецмодификаторах не нуждаются.3. локальные, т.е. востребованные только внутри модуля, функции и [глобальные] переменные должны всегда объявляться с префиксом static
А можно подробнее? А то я нормально пользовался и так и так и проблем не находил. Это вообще рекомендация по безопасности или оформлению кода?макросы cli() и sei() вместо "ассемблерных" вставок
- Реклама
- Сообщения: 139
- Зарегистрирован: Чт фев 11, 2016 18:35:37
А при чем здесь вы? Речь, напоминаю, шла о ТС, у которого этот порядок уже определен и при этом определенном порядке приведенный вами пример выдаст противоположные результаты. С чем вы никак не можете разобраться на протяжении вот уже пяти дней и семи попыток. Многовато для человека, не отягощенного чем-то, сильно отвлекающим его внимание.COKPOWEHEU писал(а):у меня он НЕ определен. Как определите так и будет работать.
Я еще после третьей итерации предложил прекратить очевидно бесплодные попытки - "Ну да ладно." - полагаете, есть смысл продолжать?
- Из овощей я больше всего люблю пельмени... © Соседский Мальчик
я говорил о локальных переменных для МОДУЛЯ, и о локальных для МОДУЛЯ функциях, а не о локальных переменных в функцияхCOKPOWEHEU писал(а):Внутри функции - точно нет, там у static'а своя область применения, а обычные локальные переменные в спецмодификаторах не нуждаются.
дело в том, что разные версии компилятора avr-gcc по-разному обращаются с ассемблерными вставками. неоднократно было отмечено, что оптимизатор выбрасывает подобные вставки. поэтому рекомендуется как минимум писать volatile asm("cli") чтобы однозначно не попасть под раздачу багов. ну а еще лучше поступать, как я и советовал - использовать макросы, за которые avr-gcc сам "отвечает"COKPOWEHEU писал(а):А можно подробнее? А то я нормально пользовался и так и так и проблем не находил. Это вообще рекомендация по безопасности или оформлению кода?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
[бьющийся головой о стену смайлик] Ладно, я не могу разобраться в своей же библиотеке. Покажите же наконец, как ее правильно использовать. Возьмите мою библиотеку (encoder.h) и подключит к проекту ТСа. после этого скажите, в ту оно сторону вращается или нет. Только очень прошу - действительно проверьте, а то пустых обвинений тут уже третья страница идет.L.O.D писал(а):А при чем здесь вы? Речь, напоминаю, шла о ТС, у которого этот порядок уже определен и при этом определенном порядке приведенный вами пример выдаст противоположные результаты. С чем вы никак не можете разобраться на протяжении вот уже пяти дней и семи попыток.COKPOWEHEU писал(а):у меня он НЕ определен. Как определите так и будет работать.
В таком случае будем считать что я несколько расширил ваш пункт, вдруг кто тоже неправильно поймет.я говорил о локальных переменных для МОДУЛЯ, и о локальных для МОДУЛЯ функциях, а не о локальных переменных в функциях
Это, кстати, странно. Ладно бы пытался оптимизировать, то есть если где-то раньше уже есть, скажем, обнуление всего SREG, то следующую asm("cli") выбрасывать. Но целую вставку просто так? Ладно, если народ наступал на такие грабли, надо поберечься.неоднократно было отмечено, что оптимизатор выбрасывает подобные вставки
В прошлый раз забыл сказать - выложите весь проект, архивом, а не только исходный код. Особенно интересует файл Default/makefile. Он автогенерированный и если у кого тут есть IDE вашей версии, проект будет полезнее. Но в крайнем случае этого файла хватит чтобы определить что и куда вы подключаете.Я рискну вернуться к теме разговора про вынос функций в отдельные файлы и попросить вас всё-же посмотреть мой проект и и подсказать, где я допускаю ошибку
- Сообщения: 139
- Зарегистрирован: Чт фев 11, 2016 18:35:37
Если вам еще и обвинения привиделись, то у вас не просто мало времени на этот топик, у вас его катастрофически мало. И тот же смайлик, что вы не нашли.COKPOWEHEU писал(а):а то пустых обвинений тут уже третья страница идет.
PS Я уже дважды предлага вам перестать спорить. Раз не хотите, продолжайте без меня.
- Из овощей я больше всего люблю пельмени... © Соседский Мальчик
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
То есть ответить по существу нечего, подтвердить слова нечем? Остается только изображать экстрасенса, видящего неправильный код и чужие мысли там где этого и в помине нет. Наверное, признать свою неправоту настолько сложно, что приходится неделю ходить кругами, лишь бы не приводить реальных фактов.
- Сообщения: 615
- Зарегистрирован: Вс дек 28, 2014 21:54:05
Господа COKPOWEHEU и L.O.D , сюда бы смайлик, затягивающий ручник...
Я всё-всё узнAю и стану профессором.
- Сообщения: 3459
- Зарегистрирован: Ср сен 27, 2006 16:18:57
А может, ну его нахуй? Пусть себе творит, что хочет. Программа работает, и слава Богу!
Тока накрайняк можно сунуть морду в ассемблерый код, ну уже когда совсем жопа, и не понятно, что и где искать...
Тока накрайняк можно сунуть морду в ассемблерый код, ну уже когда совсем жопа, и не понятно, что и где искать...
- Сообщения: 139
- Зарегистрирован: Чт фев 11, 2016 18:35:37
Предыдущих семи раз достаточно.COKPOWEHEU писал(а):То есть ответить по существу нечего, подтвердить слова нечем?
- Из овощей я больше всего люблю пельмени... © Соседский Мальчик


