Преобразование char в uin16_t и uint8_t

serenya
Offline
Зарегистрирован: 17.02.2012

Никак не могу понять что такое uint16_t и uint8_t, у меня стоит задача коррекции времени в RTC DS1302, пользуюсь такой библиотекой. В экземплах для изменения времени служат такие строчки:

  /* Make a new time object to set the date and time */
  /*   Tuesday, May 19, 2009 at 21:16:37.            */
  Time t(2009, 5, 19, 21, 16, 37, 3);

  /* Set the time and date on the chip */
  rtc.time(t);

 В библиотеке переменные объявлены так:

  uint8_t sec;
  uint8_t min;
  uint8_t hr;
  uint8_t date;
  uint8_t mon;
  uint8_t day;
  uint16_t yr;

У себя в начале скетча я их так же объявил, может быть не надо, но так хоть что-то работает.

Далее в скетче у меня присваиваются им значения и отправляются в часы:

  yr = 2012;
  mon = 2;
  date = 19;
  hr =16;
  min = 23;
  sec = 00;
  day = 7;
 /* Make a new time object to set the date and time */
  Time t(yr, mon, date,
         hr, min, sec,
         day);
  /* Set the time and date on the chip */
//  Serial.println(Time);
  rtc.time(t);

На часах меняется время, т.е. работает. Но мне необходимо изменять время через UART и терминал. Принимаю данные в char:

