Склеивание двух переменных типа char в переменную типа int

Тема в разделе "Arduino & Shields", создана пользователем Злая Птичка, 20 сен 2012.

  1. Нужно склеить две переменные типа char в одну типа int.
    (а именно - склеить hoursO и hoursT - они типа char - в переменную hours типа int)
    Вот код, пока не готовый:
    Код (Text):
    // Подключаем стандартную библиотеку LiquidCrystal
    #include <LiquidCrystal.h>
     
    // Инициализируем объект-экран, передаём использованные
    // для подключения контакты на Arduino в порядке:
    // RS, E, DB5, DB6, DB7, DB8
    LiquidCrystal lcd(4, 5, 10, 11, 12, 13);
    void setup()
    {
    Serial.begin(9600);
    Serial.println("Ready");
    Serial.println("");
    }
    void loop()
    {
    if(Serial.available() > 0 && char(Serial.read()) == 't')
    {
    spillDate();
    }
    }
    void spillDate(){
    // передаем дату вот так: tчасыминутысекунды
    // например так: t094501
    // или так: t102534
    char hoursO = char(Serial.read());
    char hoursT = char(Serial.read());
    // здесь нужно склеить hoursO и hoursT в переменную hours типа int
    }
     
  2. Megakoteyka

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

    сперва нужно перевести символ, хранящийся в чаре, в число. Для этого отнимаем от чара код символа 0 (ноль). Посмотрите ASCII-таблицу, все станет понятно. Затем сдвигаем старший байт на 8 разрядов влево и прибавляем младший байт.

    int hours = (hourO - 48) << 8 | (hourT - 48);
    либо
    int hours = (hourO - (int)'0') << 8 | (hourT - (int)'0');
    Вы это имели ввиду?
     
  3. Сейчас проверим...
     
  4. Не работает. Вот код:
    Код (Text):
    // Подключаем стандартную библиотеку LiquidCrystal
    #include <LiquidCrystal.h>
     
    // Инициализируем объект-экран, передаём использованные
    // для подключения контакты на Arduino в порядке:
    // RS, E, DB5, DB6, DB7, DB8
    LiquidCrystal lcd(4, 5, 10, 11, 12, 13);
    void setup()
    {
    Serial.begin(9600);
    Serial.println("Ready");
    Serial.println("");
    }
    void loop()
    {
    if(Serial.available() > 0 && char(Serial.read()) == 't')
    {
    spillDate();
    }
    }
    void spillDate(){
    // передаем дату вот так: tчасыминутысекунды
    // например так: t094501
    // или так: t102534
    char hoursO = char(Serial.read());
    char hoursT = char(Serial.read());
    int hours = (hoursO - (int)'0') << 8 | (hoursT - (int)'0');
    Serial.print("Your time: ");
    Serial.print(hours);
    // здесь нужно склеить hoursO и hoursT в переменную hours типа int
    }
    Выводит Your time: -49 при любом значении.
     
  5. Megakoteyka

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

    Перед чтением очередного символа неплохо бы убедиться, что символ принят портом (Serial.availale()), и лишь затем читать его. Иначе Serial.read() возврашает -1.
     
  6. Megakoteyka

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

    Вот так все работает.
    Я сперва по привычке сдвинул старший байт на 8, т.к. привык передавать значения в тексте в hex-е.
    void spillDate()
    {
    while(Serial.available() == 0) ;
    char hoursO = (char)Serial.read();
    while(Serial.available() == 0) ;
    char hoursT = (char)Serial.read();
    int hours = ((hoursO - 48) * 10) | (hoursT - 48);
    Serial.print("Your time: ");
    Serial.println(hours, DEC);
    }
     
  7. Megakoteyka

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

    Кстати, не обязательно передавать пустую строку в функцию Serial.println() - она выведет пустую строку и при вызове без аргументов.
     
  8. Код (Text):
    Перед чтением очередного символа неплохо бы убедиться, что символ принят портом (Serial.availale()), и лишь затем читать его. Иначе Serial.read() возврашает -1.
    Я так и делаю :) Повнимательнее код читайте!
     
  9. Megakoteyka

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

    Вы так делаете при приеме только символа 't'. А нужно при приеме любого символа.
    А еще лучше - сперва собрать полный пакет и затем его обрабатывать.
     
  10. Megakoteyka

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

    Вы делаете так:
    char hoursO = char(Serial.read());
    char hoursT = char(Serial.read());
    А надо так:
    while(Serial.available() == 0) ;
    char hoursO = (char)Serial.read();
    while(Serial.available() == 0) ;
    char hoursT = (char)Serial.read();



    Так что взаимно желаю Вам внимательней читать код :)
     
  11. Megakoteyka, спасибо, работает.
     
  12. Код (Text):
    Вы так делаете при приеме только символа 't'. А нужно при приеме любого символа.
    Почему нужно? Мне так надо.
     
  13. Код (Text):
    // Подключаем стандартную библиотеку LiquidCrystal
    #include <LiquidCrystal.h>
     
    // Инициализируем объект-экран, передаём использованные
    // для подключения контакты на Arduino в порядке:
    // RS, E, DB5, DB6, DB7, DB8
    LiquidCrystal lcd(4, 5, 10, 11, 12, 13);
    void setup()
    {
    Serial.begin(9600);
    Serial.println("Ready");
    Serial.println("");
    }
    void loop()
    {
    if(Serial.available() > 0 && char(Serial.read()) == 't')
    {
    spillDate();
    }
    }
    void spillDate()
        {
        while(Serial.available() == 0) ;
        char hoursO = (char)Serial.read();
        while(Serial.available() == 0) ;
        char hoursT = (char)Serial.read();
        int hours = ((hoursO - 48) * 10) | (hoursT - 48);
        while(Serial.available() == 0) ;
        char minutesO = (char)Serial.read();
        while(Serial.available() == 0) ;
        char minutesT = (char)Serial.read();
        int minutes = ((minutesO - 48) * 10) | (minutesT - 48);
        while(Serial.available() == 0) ;
        char secondsO = (char)Serial.read();
        while(Serial.available() == 0) ;
        char secondsT = (char)Serial.read();
        int seconds = ((secondsO - 48) * 10) | (secondsT - 48);
        }
     
  14. Megakoteyka

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

    Советую принимать данные примерно таким способом:

    #define PACKET_SIZE 7
    char packet[PACKET_SIZE + 1];

    void setup()
    {
    packet[PACKET_SIZE] = '\0';
    Serial.begin(9600);
    Serial.println("Ready");
    Serial.println();
    }

    void loop()
    {
    if(Serial.available() >= PACKET_SIZE && Serial.peek() == 't')
    {
    for(int i = 0; i < PACKET_SIZE; i++)
    packet = (char)Serial.read();
    Serial.print("Received packet: ");
    Serial.println(packet);
    }
    }

    Плюсы подхода:
    - скетч не будет висеть в ожидании символов
    - принимать пакет и обрабатывать его - более грамотный подход, нежели пытаться разобрать пакет на лету. Проще разделить функционал - на принимающую часть и обрабатывающую.
     
  15. mike124

    mike124 Нерд

    А что, прерывания по сериал в Ардуине отменены? Мучаете контроллер какими-то глупыми циклами... Контроллер должен спать, а не циклиться впустую.
     
    Злая Птичка нравится это.