Имеется у меня Iskra Neo, мембранная клавиатура 4х4 и дисплей на ST7920. Захотелось мне сделать простенький калькулятор. Насмотревшись всякого разного, понял, что стоит использовать для сего чудного дисплея использовать библиотеку U8glib. Вооружившись своим стандартным набором (паяльник, слабоумие и отвага) все подключил. Осталось дело, как казалось, за малым - скетчем. Изучив всемирную паутину, я понял, что так и не смог найти примера калькулятора с использованием библиотеки u8glib. Найдя пример обычного калькулятора с дисплеем 16х2, попытался переиначить его под свои нужды: Код (C++): #include <U8glib.h> #include <Keypad.h> U8GLIB_ST7920_128X64 u8g(10, 11, 12, U8G_PIN_NONE); // настройка пинов long num1,num2 ; double total; char operation,button; const byte ROWS = 4; const byte COLS = 4; char keys[ROWS][COLS] = { {'1','2','3','+'}, {'4','5','6','-'}, {'7','8','9','*'}, {'C','0','=','/'} }; byte rowPins[ROWS] = {0,1,2,3}; // подключение к строкам клавиатуры byte colPins[COLS] = {4,5,6,7}; // подключение к столбцам клавиатуры Keypad customKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS); // Этот код выполняется только один раз: при включении платы void setup() { u8g.setFont(u8g_font_6x10); // Выбор шрифта } void loop() { sprintf(num1, "%d",num2); // функция sprintf переведёт число в строковый массив // Циклы удобны для чтения нажатых кнопок клавиатуры while(1) { // Первый цикл. Здесь мы читаем клавиатуру и составляем наше первое число. // Он выполняется, пока мы не нажмем кнопку оператора, и цикл прервется, // или, если будет нажата кнопка 'C', всё начнется с начала. button = customKeypad.getKey(); // Чтение кнопки if (button=='C') // Если пользователь хочет сбросить набор первого числа { num1=0; num2=0; total=0; operation=0; } if (button >='0' && button <='9') // Если пользователь нажал на числовое значение, один символ за раз { num1 = num1*10 + (button -'0'); // Наши числовые значения лежат в диапазоне от 0 до 9, что означает, что это единицы. // Когда мы умножаем на 10, мы, по сути, добавляем 0 после числа. // Затем мы добавляем новое введенное число на место нуля. // Что касается (button -'0'), это простой трюк с таблице ASCII. Цифры 0...9 в таблице ASCII // это 48...57 (в десятичном виде), поэтому, вычитание '0' из любого из этих символов дает // соответствующее значение в десятичном виде. Например, символ '5' = 53 в десятичной системе // минус 48 (символ нуля) дает нам значение 5. // Если наше предыдущее число было, например, 25, мы получили 250 умножением его на 10, // а затем добавили 5, и получили 255, что и будет выведено на U8G. do { u8g.setPrintPos(0,10); // Выбор первой строки на U8G u8g.print(num1); // Печать текущего значения числа num1 } while(u8g.nextPage()); } if (num1 !=0 && (button=='-' || button=='+' || button=='*' || button=='/')) { // Если пользователь завершил ввод цифр operation = button; // запоминаем, какое математическое действие пользователь хочет выполнить do { u8g.setPrintPos(0,20); // установить курсор на строку 2 u8g.print(operation); // напечатать наш оператор } while(u8g.nextPage()); break; } } while(1) { // Второй цикл, он выполняется пока пользователь не нажмет '=' или 'C'. // И тогда будет выведен результат или сброшена программа. if (button =='C') break; // Это обрабатывает случай, когда пользователь нажал кнопку оператора и захотел сбросить button = customKeypad.getKey(); if (button=='C') // Еще раз проверяем, не хочет ли пользователь сбросить { num1=0; num2=0; total=0; operation=0; break; } if (button >='0' && button <='9') // Получение символов от клавиатуры для числа 2 { num2 = num2*10 + (button -'0'); do { u8g.setPrintPos(10,10); u8g.print(num2); } while(u8g.nextPage()); } } if (button == '=' && num2 !=0) { // Если нажата кнопка '=', то это конец пути. Вызываем функцию domath(), выполняющую расчет // и выводим результат. domath(); break; } } while(1) { // Когда всё выполнено, этот цикл ждет нажатия кнопки 'C', чтобы сбросить программу и начать с начала. // Это побочный эффект от предыдущего цикла, когда пользователь нажал 'C', предыдущий цикл прерывается // и переходит сюда. Поэтому мы должны также прервать и текущий цикл, иначе пользователю придется // нажимать 'C' дважды. if (button =='C') break; button = customKeypad.getKey(); if (button =='C') { u8g.setPrintPos(0,0); num1=0; num2=0; total=0; operation=0; break; } } } void domath() { switch(operation) { case '+': // Сложение total = num1+num2; break; case '-': // Вычитание total = num1-num2; break; case '/': // Деление // Может добавить ошибку деления на ноль, или измените строку во втором цикле, // где тот ожидает символа '=' на if (button == '=' && num2 != 0), это остановит программу // от дальнейших действий, пока num2 не будет отличаться от нуля. total = (float)num1/(float)num2; break; case '*': // Умножение total = num1*num2; break; } do { u8g.setPrintPos(0,10); u8g.print('='); u8g.setPrintPos(10,10); u8g.print(total); } while(u8g.nextPage()); } Прошу помочь и палками не бить!
В вопросе нет главного - собственно вопроса. Если скетч работает неправильно - ПОДРОБНО опишите ошибки
Согласен, как-то о самом вопросе я ничего толком не разъяснил. Вышеизложенный скетч не проходит компиляцию. Выходит ошибка: "C:\Users\CD86~1\AppData\Local\Temp\untitled1662855145.tmp\sketch_dec24a\sketch_dec24a.ino: In function 'void loop()': sketch_dec24a:115: error: 'domath' was not declared in this scope domath(); ^ sketch_dec24a:116: error: break statement not within loop or switch break; ^ C:\Users\CD86~1\AppData\Local\Temp\untitled1662855145.tmp\sketch_dec24a\sketch_dec24a.ino: At global scope: sketch_dec24a:120: error: expected unqualified-id before 'while' while(1) ^ exit status 1 'domath' was not declared in this scope" До того, как я добавил Код (C++): do { } while(u8g.nextPage()); В местах, где что-либо должно выводиться на дисплей, скетч проходил компиляцию, загружался в плату, но дисплей ничего не выводил. До изменений скетч выглядел так: Код (C++): #include <U8glib.h> #include <Keypad.h> U8GLIB_ST7920_128X64 u8g(10, 11, 12, U8G_PIN_NONE); // настройка пинов long num1,num2 ; double total; char operation,button; const byte ROWS = 4; const byte COLS = 4; char keys[ROWS][COLS] = { {'1','2','3','+'}, {'4','5','6','-'}, {'7','8','9','*'}, {'C','0','=','/'} }; byte rowPins[ROWS] = {A2,A3,A4,A5}; // подключение к строкам клавиатуры byte colPins[COLS] = {2,3,4,5}; // подключение к столбцам клавиатуры Keypad customKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS); // Этот код выполняется только один раз: при включении платы void setup() { u8g.setFont(u8g_font_6x10); // Выбор шрифта } void loop() { // Циклы удобны для чтения нажатых кнопок клавиатуры while(1) { // Первый цикл. Здесь мы читаем клавиатуру и составляем наше первое число. // Он выполняется, пока мы не нажмем кнопку оператора, и цикл прервется, // или, если будет нажата кнопка 'C', всё начнется с начала. button = customKeypad.getKey(); // Чтение кнопки if (button=='C') // Если пользователь хочет сбросить набор первого числа { num1=0; num2=0; total=0; operation=0; } if (button >='0' && button <='9') // Если пользователь нажал на числовое значение, один символ за раз { num1 = num1*10 + (button -'0'); // Наши числовые значения лежат в диапазоне от 0 до 9, что означает, что это единицы. // Когда мы умножаем на 10, мы, по сути, добавляем 0 после числа. // Затем мы добавляем новое введенное число на место нуля. // Что касается (button -'0'), это простой трюк с таблице ASCII. Цифры 0...9 в таблице ASCII // это 48...57 (в десятичном виде), поэтому, вычитание '0' из любого из этих символов дает // соответствующее значение в десятичном виде. Например, символ '5' = 53 в десятичной системе // минус 48 (символ нуля) дает нам значение 5. // Если наше предыдущее число было, например, 25, мы получили 250 умножением его на 10, // а затем добавили 5, и получили 255, что и будет выведено на U8G. u8g.setPrintPos(0,0); // Выбор первой строки на U8G u8g.print(num1); // Печать текущего значения числа num1 } if (num1 !=0 && (button=='-' || button=='+' || button=='*' || button=='/')) { // Если пользователь завершил ввод цифр operation = button; // запоминаем, какое математическое действие пользователь хочет выполнить u8g.setPrintPos(0,1); // установить курсор на строку 2 u8g.print(operation); // напечатать наш оператор break; } } while(1) { // Второй цикл, он выполняется пока пользователь не нажмет '=' или 'C'. // И тогда будет выведен результат или сброшена программа. if (button =='C') break; // Это обрабатывает случай, когда пользователь нажал кнопку оператора и захотел сбросить button = customKeypad.getKey(); if (button=='C') // Еще раз проверяем, не хочет ли пользователь сбросить { num1=0; num2=0; total=0; operation=0; break; } if (button >='0' && button <='9') // Получение символов от клавиатуры для числа 2 { num2 = num2*10 + (button -'0'); u8g.setPrintPos(1,1); u8g.print(num2); } if (button == '=' && num2 !=0) { // Если нажата кнопка '=', то это конец пути. Вызываем функцию domath(), выполняющую расчет // и выводим результат. domath(); break; } } while(1) { // Когда всё выполнено, этот цикл ждет нажатия кнопки 'C', чтобы сбросить программу и начать с начала. // Это побочный эффект от предыдущего цикла, когда пользователь нажал 'C', предыдущий цикл прерывается // и переходит сюда. Поэтому мы должны также прервать и текущий цикл, иначе пользователю придется // нажимать 'C' дважды. if (button =='C') break; button = customKeypad.getKey(); if (button =='C') { u8g.setPrintPos(0,0); num1=0; num2=0; total=0; operation=0; break; } } } void domath() { switch(operation) { case '+': // Сложение total = num1+num2; break; case '-': // Вычитание total = num1-num2; break; case '/': // Деление // Может добавить ошибку деления на ноль, или измените строку во втором цикле, // где тот ожидает символа '=' на if (button == '=' && num2 != 0), это остановит программу // от дальнейших действий, пока num2 не будет отличаться от нуля. total = (float)num1/(float)num2; break; case '*': // Умножение total = num1*num2; break; } u8g.setPrintPos(0,1); u8g.print('='); u8g.setPrintPos(1,1); u8g.print(total); }
первым делом переставьте код функции domath() выше - между setup и loop. Возможно, что после этого и две другие ошибки исчезнут, потому как я не вижу, почему они возникают. Но вообще код, конечно, кривоватый. Автор похоже не понимает, зачем нужна функция loop и как она работает...
функция должна быть объявлена раньше чем использована - надо где-нибудь в начале (до лупа и сетапа) написать строчку void domath(void);
Переместил. Ругается компилятор. C:\Users\CD86~1\AppData\Local\Temp\untitled1662855145.tmp\sketch_dec24a\sketch_dec24a.ino: In function 'void loop()': sketch_dec24a:150: error: break statement not within loop or switch break; ^ C:\Users\CD86~1\AppData\Local\Temp\untitled1662855145.tmp\sketch_dec24a\sketch_dec24a.ino: At global scope: sketch_dec24a:154: error: expected unqualified-id before 'while' while(1) ^ exit status 1 break statement not within loop or switch
эта ошибка чаще всего возникает, если у вас в программе непарное число открывающих и закрывающих скобок. По коду в форуме довольно трудно это проверить, так что попробуйте найти сами.
вот тут скобка лишняя Код (C++): while(1) { // Второй цикл, он выполняется пока пользователь не нажмет '=' или 'C'. // И тогда будет выведен результат или сброшена программа. if (button =='C') break; // Это обрабатывает случай, когда пользователь нажал кнопку оператора и захотел сбросить button = customKeypad.getKey(); if (button=='C') // Еще раз проверяем, не хочет ли пользователь сбросить { num1=0; num2=0; total=0; operation=0; break; } if (button >='0' && button <='9') // Получение символов от клавиатуры для числа 2 { num2 = num2*10 + (button -'0'); do { u8g.setPrintPos(10,10); u8g.print(num2); } while(u8g.nextPage()); } } if (button == '=' && num2 !=0) { // Если нажата кнопка '=', то это конец пути. Вызываем функцию domath(), выполняющую расчет // и выводим результат. domath(); break; } } после while(u8g.nextPage());
Код (C++): if (button =='C') break; // Это обрабатывает случай, когда пользователь нажал кнопку оператора и захотел сбросить Чисто из интереса, каким образом может случиться такой случай???
Люди здорово, значит я решил заняться ардуинкой на ноутбуке с Windows XP, вобщем устанавливаю IDE для нее и сталкиваюсь во всех версиях что не запускается программа ну никак, работает только 1.6.3 но она выдает ошибки типо после собки ожидается ";" когда она там стоит что делать??
что-то неправильно устанавливается. У меня ардуино 1.8.2 и 1.8.3 работают на ХП и на компе и на ноуте.
а можете подсказать я вот с грехом по полам все установил но после загрузки 2 скечей стала показываться такая ошибка что делать ? Arduino: 1.8.5 (Windows XP), Плата:"Arduino/Genuino Uno" Скетч использует 2090 байт (6%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 50 байт (2%) динамической памяти, оставляя 1998 байт для локальных переменных. Максимум: 2048 байт. avrdude: ser_open(): can't set com-state for "\\.\COM25" Произошла ошибка при загрузке скетча
Спасибо за столь детальное объяснение, но, к сожалению, не все проблемы разрешились. Совсем. Но скетч уже спокойно проходит компиляцию, но после загрузки ничего толком не происходит. При нажатии 6, 7, 8 загораются два пикселя. При нажатии 5 загорается только 1 пиксель. С чем это связано? Чувствую себя каким-то гуманитарием... на всякий случай прилагаю финальную версию кода Код (C++): #include <U8glib.h> #include <Keypad.h> U8GLIB_ST7920_128X64 u8g(10, 11, 12, U8G_PIN_NONE); // настройка пинов long num1,num2 ; double total; char operation,button; const byte ROWS = 4; const byte COLS = 4; char keys[ROWS][COLS] = { {'1','2','3','+'}, {'4','5','6','-'}, {'7','8','9','*'}, {'C','0','=','/'} }; byte rowPins[ROWS] = {0,1,2,3}; // подключение к строкам клавиатуры byte colPins[COLS] = {4,5,6,7}; // подключение к столбцам клавиатуры Keypad customKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS); void domath(void); // Этот код выполняется только один раз: при включении платы void setup() { u8g.setFont(u8g_font_6x12); // Выбор шрифта } void loop() { //sprintf(num1, "%d",num2); // функция sprintf переведёт число в строковый массив // Циклы удобны для чтения нажатых кнопок клавиатуры while(1) { // Первый цикл. Здесь мы читаем клавиатуру и составляем наше первое число. // Он выполняется, пока мы не нажмем кнопку оператора, и цикл прервется, // или, если будет нажата кнопка 'C', всё начнется с начала. button = customKeypad.getKey(); // Чтение кнопки if (button=='C') // Если пользователь хочет сбросить набор первого числа { num1=0; num2=0; total=0; operation=0; } if (button >='0' && button <='9') // Если пользователь нажал на числовое значение, один символ за раз { num1 = num1*10 + (button -'0'); // Наши числовые значения лежат в диапазоне от 0 до 9, что означает, что это единицы. // Когда мы умножаем на 10, мы, по сути, добавляем 0 после числа. // Затем мы добавляем новое введенное число на место нуля. // Что касается (button -'0'), это простой трюк с таблице ASCII. Цифры 0...9 в таблице ASCII // это 48...57 (в десятичном виде), поэтому, вычитание '0' из любого из этих символов дает // соответствующее значение в десятичном виде. Например, символ '5' = 53 в десятичной системе // минус 48 (символ нуля) дает нам значение 5. // Если наше предыдущее число было, например, 25, мы получили 250 умножением его на 10, // а затем добавили 5, и получили 255, что и будет выведено на U8G. do { u8g.setPrintPos(0,10); // Выбор первой строки на U8G u8g.print(num1); // Печать текущего значения числа num1 } while(u8g.nextPage()); } if (num1 !=0 && (button=='-' || button=='+' || button=='*' || button=='/')) { // Если пользователь завершил ввод цифр operation = button; // запоминаем, какое математическое действие пользователь хочет выполнить do { u8g.setPrintPos(0,20); // установить курсор на строку 2 u8g.print(operation); // напечатать наш оператор } while(u8g.nextPage()); break; } } while(1) { // Второй цикл, он выполняется пока пользователь не нажмет '=' или 'C'. // И тогда будет выведен результат или сброшена программа. if (button =='C') break; // Это обрабатывает случай, когда пользователь нажал кнопку оператора и захотел сбросить button = customKeypad.getKey(); if (button=='C') // Еще раз проверяем, не хочет ли пользователь сбросить { num1=0; num2=0; total=0; operation=0; break; } if (button >='0' && button <='9') // Получение символов от клавиатуры для числа 2 { num2 = num2*10 + (button -'0'); do { u8g.setPrintPos(10,10); u8g.print(num2); } while(u8g.nextPage()); } if (button == '=' && num2 !=0) { // Если нажата кнопка '=', то это конец пути. Вызываем функцию domath(), выполняющую расчет // и выводим результат. domath(); break; } } while(1) { // Когда всё выполнено, этот цикл ждет нажатия кнопки 'C', чтобы сбросить программу и начать с начала. // Это побочный эффект от предыдущего цикла, когда пользователь нажал 'C', предыдущий цикл прерывается // и переходит сюда. Поэтому мы должны также прервать и текущий цикл, иначе пользователю придется // нажимать 'C' дважды. if (button =='C') break; button = customKeypad.getKey(); if (button =='C') { u8g.setPrintPos(0,0); num1=0; num2=0; total=0; operation=0; break; } } } void domath() { switch(operation) { case '+': // Сложение total = num1+num2; break; case '-': // Вычитание total = num1-num2; break; case '/': // Деление // Может добавить ошибку деления на ноль, или измените строку во втором цикле, // где тот ожидает символа '=' на if (button == '=' && num2 != 0), это остановит программу // от дальнейших действий, пока num2 не будет отличаться от нуля. total = (float)num1/(float)num2; break; case '*': // Умножение total = num1*num2; break; } do { u8g.setPrintPos(0,10); u8g.print('='); u8g.setPrintPos(10,10); u8g.print(total); } while(u8g.nextPage()); }