LCD 192x64 по I2C BV4613 к Arduino DUE

Тема в разделе "Arduino & Shields", создана пользователем PIW2004, 22 окт 2013.

  1. PIW2004

    PIW2004 Нуб

    Родную библиотеку от данного контроллера экрана на DUE запустить не удалось, но получилось вывести информацию напрямую.
    Но для выводв текста его необходимо преобразовывать в ASCII код.
    На данный момент выводится Время с часов реального времени, для вывода приходится значение Часов, Минут и Секунд разбивать на два числа, потом каждое переводить в ASCII и только потом выводить каждое число.

    Сперва использовал вот такой вариант разложения на два числа:
    //Разделяем значение Часы, например 13 на 2 символа, 1 и 3int H1 = hour/10; //Получаем количество Десятков часов
    int H2 = hour-H1*10; //Получаем количество Едениц часов
    //Переводим каждую цифру числа 13 в ASCII код
    int h1 = char(H1+'0');
    int h2 = char(H2+'0');

    Потом нашел, что можно всё более изящно сделать при помощи функции itoa, но что то при её использовании выдаёт вот такую ошибку:

    Arduino: 1.5.4 (Windows 7), Board: "Arduino Due (Programming Port)"

    ekran.ino: In function 'void loop()':
    ekran:104: error: 'itoa' was not declared in this scope

    This report would have more information with
    "Show verbose output during compilation"
    enabled in File > Preferences.

    Вот пример используемого когда, для считывания времени с RTC, разбития значения на 2 числа, перевода полученных чисел в ASCII и вывода на дисплей.
    Код (Text):
    #include "Wire.h"
    //#include "BV4613.h"
    #include "stdio.h"
    #include "stdlib.h"

    #define DS1307_I2C_ADDRESS 0x68 //Адрес часов
       
    byte decToBcd(byte val)
    {
    return ( (val/10*16) + (val%10) );
    }
    byte bcdToDec(byte val)
    {
    return ( (val/16*10) + (val%16) );
    }
    void setDateDs1307(byte second,        // 0-59
                      char minute,        // 0-59
                      byte hour,          // 1-23
                      byte dayOfWeek,    // 1-7
                  byte dayOfMonth,    // 1-28/29/30/31
                  byte month,        // 1-12
                  byte year)          // 0-99
    {
    Wire.beginTransmission(DS1307_I2C_ADDRESS);
    Wire.write(0);
    Wire.write(decToBcd(second));  
    Wire.write(decToBcd(minute));
    Wire.write(decToBcd(hour));  
    Wire.write(decToBcd(dayOfWeek));
    Wire.write(decToBcd(dayOfMonth));
    Wire.write(decToBcd(month));
    Wire.write(decToBcd(year));
    Wire.endTransmission();
    }
       
    void getDateDs1307(byte *second,
                  byte *minute,
                  byte *hour,
                  byte *dayOfWeek,
                  byte *dayOfMonth,
                  byte *month,
                  byte *year)
    {
    Wire.beginTransmission(DS1307_I2C_ADDRESS);
    Wire.write(0);
    Wire.endTransmission();
       
    Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
          *second    = bcdToDec(Wire.read() & 0x7f);
          *minute    = bcdToDec(Wire.read());
          *hour      = bcdToDec(Wire.read() & 0x3f);
          *dayOfWeek  = bcdToDec(Wire.read());
          *dayOfMonth = bcdToDec(Wire.read());
          *month      = bcdToDec(Wire.read());
          *year      = bcdToDec(Wire.read());
    }
       
    void setup(){
    Serial.begin(9600);
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

    Wire.begin();
    delay (1500); //Ожидание пока экран прогрузится
    Wire.beginTransmission(0x32); //Соединение с экраном по адресе 0x32
     
    //Посылаем команду Очистка экрана
    Wire.write(0x1b); // esc
    Wire.write(0x5b); // [
    Wire.write(0x32);
    Wire.write(0x4a);
    //Посылаем команду Отключение курсора
    Wire.write(0x1b); // esc
    Wire.write(0x5b); // [
    Wire.write(0x3f); // ?
    Wire.write(0x32); //2
    Wire.write(0x35); //5
    Wire.write(0x49); //I
    //Посылаем команду Отключение прокрутки
    Wire.write(0x1b); // esc
    Wire.write(0x5b); // [
    Wire.write(0x3f); // ?
    Wire.write(0x32); //2
    Wire.write(0x36); //6
    Wire.write(0x6E); //n
    Wire.endTransmission();
    }


    void loop()
    {
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
    //Разделяем значение Часы, например 13 на 2 символа, 1 и 3
    int H1 = hour/10;
    int H2 = hour-H1*10;
    //Переводим каждую цифру числа 13 в ASCII код
    int h1 = char(H1+'0');
    int h2 = char(H2+'0');

    int hour1 = hour;
    char buff[6];
    itoa(hour1, buff, 10);

    Serial.println(hour1);
    Serial.println(buff);
    Serial.println(h1);
    Serial.println(h2);

    //Разделяем значение Минуты
    int M1 = minute/10;
    int M2 = minute-M1*10;
    //Переводим в ASCII код
    int m1 = char(M1+'0');
    int m2 = char(M2+'0');

    //Разделяем значение Секунды
    int S1 = second/10;
    int S2 = second-S1*10;
    //Переводим в ASCII код
    int s1 = char(S1+'0');
    int s2 = char(S2+'0');


    Wire.beginTransmission(0x32);
            //Переводим курсор на 4 строчку, 1 символо
            Wire.write(0x1b); // esc
            Wire.write(0x5b); // [
            Wire.write(0x30); //4
            Wire.write(0x3b); //;
            Wire.write(0x30); //1
            // Wire.write(0x32); //2
            Wire.write(0x48); //H
    //Рисуем часы      
    Wire.write(h1);//Отправляем первую цифру числа Часы в ASCCI коде
    Wire.write(h2);//Отправляем вторую цифру числа Часы в ASCCI коде
    Wire.write(":");
    Wire.write(m1);
    Wire.write(m2);
    Wire.write(":");
    Wire.write(s1);
    Wire.write(s2);

    Wire.endTransmission();
    delay(1000);
        }

    Вопрос, где ошибочка, почему не даёт использовать эту функцию (itoa) потому что родная бибилиотека для контроллера BV4613 использует её же.
     
  2. Unixon

    Unixon Оракул Модератор

    Может компилятор просто загловок не находит? Сделайте #include <>
     
  3. PIW2004

    PIW2004 Нуб

    Оказалось не ту библиотеку вставлял, для Arduino DUE она другая, в итоге удалось запустить родную библиотеку контроллера экрана BV4613, для подключения экрана по I2C.
    Удалось даже вывести простой Текст, но возникли 2 новых проблемки:
    1)Выводит только латиницу, как можно прикрутить поддержку кириллицы?

    2)Удалось вывести только текст, не могу вывести данные из переменной
    Для вывода текста используется вот такая команда:
    Код (Text):
    BV4613.WriteText(0,3,"1221");
    А вот так эта команда расписана в библиотеке BV4613.h :

    Код (Text):
    void BV4613::WriteText(int F,int C,char *Str,int Color)
    {
    Cursor_POS(F,C);
    WriteText(Str,Color);
    }

    //-----------------------------------------------------------------------------

    void BV4613::WriteText(TPointI P,char *Str,int Color)
    {
    SET_CursorPixel(P);
    WriteText(Str,Color);
    }

    //-----------------------------------------------------------------------------

    void BV4613::WriteText(char *Str,int Color)
    {
    if (gForeColor!=Color)
      SET_Inverse();

    SendI2C((unsigned char *)Str);

    //esperamos fin comando
    Wait_ACK();
    }
    Насколько я понимаю, Первый вариант, это вывод текста с указанием Строки и Символа, откуда начинать выводить текст.
    Второй, это вывод с заданного пикселя.
    Третий вариант, это вывод с ранее установленной позиции курсора.

    Вопрос, как в строке
    Код (Text):
    BV4613.WriteText(0,3,"1221");
    Вместо 1221 записать переменную?
    Если просто вставляю название переменной, то выдаёт ошибку:
    Код (Text):
    ekran_BV4613.ino: In function 'void loop()':
    ekran_BV4613:110: error: invalid conversion from 'byte' to 'char*'
    ekran_BV4613:110: error: initializing argument 3 of 'void BV4613::WriteText(int, int, char*, int)'
     
    Причём, в какомм бы формате не была эта переменная, будет выдавать эту ошибку, с изменением лиш from 'int ' to 'char* или from 'char' to 'char*
     
  4. Megakoteyka

    Megakoteyka Оракул Модератор

    Сначала переменную нужно преобразовать в текст, а затем передать текст.
    Попробуйте так:
    Код (Text):
    #include <itoa.h>

    char str[8 * sizeof (int) + 1];

    int main()
    {
      int value = 8;
      itoa(value, str, 10);
      return 0;
      ...
      BV4613.WriteText(0, 3, str);
    }
     
  5. PIW2004

    PIW2004 Нуб

    Получилось по Вашему примеру, но чуть изменил его.
    Написал вот так:
    Код (Text):
    char S[1];
    int s = second;
    itoa(s, S, 10);
    BV4613.WriteText(S);
    Выводит правильно, но одно неудобство, из часов в переменную second считываются секунды в формате 0,1,2,3,4....10,11,....59, а хотелось бы вывести 00,01,02,03,04....10,11...59.
    Как нолик в начале нарисовать?
     
    Последнее редактирование: 23 окт 2013
  6. Megakoteyka

    Megakoteyka Оракул Модератор

    char S[0]; - это зачем?

    if(s < 10)
    BV4613.WriteText("0");
    BV4613.WriteText(S);
     
  7. PIW2004

    PIW2004 Нуб

    Это вместо
    Код (Text):
    char str[8 * sizeof (int) + 1];
     
  8. Megakoteyka

    Megakoteyka Оракул Модератор

    Это понятно, что вместо. А зачем? Вы смысл данной строки кода понимаете?
    Любая строка имеет символ '\0' - он означает конец строки. В буфер размером 1 символ ничего, кроме конца строки не влезет. Если в этот буфер записать что-то еще, произойдет выход за его границы. Если в памяти после буфера лежит переменная - она будет испорчена. Буферы для строк не просто так объявляют максимально допустимой длины.
    В Вашем случае необходимо хотя бы 3 символа - 2 цифры и завершающий ноль.
     
    Последнее редактирование: 23 окт 2013
  9. PIW2004

    PIW2004 Нуб

    Спасибо за разъяснение, я примерно читал про размер буфера, что если его не определить, может работать не верно. Я только начинаю разбираться с контроллерами, многое пока непонятно, большей частью пользуюсь примерами, и пытаюсь разобраться, меняя параметры, что бы понять, какой за что отвечает, так что шибко не ругайтесь )
     
  10. Unixon

    Unixon Оракул Модератор

    В справочник поглядывайте, чтобы в коде глупости не писать.
     
  11. Megakoteyka

    Megakoteyka Оракул Модератор

    Код (Text):
    char str[8 * sizeof (int) + 1];
    Такой размер буфера нужен, если в двоичное представление переводить, а у нас десятичное, я поспешил и тоже глупость написал :)
    Если нужно перевести, скажем, количество секунд или минут в строку, то сперва нужно проверить, что данное значение >=0 и <60, т.е. займет не более 2х символов в строке и представляет собой осмысленное число. Тогда можно смело выделять буфер размером 3 символа для хранения строкового представления этого числа.