Сб янв 07, 2017 17:08:52
Аlex писал(а):В 18B20 младшие 4 бита - дробное значение температуры. И без разницы, какое разрешение установлено. 4 бита - это 16. Отсюда, чтобы получить реальную температуру, значение нужно делить на 16.
Сб янв 07, 2017 19:11:57
int16_t ds18x20GetTemp(uint8_t num)
{
int16_t ret = devs[num].temp * 5;
if (devs[num].id[0] == 0x28) // DS18B20 has 8X better resolution
ret /= 8;
// Return value is in 0.1°C units
return ret;
}
Сб янв 07, 2017 19:23:12
возьмите калькулятор Windows, включите его в режим программиста и убедитесь, что описанное мною ранее полностью верно. делить нужно. то, что деление на 16 можно заменить сдвигом на 4, сути не меняет.levaclaus писал(а):Целое число не нужно делить.
Сб янв 07, 2017 19:58:14
Сб янв 07, 2017 20:05:14
ARV писал(а):возьмите калькулятор Windows, включите его в режим программиста и убедитесь, что описанное мною ранее полностью верно. делить нужно. то, что деление на 16 можно заменить сдвигом на 4, сути не меняет.levaclaus писал(а):Целое число не нужно делить.
Сб янв 07, 2017 20:17:35
Это-то так (хотя, вернее, с 4 по 11). Но всё равно, чтобы выделить этот байт, без промежуточных вычислений не обойтись. Самое простое - сдвинуть на 4 16-битное число (reg[0] и reg[1] - это байты температуры).откройте калькулятор и введите в него биты с 4 по 9 из таблицы ниже
int16_t temp = *(int16_t*)reg;
temp *= 10;
temp /= 16; // результат в десятых долях градуса
int8_t temp = __builtin_avr_swap((reg[0] & 0x0F) | (reg[1] & 0xF0)); // выделили целую часть из 4..11 битов
uint8_t temp10 = (reg[1] & 0x0F) * 10 / 16; // выделили дробную часть
if (temp < 0)
temp10 = 10 - temp10; // пересчитали для отрицательных температур
Сб янв 07, 2017 20:34:09
ок, давайте ваш вариант кода в студию! сравним, будет ли он проще, чем мой *temp / 16levaclaus писал(а):И ненужен не флоат, не интеджер. Достаточно signed char (максимально до 127 градусов)
Сб янв 07, 2017 20:39:26
Как не нужно ? Посмотрите внимательнее на картинкуlevaclaus писал(а):вот картинка из датащита
Целое число не нужно делить. Делить нужно только дробную часть. Если эта дробная часть нужна...
Сб янв 07, 2017 20:44:38
#define DS18X20_SCRATCH_LEN 9
#define DS18X20_ID_LEN 8
typedef union {
int16_t temp;
struct {
uint8_t sp[DS18X20_SCRATCH_LEN];
uint8_t id[DS18X20_ID_LEN];
};
} ds18x20Dev;
Сб янв 07, 2017 20:48:50
signed char temp=0;
unsigned char temp_10=0;
signed char ds18b20_temperature(void)
{
unsigned char LSB,MSB;
w1_init();
w1_write(0xCC);
w1_write(0xBE);
LSB=w1_read();
MSB=w1_read();
temp_10=LSB;
w1_init();
w1_write(0xCC);
w1_write(0x44);
delay_ms(800); //если 1f то убрать
return ((MSB<<4)&0xf0) | ((LSB>>4)&0x0f);
}
void ds_init(void)
{
w1_init();
w1_write(0x4e);
w1_write(0x64); //100
w1_write(0xD8);
w1_write(0x7f); //1f
delay_ms(15);
}
temp = ds18b20_temperature();
d2=temp/10; // десятки
d3=temp%10; // единицы
d4=(temp_10&0x0f)*10/16; //знак после запятой
Сб янв 07, 2017 21:00:52
у меня нет сомнений в вашей квалификации, и свой вопрос я адресовал не вамWiseLord писал(а):я чуть выше написал, как это предположительно выглядело бы
вы сами-то понимаете, какую ахинею вы несете? вы по своей табличке-то проверьте, которую приводили в начале странички...levaclaus писал(а):Дополнительный код распространяется только на целую часть, а дробная в прямом.
очень далеко не все: как минимум, вы не считываете весь scratchpad и не проверяете CRC принятых данных. одно это полностью противоречит даташиту.levaclaus писал(а):Все согласно датащиту
то есть вы продолжаете настаивать, чтоlevaclaus писал(а):Вот код, рабочий
проще и оптимальнее, чем предложенный мной вариантlevaclaus писал(а):((MSB<<4)&0xf0) | ((LSB>>4)&0x0f)
???ARV писал(а):*temp / 16
Сб янв 07, 2017 21:02:49
Вы очень сильно ошибаетесь. Дополнительный код распространяется на всё число, и Ваш код в плане temp10 - неверен.levaclaus писал(а):Дополнительный код распространяется только на целую часть, а дробная в прямом. Все согласно датащиту.
+10.125 0000 0000 1010 0010
-10.125 1111 1111 0101 1110
Сб янв 07, 2017 21:07:59
ARV писал(а):
то есть вы продолжаете настаивать, чтопроще и оптимальнее, чем предложенный мной вариантlevaclaus писал(а):((MSB<<4)&0xf0) | ((LSB>>4)&0x0f)
Сб янв 07, 2017 21:11:22
всё, я умолкаю - посрамлен и растоптанlevaclaus писал(а):либо integer и много много памяти для работы с ним
Сб янв 07, 2017 21:28:53
Они одинаковые всего-лишь из-за совпадения. +0.5(значение = +8) и -0.5(значение = -8) имеют одинаковые 4 младших бита.WiseLord писал(а):Да, для 0,5 и -0.5 дробная часть одинаковая. Но только для такой дробной части.
((MSB<<4)&0xf0) | ((LSB>>4)&0x0f)
Сб янв 07, 2017 21:50:07
Аlex писал(а):А вот этот код :эквивалентен сдвигу обоих байтов вправо на 4 и отбрасыванию старшего байта. Что и есть обычное деление на 16, только с туевой хучей ненужных операций
- Код:
((MSB<<4)&0xf0) | ((LSB>>4)&0x0f)
levaclaus, вы вместо выдвиганий своих мыслей за правду, взяли бы лучше бумажку с карандашиком и уделили бы этому вопросу немного времени, разрисовывая битики и байтики. И всё бы встало на свои места. Вопрос то элементарный, на уровне 5-ого класса.
Сб янв 07, 2017 21:55:08
Сб янв 07, 2017 22:01:38
это сильно... такая слава.... такая честь....levaclaus писал(а):Сжечь еретика-Коперника, он нам тут воздух портит
Сб янв 07, 2017 22:42:55
Я просто даже представить не могу, что вы там такого понаписали, что сдвиг 16-битной переменной занимает на 500 байт больше, чем вот такое :levaclaus писал(а):и 1,3 кбайта для варианта с integer
((MSB<<4)&0xf0) | ((LSB>>4)&0x0f)
Вс янв 08, 2017 00:28:35