Как вместо digitalRead() использовать регистр ?
- Войдите на сайт для отправки комментариев
Вс, 11/02/2018 - 17:39
Здавствуйте уважаемые форумчане.
Помогите подставить PORTD вместо "!digitalRead(4)".
/* */ #include <avr/io.h> #include <util/delay.h> #include <OLED_I2C.h> OLED myOLED(SDA, SCL, 1); extern uint8_t SmallFont[]; volatile int encoderPin1 = 2; volatile int encoderPin2 = 3; volatile int MSB ; volatile int LSB ; volatile int encoded = 0 ; volatile int lastEncoded = 0; volatile int sum ; volatile int a = 0; volatile int b = 0; volatile int c = 0; volatile int d = 0; volatile int encoderValue = 0; byte menuPos = 1; long val; long val_old = 0; int i = 0; void setup(){ Serial.begin (9600); myOLED.begin(); myOLED.clrScr(); myOLED.setFont(SmallFont); DDRD &= ~(1<<2); DDRD &= ~(1<<3); PORTD |= 1<<2; PORTD |= 1<<3; PORTD |= 1<<4; // pinMode(4, INPUT);// Kнопка "Mеню" DDRD &= ~(1<<4); // digitalWrite(4, HIGH); attachInterrupt(0, updateEncoder, CHANGE); attachInterrupt(1, updateEncoder, CHANGE); } void loop(){ MainScreen(); if(!digitalRead(4)){ // Заменить на порт прямого доступа "pin 4 Arduino Nano" delay(200); Menu(); } } void updateEncoder(){ MSB = digitalRead(encoderPin1); LSB = digitalRead(encoderPin2); encoded = (MSB << 1) |LSB; sum = (lastEncoded << 2) | encoded; if(encoded==0b0000){ if(a==0){ encoderValue = encoderValue+d; c=1; a=1; b=0; } } if(encoded==0b0011){ if(b==0){ encoderValue = encoderValue+d; c=1; b=1; a=0; } } if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011){ d=+1; } if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000){ d=-1; } lastEncoded = encoded; } void MainScreen() { myOLED.clrScr(); //myOLED.invertText(true); myOLED.print("MainScreen", CENTER, 20); //myOLED.invertText(false); myOLED.printNumI(encoderValue, CENTER, 40); myOLED.update(); } void Menu(){ for (i=0; i<=500; i++){ val = encoderValue; //***************************** Выбор позиции в меню *********************** if(val > val_old){ menuPos = menuPos + 1; val_old = val; } if(menuPos > 6){ menuPos = 1; } if(val < val_old){ menuPos = menuPos - 1; val_old = val; } if(menuPos < 1){ menuPos = 6; } switch(menuPos){ //*************** устанавливаем курсор согласно позиции в меню *************** case 1: myOLED.clrScr(); //myOLED.print(">", 0, 0); myOLED.invertText(true); myOLED.print("Alarm", 10, 0); myOLED.invertText(false); myOLED.print("Time", 10, 10); myOLED.print("Setting", 10, 20); myOLED.print("Setting2", 10, 30); myOLED.print("Setting3", 10, 40); myOLED.print("back", 10, 50); if (menuPos == 1 && !digitalRead(4)) MenuSetAlarm(); break; case 2: myOLED.clrScr(); //myOLED.print(">", 0, 10); myOLED.print("Alarm", 10, 0); myOLED.invertText(true); myOLED.print("Time", 10, 10); myOLED.invertText(false); myOLED.print("Setting", 10, 20); myOLED.print("Setting2", 10, 30); myOLED.print("Setting3", 10, 40); myOLED.print("back", 10, 50); if (menuPos == 2 && !digitalRead(4)) MenuSetTime(); break; case 3: myOLED.clrScr(); //myOLED.print(">", 0, 20); myOLED.print("Alarm", 10, 0); myOLED.print("Time", 10, 10); myOLED.invertText(true); myOLED.print("Setting", 10, 20); myOLED.invertText(false); myOLED.print("Setting2", 10, 30); myOLED.print("Setting3", 10, 40); myOLED.print("back", 10, 50); if (menuPos == 3 && !digitalRead(4)) MenuSetting(); break; case 4: myOLED.clrScr(); //myOLED.print(">", 0, 30); myOLED.print("Alarm", 10, 0); myOLED.print("Time", 10, 10); myOLED.print("Setting", 10, 20); myOLED.invertText(true); myOLED.print("Setting2", 10, 30); myOLED.invertText(false); myOLED.print("Setting3", 10, 40); myOLED.print("back", 10, 50); if (menuPos == 4 && !digitalRead(4)) MenuSetting(); break; case 5: myOLED.clrScr(); //myOLED.print(">", 0, 40); myOLED.print("Alarm", 10, 0); myOLED.print("Time", 10, 10); myOLED.print("Setting", 10, 20); myOLED.print("Setting2", 10, 30); myOLED.invertText(true); myOLED.print("Setting3", 10, 40); myOLED.invertText(false); myOLED.print("back", 10, 50); if (menuPos == 5 && !digitalRead(4)) MenuSetting(); break; case 6: myOLED.clrScr(); //myOLED.print(">", 0, 50); myOLED.print("Alarm", 10, 0); myOLED.print("Time", 10, 10); myOLED.print("Setting", 10, 20); myOLED.print("Setting2", 10, 30); myOLED.print("Setting3", 10, 40); myOLED.invertText(true); myOLED.print("back", 10, 50); myOLED.invertText(false); } myOLED.update(); if (!digitalRead(4) && menuPos == 6){break;} } delay (150); } void MenuSetTime(){ for (i=0; i<=500; i++){ myOLED.clrScr(); myOLED.print("MenuSetTime", CENTER, 20); myOLED.update(); if(!digitalRead(4)){break;} } } void MenuSetAlarm(){ for (i=0; i<=500; i++){ myOLED.clrScr(); myOLED.print("MenuSetAlarm", CENTER, 20); myOLED.update(); if(!digitalRead(4)){break;} } } void MenuSetting(){ }
Для разных контроллеров по-разному, но, если верить остальным фрагментам кода, то должно подойти !(PIND & (1<<4)).
Но в совокупности с delay(200) это не имеет никакого смысла.
PS. Поправлено: оказывается, "остальным фрагментам" верить нельзя.
!(PIND & 1<<4)
Igoreck, для чего вам это? На фоне delay(200) никакого смысла в этом нет.
Вы для начала научитесь просто писать нормальный код, без делеев и без жутких операторв кэйса, где в пяти вариантах выбора на 80% один и тот же код.
А чё, RTFМ прямо на этом сайте ... с религией что-то?
Спасибо за "!(PIND & 1<<4)" работает четко.
Но поповоду "жутких операторв кэйса" , посоветуйте пожалуйста правильную альтернативу!
Но поповоду "жутких операторв кэйса" , посоветуйте пожалуйста правильную альтернативу!
ну вот смотрите - у вас все кейсы выводят одно и то же - меняется только то, какая строка инвертирована, верно? Так сделайте процедуру вывода меню, которая будет принимать в качестве параметра номер строки, которую надо подсветить.
По поводу использования регистров вместо digitalRead - вам наверно кажется, что это признак крутого программиста? ^) На самом деле неуклюжий код кейса опускает вас куда сильнее, чем использование регистров - поднимает. По коду кейса сразу видно, что писал чайник. И на фоне этого кажется, что код с регистрами вы просто где-то списали.
Признаюсь - да я в этом пока чайник.
Собрал этот код по кускам и хочу зделать задуманное устройство, но места уже не хватает.
Пришлось укорачивать код посредством перехода из digitalRead() на тот кошмар который Вы видите.
Говорите "принимать в качестве параметра номер строки, которую надо подсветить", подскажите как привильно это реализовать.
Не кричите на меня, ведь я только учусь.
Прошу Вас поправте в меня в коде.
Кто нибудь помогите сделайть процедуру вывода меню, которая будет принимать в качестве параметра номер строки, которую надо подсветить.
Собрал этот код по кускам и хочу зделать задуманное устройство, но места уже не хватает.
Какого места не хватает? - флеша или оперативки? скорее оперативки...
По моему, вы не с того начали оптимизацию программы, у вас куча строк в оперативной памяти, которые можно оттуда выкинуть.
Какие именно строки?
Собрал этот код по кускам и хочу зделать задуманное устройство, но места уже не хватает.
Какого места не хватает? - флеша или оперативки? скорее оперативки...
По моему, вы не с того начали оптимизацию программы, у вас куча строк в оперативной памяти, которые можно оттуда выкинуть.
Прошу Вас помогите с оптимизацией кода!
В начале скетча добавить
а вместо всего твоего switch - вот это
и не забудь померить, сколько занимал код до и после
В начале скетча добавить
а вместо всего твоего switch - вот это
и не забудь померить, сколько занимал код до и после
Выражаю особеную благодарность и дай Вам Бог здоровья.
Выражаю особеную благодарность и дай Вам Бог здоровья.
напишите лучше - помогло или нет? что-то у меня ваш код и мой дают примерно одинаквую загрузку памяти, что удивительно, с учетом переноса строк в Пргмем и того, насколько мой код короче
Выражаю особеную благодарность и дай Вам Бог здоровья.
напишите лучше - помогло или нет? что-то у меня ваш код и мой дают примерно одинаквую загрузку памяти, что удивительно, с учетом переноса строк в Пргмем и того, насколько мой код короче
Помойму 28%. Точнее сравнить смогу завтра.
К сожалению Ваша оптимизация занимает 8 514 bytes (27%) памяти, а до этого была 7 954 bytes (25%).
Может мой быдлокод не такой плохой как кажется?
К сожалению Ваша оптимизация занимает 8 514 bytes (27%) памяти, а до этого была 7 954 bytes (25%).
Может мой быдлокод не такой плохой как кажется?
Свертывание шести одинаковых кейсов в одну компактную функцию - это однозначно более правильно, чем было. А почему более компактный код занял больше места - у меня есть некие мысли, вечером вам напишу. Я, видимо, где-то не совсем оптимально построил код, размер скетча явно должен быть менше.
К сожалению Ваша оптимизация занимает 8 514 bytes (27%) памяти, а до этого была 7 954 bytes (25%).
Может мой быдлокод не такой плохой как кажется?
Это не ваша заслуга. Это заслуга компилятора.)
Не хочу показаться назойливым, но Вы обещали помочь с оптимизацией !
Если Вы про использование регистра, так я же Вам дал ссылку - RTFМ прямо на этом сайте .
Вам нужно что-то ещё?
Не хочу показаться назойливым, но Вы обещали помочь с оптимизацией !
Не совсем так. Я обещал посмотреть, почему уменьшение скетча не привелу к уменьшению кода. Я мельком глянул - явных ошибок нет, на большее времени пока не хватило. Сегодня попытаюсь покопаться подробнее - мне самому этот вопрос интересен.
qwone? ты меня потроллить решил? :)
Строки 16 и 17 не обязательны, возьми ИДЕ и проверь :)
И вообще - вопрос в другом - вставь этот код в код ТС из заголовка темы и убедись - число строк скетча сокращается с 200 до 150, а размер прошивки при этом растет с 6700 до 7700 байт. почему?
ПС: У меня этого железа нет, а значит и программу под это железо писать не могу. Потому что успешное компилирование и успешная работа это тоже разные вещи.
ПС: У меня этого железа нет, а значит и программу под это железо писать не могу. Потому что успешное компилирование и успешная работа это тоже разные вещи.
Ссылки на неунжное железо можно выкинуть, суть вопроса не в этом. Я, собственно, собирался сегодня об этом даже новую тему открыть (что у меня случается крайне редко) - но потом решил, что еще не готов, не все варианты кода попробовал. Я не совсем рад, что эта тема выплыла - рано еще - но если у кого есть свежие мысли, то велкам.
Добрый вечер уважаемые колеги.
Может библиотеку заменить на U8glib, она меньше весит, но сам я не справлюсь ?
Помогите мне пожалуйста.
Вообще-то скетч на Ардуине, если в ней должно быть меню надо начинать так :)
Разбирался, почему у меня после сокращения исходника на четверть размер прошивки вдруг вырос. Провел тесты, упростил скетч до предела - и НАШЕЛ.
Правда найти - не значит понять. Вот примеры, чтобы ВЫСВЕТИТЬ ЭФФЕКТ.
Эффект, надо сказать, классный.
Скетч номер 1
Скетч номер 2
Непостижимо. Откуда разница в 1500 байт? Можно было бы подумать, что для разных параметров вызываются разные функции myOLED.print(). Но параметр-то вроде одного типа - const char*
А что говорит дизассемблер?
Если хотите, чтобы я тоже попытался поломать голову, то дайте пожалуйста ссылку где Вы брали OLED_I2C.h(ну и вообще библиотеку), чтобы эксперимент чистым был.
Если хотите, чтобы я тоже попытался поломать голову, то дайте пожалуйста ссылку где Вы брали OLED_I2C.h(ну и вообще библиотеку), чтобы эксперимент чистым был.
Пожалуйста.
http://www.rinkydinkelectronics.com/library.php?id=79
b707, ну, понятно.
По идее разработчики системных вещей должны быть грамотными (очень), а здесь ситуация наоборот - Вы грамотнее разработчика библиотеки - отсюда и беда. Вы использовали константу, а он - нет.
Уберите const в строке 4 и скомпилируйте. Полюбуйтесь.
А потом (тоже интересно) ещё попробуйте ту же строку в виде
char
*string_1 =
"Alarm"
;
)Проблема же в том, что разработчик библиотеки не предусмотрел метода print с константным параметром. У него параметр не объявлен константой (и, кстати, совершенно необоснованно). Ну, а коль так, Ваш компилятор тащит "службу защиты констант", с копированием, дублированием и восстановлением после вызова.
Почему он не сделал параметр константой - хрен его знает. Как говорил Мюллер в исполнении Броневого: "Невозможно понять логику непрофессионала".
ЕвгенийП, спасибо за ответ. Но яснее не стало. Назвать меня "грамотным" вы явно поспешили :)
Мне непонятно, почему код компилируется по разному. Ведь если автор библиотеки поленился обьявить параметр функции константой - это должно сказываться в обоих случаях, рахве нет?
Разве константная строка "Alarm" и константа const char string_1[] = "Alarm"; - это не один тип данных для компилятора?
Если ответ лежит в примерах, которые вы предлагаете проверить - тогда подождем до вечера, мне сейчас нечем компилировать.
это должно сказываться в обоих случаях, рахве нет?
Нет. Вот смотрите.
В "плохом" случае константа описана снаружи и, значит, что её читают из прогмема во время инициализации и с тех пор она живёт в RAM и ею теоретически может воспользоваться кто-то ещё, кроме оператора вызова функции. Функция же имеет право в неё нагадить, т.к. параметр функции не константый. И компилятор вставляет код для сохранения её неизменной независимо от того будет функция её менять или нет (копирование и восстановление, но на самом деле там здоровый кусок кода на все случаи жизни).
В "хорошем" случае эта константа стоит как литерал прямо в вызове функции, а значит она читается из прогмема непосредственно перед вызовом и после вызова её никто уже использовать не сможет - она никому не нужна, так что пусть себе функция в неё гадит, никого это не волнует.
понял, огромное спасибо.
Igoreck - практический вывод из этой дискуссии - надо чуть подправить библиотеку OLED_I2C.h. Я вечером посмотрю и напишу. что вам сделать. Думаю, получится выиграть порядка 1500 - 2000 байт в размере кода.
Но это касается флеш. Занятость оперативной памяти от этого почти не изменится - а у вас, насколько я вижу - загвоздка в этом. Чтобы решить эту проблему кардинально - надо выбирать другую библиотеку ОЛЕД или вообще писать свою.
Кстати, попробовал поменять в библиотеке тип параметра на const (ну, и всё, что для этого надо аккуратно сделал). Ваш "плохой пример" сразу стал нормально компилироваться с нормальным размером.
P.S. Заодно глянул код библиотеки - действительно очень по-любительски написано.
Так накидал примерный скетч Меню, работает. Если ТС разберется, то сможет применить.
Ценю Ваш труд колега, но есть вопросы.
Мои вам соболезнования и вашему компилятору. Как вариант могу этот вариант скинуть . Но у меня все в норме
Igoreck.
Как обещал - пишу что надо поправить в библиотеке OLED_I2C.h.
=== В файле OLED_I2C.h ===
---- строка 113
void print(char *st, int x, int y);
исправить на
void print(const char *st, int x, int y);
=== В файле OLED_I2C.cpp ===
---- строка 181
void OLED::print(char *st, int x, int y)
исправить на
void OLED::print(const char *st, int x, int y)
===========================
У меня исправление двух этих строк уменьшают ваш код на 1450 байт.
Спасибо огромное, мне очень приятно что Вы находите на это время, и помогаете.
На чем Вы работаете?
Какая у Вас среда и версия разработки?
Можно ли в Visual Studio, но заливать потом как?
На чем Вы работаете?
Какая у Вас среда и версия разработки?
Ваш код я проверял на Ардуино ИДЕ 1.8.3, Вин7 х64
Тогда все ясно- 1.6.5!
Тогда все ясно- 1.6.5!
А что, что-то не работает?
Да тут Qwone пишет что соболезнует моему компилятору, поэтому я разпереживался.
Можно ли в Visual Studio, но заливать потом как?
при уже установленной Arduino IDE добавить в Visual Studio плагин Visual Micro