void SetTime()
{
  Serial.println("SetTime");
  while(Serial.available() == 0){}
  delay(100); 
  int i=0;
  if(Serial.available() > 0) {
    char yr_[4];
    int i;
    for (i = 0; i < 4; i++) {
    yr_[i] = Serial.read();
    }
    yr_[i] = '\0';
  if ( strstr(yr_, "2012") != NULL )
  {
  Serial.println("OK");
  }
  Serial.println(yr_);

и при попытке подставить принятые данные

yr = yr_;

получаю ошибку:

error: invalid conversion from 'char*' to 'uint16_t'

а при попытке

mon = mon_;

получаю ошибку:

error: invalid conversion from 'char*' to 'uint8_t'

что в принципе объяснимо, т.к. типы данных разные. Вот и возник вопрос как сконвертировать char в  uint8_t и uint16_t.

Заранее спасибо всем откликнувшимся.

step962
Offline
Зарегистрирован: 23.05.2011

serenya пишет:

[...]

получаю ошибку:

error: invalid conversion from 'char*' to 'uint8_t'

что в принципе объяснимо, т.к. типы данных разные. Вот и возник вопрос как сконвертировать char в  uint8_t и uint16_t.

Заранее спасибо всем откликнувшимся.

Вы определили yr_ как массив из четырех элементов типа char. При этом:

- выделяется область памяти длиной 4 байта для размещения четырех элементов типа char

- в переменную yr_ записывается адрес этой области.

Кстати сама переменная имеет тип не char, а char * (адрес элемента типа char или другими словами - указатель на char). Любое прямое обращение к переменным подобных типов - это арифметика указателей (или адресная арифметика). Дело достаточно опасное. Настолько опасное, что компилятор не допускает неявного преобразования между обычными типами данных и указателями на обычные типы данных. Если, тем не менее хочется, необходимо использовать явное преобразование типов (и брать всю полноту ответственности за последствия на себя).

Хотите подавить сообщение об ошибке - напишите

yr=(uint16_t)yr_;

 Для mon/mon_ аналогично.

 

Только это никак не поможет вам в деле преобразования строки в числовое значение.

serenya
Offline
Зарегистрирован: 17.02.2012

Спасибо, ошибка пропала.

step962 пишет:

Только это никак не поможет вам в деле преобразования строки в числовое значение.

В каком смысле?

step962
Offline
Зарегистрирован: 23.05.2011

serenya пишет:

В каком смысле?

К сожалению, я привык, что в мире Arduino народ слишком часто не делает различия, например, между 7 и '7', между 3287 и "3287". Ну и так далее.

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

Если же вы получаете числовое значение для года с помощью оператора

yr = (uint16_t)yr_;

то очень советую вывести полученное таким образом значение yr в терминал и сравнить его с ожидаемым.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

serenya пишет:

и при попытке подставить принятые данные

yr = yr_;

получаю ошибку:

error: invalid conversion from 'char*' to 'uint16_t'

а при попытке

mon = mon_;

получаю ошибку:

error: invalid conversion from 'char*' to 'uint8_t'

 

Проблема в несоответствии типов. Если у Вас yr_ объявлена как String (если нет, то необходимо преобразовать), то Вам необходимо:

yr=yr_.toInt();

Смотрите стандартный пример "StringToInt"

 

serenya
Offline
Зарегистрирован: 17.02.2012

AlexFisher пишет:

Проблема в несоответствии типов. Если у Вас yr_ объявлена как String (если нет, то необходимо преобразовать), то Вам необходимо:

yr=yr_.toInt();

Смотрите стандартный пример "StringToInt"

 

У меня yr_ объявлена как char*

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

serenya пишет:

У меня yr_ объявлена как char*

Тогда Вас спасёт конструкция:

yr=String(yr_).toInt();

 

serenya
Offline
Зарегистрирован: 17.02.2012

Попробовал так написать:

  yr = String(yr_).toInt();
  Serial.println(yr);

не получилось, в ответ пустая строка с переводом каретки.

step962
Offline
Зарегистрирован: 23.05.2011

serenya пишет:

Попробовал так написать:

  yr = String(yr_).toInt();
  Serial.println(yr);

не получилось, в ответ пустая строка с переводом каретки.

Перепишите так:

yr = String(yr_).toInt();
Serial.print(yr_);
Serial.print(" -> ");
Serial.println(yr);

Будет больше информации для анализа. А то мало-ли: может быть, вы и стороку-то еще не приняли...

serenya
Offline
Зарегистрирован: 17.02.2012

step962 пишет:

Будет больше информации для анализа. А то мало-ли: может быть, вы и стороку-то еще не приняли...

Serial.print(yr_);

Это я проверяю чуть раньше по коду, все в норме. Может мне выложить весь код для большей ясности?

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Похоже, или при преобразовании в String что-то теряется, или указатель к этому моменту уже не указывает на начало строки (что более вероятно).

Вам надо сделать как в примере:

String yr_;
...
yr_="";
while (Serial.available() > 0) yr_+=Serial.read();
yr=yr_.toInt();

 

hugoboss317
Offline
Зарегистрирован: 21.03.2013

Немного струсю пыль с темы, достав её из закрамов форума. 

объявляется локальная беззнаковая переменная uint8_t var; и так должно быть дальше. Как преобразовать тип в двух или четырёх байтную беззнаковую. 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Если неявное преобразование не проходит, сделайте явное (основы си):

uint8_t x=20;
uint16_t y;
...
y=(uint16_t)x;

 

hugoboss317
Offline
Зарегистрирован: 21.03.2013

Теперь х это тип uint16_t ?

Нет, не совсем.

 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

тип у х не изменится, это просто "явное" указание компиллятору "привести значение к типу uint16_t и положит в y". Используется когда нужно присвоить значение переменной, когда типы не совпадают. Таким образом программист "снимает ответственность с компиллятора" за корректность присвоения.

hugoboss317
Offline
Зарегистрирован: 21.03.2013

Тогда у меня большие проблемы ((

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Преобразовать тип у переменной нельзя, но если есть необходимость по ходу программы рассматривать ее то как один тип, то как другой, то есть 2 пути: Завести переменную максимальной длины, обращаться к ней по ссылке (пользуясь тем, что младший байт хранится в памяти первым), но это не совсем понятно, особенно "со стороны". Рассмотрите структуру "union" - она позволяет обращаться к одной и той же переменной, но по-разному. Только почитайте сами, ее нужно "вкурить", иначе вопросов будет много, а теорезировать не очень хочется.

hugoboss317
Offline
Зарегистрирован: 21.03.2013

Принято, попробуем. 

Да, как я и говорил у меня проблемы.

Неужели такую мелоч как преобразовать тип переменной нельзя решить?

Я было попробовал провернуть фокус с указателем на нечно (void* counter), только ему присвоить тип не получилось. подскажите что можно сделать?

или как из грёбаной uint8_t сделать uint32_t   ?

или что не так с указателем делаю ?

int var = 5;    //как всегда
void *count;    //указатель  ни на что
count = &var;   //присвоили адрес переменной
(int*)count;    //приводим тип указателю
 

 

axill
Offline
Зарегистрирован: 05.09.2011

Без понимания вашей задачи вам сложно помочь

опишите лучше какой конечный результат нужен, ведь само по себе преобразование типа не самоцель

hugoboss317
Offline
Зарегистрирован: 21.03.2013

axill пишет:

Без понимания вашей задачи вам сложно помочь

опишите лучше какой конечный результат нужен, ведь само по себе преобразование типа не самоцель

Да, Вы правы, прошу прощения.

Библиотека для LCD от siemens S65. Размер шрифта задаётся перед компелированием. Я добавил функцию вывора шрифта. Всё здорово, но.... шрифт можно выбрать с шириной от 9 до 16 пикселей. Дело в том, что в функции вывода символа ( drawChar ) обьявляется переменная (в моём случаи её размер 2 байта) в которую помешается два байта сивола (ширина). А если я выберу шрифт, к примеру 6х8, эта же переменная( с таким же именем) должна иметь размер 1 байт, т.к. ширина символа помешается в 1 байт.

uint16_t data, mask;   //мои переменные

вот примерно почему нужен разный тип

if (FONT_WIDTH <= 8){
      data = pgm_read_byte(ptr); ptr+=1;} // byte
else if (FONT_WIDTH <= 16){
      data = pgm_read_word(ptr); ptr+=2;} //world
else if (FONT_WIDTH <= 32){
      data = pgm_read_dword(ptr); ptr+=4;} //dworld

 

hugoboss317
Offline
Зарегистрирован: 21.03.2013

Ладно, нет ответа, а у меня нет больше мыслей. Тогда пробую пойти другим путём используя восьмибитную переменную.

Простая просьба, раскоментируйте следующее (там где вопросы):



   uint16_t data, mask;          //обьявили и ладно
.....
  data = pgm_read_word(ptr); ptr+=2;}   //бла бла бла инициализировали
.....
   for(mask=(1<<(width-1)); mask!=0; mask>>=1) //width- ширина символа = 12.
                     //как тут оператор for проводит вычисление?
      {
        if(data & mask)  // как это условие звучит ?
          .......

 

axill
Offline
Зарегистрирован: 05.09.2011

Вы уже все сделали, в чем проблема? Только data надо обьявить как uint32_t

hugoboss317
Offline
Зарегистрирован: 21.03.2013

Пля.я.я, обьявить четерёхбайтную переменную и "класть" в неё столько байт, сколько надо. axill , а раньше Вы где были? 

Проверел, работает. Спасибо.

И попутно понял о чём спрашивал в предидущем посте.