Вывод значения нажатой клавиши на экран

Добрый день.

никак не могу понять, что делаю не так. Суть в том, что мне надо вывести значение нажатой клавиши на экран. По отдельности все работает. Прерывание срабатывает, клавиатура читается, в Serial port значение клавиши выводится. На экранчик текст тоже выводится.

Но окгда вов ремя прерывания я преобразовываю char в char* что-то идет не так, получаемое значение не выводится на экран, хотя если переменную char* задать в явном виде, то она выводится. Подскажите, что не так.

#include <Keypad.h>
#include <TimerOne.h>  // Подключаем библиотеку
#include "U8glib.h"

U8GLIB_ST7920_128X64 u8g(10, 11, 12, U8G_PIN_NONE);  // настройка пинов

const byte ROWS = 4;  //four rows
const byte COLS = 4;  //three columns
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
char k;
char* u;
byte rowPins[ROWS] = { 6, 7, 8, 9 };  //connect to the row pinouts of the keypad
byte colPins[COLS] = { 2, 3, 4, 5 };  //connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void toggle() {
  k = keypad.getKey();
  if (k) {
  u = &k;
    Serial.print(k);
    Serial.print("    ");
    Serial.println(u);
  }
}

void setup() {
  Serial.begin(9600);
  Timer1.initialize(10000);  //в мкс
  Timer1.attachInterrupt(toggle);
}

void loop() {

    u8g.firstPage();
  do {
    u8g.setFont(rus6x12);
    u8g.drawStr(0, 22, "Тест 2");
        u8g.drawStr(0, 35, u);
  } while (u8g.nextPage());

    delay(1000);
}

Плохая идея работать с Serial в прерывании. Это очень медленная функция.

Кстати, печать указателя то вот так делается:

Serial.print(*u);

Замечание по использованию

Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются. Возможна потеря данный передаваемых по последовательному соединению (Serial data) в момент выполнения функциии обработки прерывания. Переменные, изменяемые в функции, должным быть объявлены как volatile.

Не нужно ничего делать в прерывании - из него нужно выходить как можно скорее. Поэтому заводите переменную-флаг, в прерывании просто поднимаете ее, а в loop() проверяете ее значение - если поднята, выполняете нужные вам действия и сбрасываете флаг.

может я че не понимаю, но это зачем вообще?

а вот то что кто то не делает переменную глобально, не менее важная проблема многих как и с миллис!)))

Напишите подробнее, что вы хотите получить. В вашем случае, Serial выводит строку, находящуюся по указателю u . А что там, после 1-го символа может быть - да что угодно)))


.

Поясните - нахрена вы это делаете? (преобразовываете char в char*)

на этот вопрос я возможно могу ответить)))
из за библиотеки #include “U8glib.h” но это не точно

Так не делается.

Вы присваиваете u адрес локального объекта, который существует только внутри функции toggle. А потом, в строке №44 пытаетесь использовать этот указатель на уже несуществующий объект.

Если Вам так приспичило, делайте u честным массивом и записывайте свою k в него, а не берите указатель. Только не забудьте добавить слово volatile к описанию u.

автор так и не написал, зачем ему это…
Поскольку U8glib наследует классу Print, в ней, естественно, должен быть отдельный метод для вывода единичного символа. Для печати переводить “из char в char*” специально не нужно.

А какая разница? Так не делается в любом случае, независимо от целей.

Евгений, товарищи, спасибо.

Char в Char* переводил, так как такой тип требовала функция вывода текста на экран. Но как оказалось единичное значение массива тоже подходит.

Volatilу добавить не получается, компилятор ругается, что значение должно быть const, а не меняться в произвольное время.

Тем не менее код заработал, спасибо.

#include <Keypad.h>
#include <TimerOne.h>  // Подключаем библиотеку
#include "U8glib.h"

U8GLIB_ST7920_128X64 u8g(10, 11, 12, U8G_PIN_NONE);  // настройка пинов

const byte ROWS = 4;  //four rows
const byte COLS = 4;  //three columns
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
char k;
char u[] = {'0'};
bool flag = 0;

