реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Closed TopicStart new topic
> Что означает этот код?
RW6MKA
сообщение Mar 9 2014, 07:11
Сообщение #16


Частый гость
**

Группа: Участник
Сообщений: 163
Регистрация: 25-10-10
Из: Ростовская обл.
Пользователь №: 60 401



Цитата(aaarrr @ Mar 9 2014, 08:09) *
По приведенному к типу char адресу переменной записать ничего нельзя, это и не скомпилируется.
Это примерно как написать: 5 = 10;

Понял. Да, мог бы конечно и сам понять что в адрес ничего не запишешь, можно записать по указателю адреса.
Цитата
Переменная temp должна иметь тип как минимум short, чтобы в нее поместилось два char'а.

Но short вроде бы тип для целых чисел, а у меня переменная Temp потом будет преобразовывать свое содержимое из двух байт двоичного кода в десятичные показания температуры с точностью до десятых. И сама функция будет возвращать такое число. Поэтому я и спросил за float, может лучше это тип использовать?

Сообщение отредактировал RW6MKA - Mar 9 2014, 07:12
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 9 2014, 07:30
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Обычно из таких - низкоуровневых - функций данные в плавающей точке все же не вытаскивают. Но если очень хочется, то можно.
Другой вопрос, нужен ли будет на деле этот float потом.
Go to the top of the page
 
+Quote Post
RW6MKA
сообщение Mar 9 2014, 08:20
Сообщение #18


Частый гость
**

Группа: Участник
Сообщений: 163
Регистрация: 25-10-10
Из: Ростовская обл.
Пользователь №: 60 401



Цитата(aaarrr @ Mar 9 2014, 11:30) *
Обычно из таких - низкоуровневых - функций данные в плавающей точке все же не вытаскивают. Но если очень хочется, то можно.
Другой вопрос, нужен ли будет на деле этот float потом.

Хорошо, может это стрельба по воробьям из пушки. Какой тип вы для этой функции и переменной порекомендуете, если в результате функция должна вернуть число от -45,5 до 45,5 ?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 9 2014, 08:28
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(RW6MKA @ Mar 9 2014, 12:20) *
Какой тип вы для этой функции и переменной порекомендуете, если в результате функция должна вернуть число от -45,5 до 45,5 ?

Я бы оставил short, а привести/масштабировать всегда можно по месту.
Go to the top of the page
 
+Quote Post
SM
сообщение Mar 9 2014, 08:32
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(RW6MKA @ Mar 9 2014, 12:20) *
от -45,5 до 45,5 ?


Умножте это дело на 10, получите -455...455, это влезает в 16 битное целое с запасом.
Go to the top of the page
 
+Quote Post
RW6MKA
сообщение Mar 9 2014, 08:56
Сообщение #21


Частый гость
**

Группа: Участник
Сообщений: 163
Регистрация: 25-10-10
Из: Ростовская обл.
Пользователь №: 60 401



Во общем из советов я прихожу к выводу, что float лучше не использовать, а все постараться свести к типу целых чисел например int или short. Кстати вот еще вопрос, чем они отличаются? Как я понял и тот и тот тип могут быть 16 битным.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 9 2014, 09:13
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Могут. На 8-16 битных архитектурах ничем не отличаются. На архитектурах большей разрядности short может (по стандарту никто не обязывает) остаться 16 битным, а int соответствует разрядности процессора.
Go to the top of the page
 
+Quote Post
RW6MKA
сообщение Mar 9 2014, 09:35
Сообщение #23


Частый гость
**

Группа: Участник
Сообщений: 163
Регистрация: 25-10-10
Из: Ростовская обл.
Пользователь №: 60 401



Понятно. Тогда с учетом того, что я пишу код в AVRStudio под tiny2313 будет ли правильной вот эта функция
Код
uint16_t temp_18b20(){//функция получает с датчика данные с температурой в виде двух байт

    uint16_t temp = 0;
    if(TD_find()==1)//если устройство присутствует на шине
    {
        TD_sendcmd(0xcc);//пропустить ROM код, так ка датчик в устройстве один и не требуется идентификация
        TD_sendcmd(0x44);//команда датчику преобразовать температуру
        _delay_ms(750);//преобразование в 12 битном режиме занимает 750ms
        TD_find();//снова посылаем Presence и Reset
        TD_sendcmd(0xcc);
        TD_sendcmd(0xbe);//команда датчику передать байты (у 18b20 в первых двух байтах содержится температура)
        //читаем два байта с температурой и записываем оба байта в двух байтную переменную
        temp = TD_receive_byte();
        temp = (temp << 8) | TD_receive_byte();
        
    }
    //возвращаем температуру
    return temp;
}
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 9 2014, 09:38
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Правильнее будет int16_t, а не uint - результат ведь знаковый. И проверьте, что TD_receive_byte() возвращает char, а не больше.
Go to the top of the page
 
