Разделение целых чисел

У меня есть bluetooth (HC-05), подключенный к последовательному порту Arduino Mega и два TM1637, я получаю строки с телефона Android с приложением с двумя Time picker (Fajar и Zohar). Я посылаю время, которое задается тайм-пикером в форматированном виде.

Формат

< : Начало разделителя чисел.

ID : это число 1 или 2 (1 для Fajar и 2 для Zohar), оно указывает, из какого сборщика времени получены данные.

HH : Часы, установленные в устройстве выбора времени.

MM : Минуты, устанавливаются из программы выбора времени.

> : Разделитель конца числа.

Здесь в примере, первые данные, которые приходят это , которые имеют начальный разделитель "<" первая цифра "1" это ID от Fajar time picker, 03 часа и 20 минут и конечный разделитель ">". Вторая цифра - это данные от Zohar time picker и наоборот.

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

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

void setup ()
 { 
 Serial.begin (9600);
 Serial.println ("Starting ...");
 } // end of setup

void processNumber (const long n)
 {
 Serial.println (n);
 }  // end of processNumber

void processInput ()
 {
 static long receivedNumber = 0;
 static boolean negative = false;

 byte c = Serial.read ();

 switch (c)
   {

   case endOfNumberDelimiter:  
     if (negative) 
       processNumber (- receivedNumber); 
     else
       processNumber (receivedNumber); 

   // fall through to start a new number
   case startOfNumberDelimiter: 
     receivedNumber = 0; 
     negative = false;
     break;

   case '0' ... '9': 
     receivedNumber *= 10;
     receivedNumber += c - '0';
     break;

   case '-':
     negative = true;
     break;

   } // end of switch  
 }  // end of processInput

void loop ()
 {

 if (Serial.available ())
   processInput ();

 // do other stuff here
 } // end of loop

С помощью приведенного выше кода я могу преобразовать строку в целые числа и удалить разделители.

Смотрите вывод кода в последовательном мониторе.

Проблема в следующем: Мне нужно отделить ID, часы и минуты от целого числа и завернуть часы и минуты в целое число.

int8_t Digits [] = {1, 2 , 3 , 4 };

Здесь {1,2,3,4} это {H,H,M,M} Часы и минуты, которые отображают цифры на одном из TM1637.

а также ID с "1" должен изменить цифры на одном из TM167, а ID с "2" должен изменить цифры на другом TM1637.

Вот мой полный код:

#include "TM1637.h"

#define CLK1 2
#define DIO1 3

#define CLK2 4
#define DIO2 5

TM1637 Display1 (CLK1, DIO1);

TM1637 Display2 (CLK2, DIO2);

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

void setup ()
{
  Display1.set ();
  Display1.init ();

  Display2.set();
  Display2.init();

  Serial.begin(9600);
  Serial.println ("Starting ...");
}

void loop ()
{
  if (Serial.available ())
    processInput ();
  fajar();
  zohar();
}

void processNumber (const long n)
{
  Serial.println (n);
}  // end of processNumber

void processInput ()
{
  static long receivedNumber = 0;
  static boolean negative = false;

  byte c = Serial.read ();

  switch (c)
  {

    case endOfNumberDelimiter:
      if (negative)
        processNumber (- receivedNumber);
      else
        processNumber (receivedNumber);

    // fall through to start a new number
    case startOfNumberDelimiter:
      receivedNumber = 0;
      negative = false;
      break;

    case '0' ... '9':
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;

    case '-':
      negative = true;
      break;

  } // end of switch
}  // end of processInput

void fajar ()
{
  int8_t Digits [] = {1, 2 , 3 , 4 };
  Display1.display (Digits);
  Display1.point(POINT_ON);
}

void zohar ()
{
  int8_t Digits [] = {1, 2 , 3 , 4 };
  Display2.display (Digits);
  Display2.point(POINT_ON);
}

Пожалуйста, помогите

EDIT : Вот мой отредактированный код с показанной техникой Маженко.

#include "TM1637.h"

#define CLK1 2
#define DIO1 3

#define CLK2 4
#define DIO2 5

uint8_t fajar[4];
uint8_t zohar[4];

uint8_t address = 0;
uint8_t ptr = 0;

TM1637 Display1 (CLK1, DIO1);

TM1637 Display2 (CLK2, DIO2);
void setup ()
{
  Display1.set ();
  Display1.init ();

  Display2.set();
  Display2.init();

  Serial.begin(9600);
}

void loop ()
{
  int c = Serial.read();
  switch (c) {
    case '<': // Start of string - reset everything
      address = 0;
      ptr = 0;
      break;
    case '>': // End of string

       fajartime (); // Edited 
       zohartime (); // Edited

      break;
    default:
      if ((c >= '0') && (c <= '9')) {
        if (address == 0) {
          address = c - '0';
        } else if (ptr < 4) {
          switch (address) {
            case 1:
              fajar[ptr] = c - '0';
              break;
            case 2:
              zohar[ptr] = c - '0';
              break;
          }
          ptr++;
        }
      }
  }
}

void fajartime ()
{

  Display1.display (fajar);
  Display1.point(POINT_ON);
}

void zohartime ()
{

  Display2.display (zohar);
  Display2.point(POINT_ON);
}

Спасибо

Решение

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

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

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

Простая конечная государственная машина для правильного приема облегчит работу:


uint8_t fajar[4];
uint8_t zohar[4];
uint8_t address = 0;
uint8_t ptr = 0;

int c = Serial.read();
switch (c) {
    case '': // End of string
        // Do whatever with the data here
        break;
    default: 
        if ((c >= '0') && (c 
Комментарии (7)

Я не уверен, что понимаю, в чем вам нужна помощь. У вас есть код, который считывает строку из 5 символов между .

  • Если i == 1, вы передаете оставшиеся 4 символа в fajar.
  • Если i == 2, вы передаете оставшиеся 4 символа в zohar.

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

TM1637 Displays[2] = {(CLK1, DIO1), (CLK2, DIO2)};
void loop()
{
    char buffer[1 + 5 + 1 + 1];
    buffer = readNumber (buffer);
    if (buffer[0] == '1')          // Treating as a character not a number.
        fajar(&(buffer[1]));
    else
        zohar(&(buffer[1]));
}
void fajar(char const* buffer) { displayValue(1, buffer);}
void zohar(char const* buffer) { displayValue(2, buffer);}
void displayValue (const int& displayID, char const* buffer)
{
    int numericValues[4];
    convertToNumbers (buffer, numericValues);  // The code in the switch statement.
    Display[displayID].display (numericValues);
    Display[displayID]..point(POINT_ON);
}

Приведенный выше код - это только руководство, он никогда не компилировался, и в нем много проблем, которые могут, в случае получения плохих данных, привести к серьезной проблеме. Вам придется добавить проверку ошибок и границ, прежде чем вы сделаете что-то большее, чем dev-тестирование, но это должно работать :)

Комментарии (0)