byte rowPins[ROWS] = { 6, 7, 8, 9 };  //connect to the row pinouts of the keypad
byte colPins[COLS] = { 2, 3, 4, 5 };  //connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void toggle() {
  k = keypad.getKey();
  if (k) {
    flag = 1;
    u[0] = k;
  }
}

void setup() {
  Serial.begin(9600);
  Timer1.initialize(10000);  //в мкс
  Timer1.attachInterrupt(toggle);
}

void loop() {

if (flag == 1) {
  u8g.firstPage();
  do {
    u8g.setFont(rus6x12);
    u8g.drawStr(0, 22, "Тест 2");
    u8g.drawStr(0, 35, u);
  } while (u8g.nextPage());
flag = 0;
}

}

Массив не нужен, можно было исходный символ сразу выводить:

опять 25

и не получится, добавить надо

volatile char k;

зачем потом опять из ‘k’ в ‘u’ перекладывать?

Простите, это бред. Если Вы откроете любой словарь, увидите, что слово volatile означает изменчивый, непостоянный, быстро и неожиданно изменяющийся. (например, волатильные рынки)

Так как у Вас написано сейчас (без volatile) будет глючить. Причём глюки будут непостоянные, фантомные и “необъяснимые”.

Вы просто неправильно его туда вставили и не показали нам ни как вставляли, ни как ругалось.

Впрочем, если Вас устраивает, что будет глючить, оставляйте как есть, дело Ваше.

Возможно. Тогда если просто сделать как я вас понял, то:

#include <Keypad.h>
#include <TimerOne.h>  // Подключаем библиотеку
#include "U8glib.h"

U8GLIB_ST7920_128X64 u8g(10, 11, 12, U8G_PIN_NONE);  // настройка пинов

const byte ROWS = 4;  //four rows
const byte COLS = 4;  //three columns
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};

volatile char k;
bool flag = 0;


byte rowPins[ROWS] = { 6, 7, 8, 9 };  //connect to the row pinouts of the keypad
byte colPins[COLS] = { 2, 3, 4, 5 };  //connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void toggle() {
  k = keypad.getKey();
  if (k) flag = 1;
}

void setup() {
    Serial.begin(9600);
  Timer1.initialize(10000);  //в мкс
  Timer1.attachInterrupt(toggle);
}

void loop() {

  if (flag == 1) {
    u8g.firstPage();
    do {
      u8g.setFont(rus6x12);
      u8g.drawStr(0, 22, "Тест 2");
      u8g.drawStr(0, 32, k);
    } while (u8g.nextPage());
    flag = 0;
  }
}

Ошибки:

C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino: In function 'void loop()':
C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino:43:27: error: no matching function for call to 'drawStr(int, int, volatile char&)'
In file included from C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino:3:0:
c:\Users\������������\Documents\Arduino\libraries\U8glib\src/U8glib.h:171:16: note: candidate: u8g_uint_t U8GLIB::drawStr(u8g_uint_t, u8g_uint_t, const char*) <near match>
     u8g_uint_t drawStr(u8g_uint_t x, u8g_uint_t y, const char *s) { return u8g_DrawStr(&u8g, x, y, s); }
                ^~~~~~~
c:\Users\������������\Documents\Arduino\libraries\U8glib\src/U8glib.h:171:16: note:   conversion of argument 3 would be ill-formed:
C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino:43:27: warning: invalid conversion from 'char' to 'const char*' [-fpermissive]
In file included from C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino:3:0:
c:\Users\������������\Documents\Arduino\libraries\U8glib\src/U8glib.h:201:16: note: candidate: u8g_uint_t U8GLIB::drawStr(u8g_uint_t, u8g_uint_t, const __FlashStringHelper*) <near match>
     u8g_uint_t drawStr(u8g_uint_t x, u8g_uint_t y, const __FlashStringHelper *s) { return u8g_DrawStrP(&u8g, x, y, (u8g_pgm_uint8_t *)s); }
                ^~~~~~~