+Quote Post
SM
сообщение Mar 9 2014, 09:44
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(aaarrr @ Mar 9 2014, 13:38) *
Правильнее будет int16_t


Не совсем правильнее. Еще один момент есть - при таком раскладе, если Если TD_receive_byte() возвращаяет signed char, то операция temp = (temp << 8) | TD_receive_byte() убьет старший байт, если 7-ой бит там окажется в единице, и расширится до 16 бит. Так что, поосторожнее, надо бы на всяк случай написать temp = (temp << 8) | ((unsigned char)TD_receive_byte()). Вариант с прямой записью байтов на свои места по указателю в данном случае не имеет под собой таких "засад".
Go to the top of the page
 
+Quote Post
RW6MKA
сообщение Mar 9 2014, 09:48
Сообщение #26


Частый гость
**

Группа: Участник
Сообщений: 163
Регистрация: 25-10-10
Из: Ростовская обл.
Пользователь №: 60 401



Цитата(aaarrr @ Mar 9 2014, 13:38) *
Правильнее будет int16_t, а не uint - результат ведь знаковый. И проверьте, что TD_receive_byte() возвращает char, а не больше.

Нет, знак еще находится в коде, т.е. если 11-15 биты 1,то знак будет -. Так же и с дробной частью. Она заложена в 0-3 битах. Все это буду извлекать в отдельной функции с преобразованием в код LCD дисплея. Функция TD_receive_byte() возвращает uint8_t.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 9 2014, 10:06
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(RW6MKA @ Mar 9 2014, 13:48) *
Нет, знак еще находится в коде, т.е. если 11-15 биты 1,то знак будет -.

Это понятно. Но если Вы хотите, чтобы этот знак был учтен в дальнейшем, то результат должен быть знаковый:
short s = 0xffff;
unsigned short us = 0xffff;
float f;

f = s; // f = -1;
f = us; // f = 65535

Цитата(RW6MKA @ Mar 9 2014, 13:48) *
Функция TD_receive_byte() возвращает uint8_t.

Тогда порядок.
Go to the top of the page
 
+Quote Post
RW6MKA
сообщение Mar 9 2014, 10:15
Сообщение #28


Частый гость
**

Группа: Участник
Сообщений: 163
Регистрация: 25-10-10
Из: Ростовская обл.
Пользователь №: 60 401



Цитата(aaarrr @ Mar 9 2014, 14:06) *
Но если Вы хотите, чтобы этот знак был учтен в дальнейшем, то результат должен быть знаковый:

Понятно. Учту.
Спасибо всем за подробные ответы. Надеюсь и в дальнейшем на вашу помощь.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Mar 9 2014, 10:34
Сообщение #29


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Судя по стартовому посту темы, вопрос касался оптимизации кода, т.е. стремления избавиться от операции 8-кратного сдвига, который МК обычно не умеют делать одной инструкцией. А то и вызывают на этом месте библиотечную функцию, которая осуществляет сдвиги в цикле со счетчиком. Тогда как ответы в общем-то сводятся к тому, как этот сдвиг красивше записать. Т.е. в плане оптимизации эти ответы не только бесполезны, но и уже негативно проявили себя по части всевозможных ошибок при реализации.

В этом плане выражение
Код
*(char *)&Temp = TD_receive_byte();
*((char *)&Temp + 1) = TD_receive_byte();
было вполне оптимальным, с тем лишь недостатком, что оказалось непонятным топикстартеру. Т.е. его и надо было просто разъяснить, но не возвращаться к сдвигу.

На этот счет могу предложить альтернативу с union, которая в максимальной степени оптимальна, но гораздо проще в понимании:
Код
uint16_t temp_18b20()
{
  union {
    unsigned char byte[2];
    uint16_t word;
  } temp;

  ...
  temp.byte[1] = TD_receive_byte();
  temp.byte[0] = TD_receive_byte();
   ...
  return temp.word;
}

Здесь union располагает в одной и той же памяти 2 байта byte и одно слово word, тем самым, позволяя заполнить последнее по частям.
Go to the top of the page
 
+Quote Post
SM
сообщение Mar 9 2014, 10:41
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(Xenia @ Mar 9 2014, 14:34) *
т.е. стремления избавиться от операции 8-кратного сдвига, который МК обычно не умеют делать одной инструкцией.

Вот это, как раз, большинство 8-разрядных МК делают одной командой с легкостью, так как 16-битные регистры образуются из пар 8-битных, и такой сдвиг оптимизируется в пересылку сразу в нужный регистр.
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 17:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.01494 секунд с 7
ELECTRONIX ©2004-2016