c:\Users\������������\Documents\Arduino\libraries\U8glib\src/U8glib.h:201:16: note:   conversion of argument 3 would be ill-formed:
C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino:43:27: warning: invalid conversion from 'char' to 'const __FlashStringHelper*' [-fpermissive]
grpc: error while marshaling: string field contains invalid UTF-8

Compilation error: no matching function for call to 'drawStr(int, int, volatile char&)'

В описании библиотеки нет функции write

userreference · olikraus/u8glib Wiki · GitHub

код хоть и компилируется в таком виде, но на дисплей ничего не выводит, кроме Тест 2

Вот правда, не зна, что Вы поняли, но я Вам писал про присваивание в массив, здесь же у Вас вообще нет массива (что правильно). Вы постоянно меняете вводные никогда не поймёшь о чём Вы говорите. Так как Вы делали выше - нельзя буду глюки. Здесь Вы пошли по верному пути, но сделали это неправильно.

Что Вам надо? Пояснить про это эти сообщения компилятора? Что они значат и что с ними делать?

Тогда лучше начну с начала.

С помощью прерывания по таймеру опрашивается клавиатура. Если нажата клавиша, то функция возвращает значение типа char, которая записывается в глобальную переменную k.

Значение нажатой клавиши я хочу вывести на экран, но, как я прочел в описании библиотеки, функция вывода на экран ожидает строку, а не символ, да еще и обязательно с символом конца строки, поэтому напрямую переменную k библиотека вывести не может.

Для этого я помещаю ее в массив U и вот его то (видимо массив воспринимается как строка) библиотека уже может вывести на экран.

Теперь вопросы:

  1. Массив U объявлен глобально, в прерывании он напрямую принимает значения k, я не совсем понимаю, почему могут быть проблемы.
  2. Если добавить volatile к массиву, выводятся ошибки:
C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino: In function 'void loop()':
C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino:45:25: warning: invalid conversion from 'volatile char*' to 'const char*' [-fpermissive]
In file included from C:\Users\Пользователь\Desktop\HelloKeypad\HelloKeypad.ino:3:0:
c:\Users\������������\Documents\Arduino\libraries\U8glib\src/U8glib.h:171:16: note:   initializing argument 3 of 'u8g_uint_t U8GLIB::drawStr(u8g_uint_t, u8g_uint_t, const char*)'
     u8g_uint_t drawStr(u8g_uint_t x, u8g_uint_t y, const char *s) { return u8g_DrawStr(&u8g, x, y, s); }
                ^~~~~~~
Скетч использует 9434 байт (3%) памяти устройства. Всего доступно 253952 байт.
Глобальные переменные используют 577 байт (7%) динамической памяти, оставляя 7615 байт для локальных переменных. Максимум: 8192 байт.
grpc: error while marshaling: string field contains invalid UTF-8

Compilation error: grpc: error while marshaling: string field contains invalid UTF-8

код:

#include <Keypad.h>
#include <TimerOne.h>  // Подключаем библиотеку
#include "U8glib.h"

U8GLIB_ST7920_128X64 u8g(10, 11, 12, U8G_PIN_NONE);  // настройка пинов

const byte ROWS = 4;  //four rows
const byte COLS = 4;  //three columns
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
char k;
volatile char u[] = {'0'};
bool flag = 0;

byte rowPins[ROWS] = { 6, 7, 8, 9 };  //connect to the row pinouts of the keypad
byte colPins[COLS] = { 2, 3, 4, 5 };  //connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void toggle() {
  k = keypad.getKey();
  if (k) {
    flag = 1;
    u[0] = k;
  }
}

void setup() {
  Serial.begin(9600);
  Timer1.initialize(10000);  //в мкс
  Timer1.attachInterrupt(toggle);
}

void loop() {

if (flag == 1) {
  u8g.firstPage();
  do {
    u8g.setFont(rus6x12);
    u8g.drawStr(0, 22, "Тест 2");
    u8g.drawStr(0, 35, u);
  } while (u8g.nextPage());
flag = 0;
}

}

Если volatile убрать, то код компилируется без ошибок и работает.

Конечно в идеале выводить значение k напрямую, но… попытки успехом не увенчались.

A u8g.print(‘h’) пробовали? Попробуйте отдельный символ.