Как перевести код (DS18B20)

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Tom91
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт окт 08, 2010 15:43:55

Как перевести код (DS18B20)

Сообщение Tom91 »

Доброго времени суток!
Начал осваивать DS18B20, помогите разобраться как перевести 2 байтный код в численный ASCI код LCD.
SSSS SXXX XXXX XXXX - исходный код с DS18B20
SXXX XXXX X - тот что хочу преобразовывать (биты 0,1,2 откинул), где S - показатель знака, S=0 температура положительна, S = 1 - температура отрицательна. На LCD хочу получить что-то типа SXXX,X ,где S - знак.
Только хотелось бы увидеть код на ассемблере.
Реклама
Vov123
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Re: Как перевести код (DS18B20)

Сообщение Vov123 »

В CVAVR что-то типа этого sprintf(buf,"t%u=%i.%u\xdfC",++i,temp/10,abs(temp%10));
если температура отрицательная,будет знак - минус.
Вложения
Новая папка (8).rar
(30.81 КБ) 240 скачиваний
Реклама
Tom91
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт окт 08, 2010 15:43:55

Re: Как перевести код (DS18B20)

Сообщение Tom91 »

Vov123, спасибо конечно, но с CVAVR я не работаю.

Может кто сможет объяснить на ассемблере?
Аватара пользователя
Pavel V.
Мявтор!
Сообщения: 384
Зарегистрирован: Ср май 17, 2006 18:39:01
Откуда: Москва
Контактная информация:

Re: Как перевести код (DS18B20)

Сообщение Pavel V. »

Я до градусов округляю, десятые не использую. Вот пример:

Код: Выделить всё

uint16_t fullTemperature = (scratchpad[1] << 8) | scratchpad[0];
if(m_Roms[i].Bytes[0] == DS18B20) {
	m_Temperature[i] = (int8_t)(fullTemperature >> 4);
} else if (m_Roms[i].Bytes[0] == DS1920) {
	m_Temperature[i] = (int8_t)(fullTemperature >> 1);
} else {
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Хатуль_мадан
Электрический кот
Сообщения: 1007
Зарегистрирован: Ср мар 03, 2010 11:48:00
Откуда: Уфа

Re: Как перевести код (DS18B20)

Сообщение Хатуль_мадан »

Вам нужен пример реализации или понять принцип преобразования? В свое время тоже начинал его изучение и тоже на ассемблере для термостата, очень помогло русское описание на датчик от Чернова Г. посмотреть можно тут http://www.masterkit.ru/zip/ds18b20-rus.pdf. Там и примеры есть (тоже на ассемблере).
Реклама
Tom91
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт окт 08, 2010 15:43:55

Re: Как перевести код (DS18B20)

Сообщение Tom91 »

Вам нужен пример реализации или понять принцип преобразования?
Всё в одном флаконе.

Итак у меня есть SXXX XXXX X (биты 11-3 для DS18B20) , где S - показатель знака, далее я разложил:
S - при 1 состоянии вывожу минус на дисплей, с этим проблем нет, остаётся
XXXX XXXX(биты 10-3) - лежит в регистре TEMP, теперь как этот ТЕМР преобразовать в численные значения LCD ??

тоесть чтобы получилось SXXX,X, так как S - это знак температуры и его вывести проблем не составит, остаётся преобразовать ТЕМР для получения численного значения в формате XXX,X Кто что предложит?
Реклама
Аватара пользователя
Хатуль_мадан
Электрический кот
Сообщения: 1007
Зарегистрирован: Ср мар 03, 2010 11:48:00
Откуда: Уфа

Re: Как перевести код (DS18B20)

Сообщение Хатуль_мадан »

Ну если на пальцах, то датчик дает 12 разрядов измеряемой температуры (по умолчанию), причем 4 младших это дробная часть градуса, т.е 1/16=0,0625 дискретность замера. оставшиеся 8 разрядов (со знаком) это число соответствующее целым градусам в замере. В зависимости от того, что Вам нужно, такое количество разрядов и используете. Как реализовать, это дело вкуса каждого. Когда сам начинал изучение программирования, тоже искал свои пути решения. Вот предлагаю кусочек своей программы по Вашей задаче. Знатоков прошу не судить стого, возможно кое-что коряво, но работает.
PS:
Ну если кому интересно как, то это реализовано тут: http://radiokot.ru/konkurs/012/
Последний раз редактировалось Хатуль_мадан Вт янв 18, 2011 14:42:10, всего редактировалось 1 раз.
Аватара пользователя
Rimsky
Грызет канифоль
Сообщения: 299
Зарегистрирован: Вт июн 15, 2010 07:16:42
Откуда: Иркутск
Контактная информация:

Re: Как перевести код (DS18B20)

Сообщение Rimsky »

кое что из моего опыта
Вложения
1wire_dr.asm
(6.96 КБ) 434 скачивания
Tom91
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт окт 08, 2010 15:43:55

Re: Как перевести код (DS18B20)

Сообщение Tom91 »

.
Последний раз редактировалось Tom91 Ср янв 19, 2011 09:38:32, всего редактировалось 1 раз.
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Как перевести код (DS18B20)

Сообщение stas00n »

Tom91, вам нужно сначала преобразовать двоичное значение температуры в двоично-десятичное, поищите процедуры вроде bin2bcd, вот мой пример для беззнакового 8-бит целого:

Код: Выделить всё

_bin2bcd:
   ldi      r17,255
   ldi      r18,255
_calc_hundreds:
   inc      r18
   subi   r16,100
   brbc   sreg_c,_calc_hundreds
   subi   r16,156
_calc_tens:
   inc      r17
   subi   r16,10
   brbc   sreg_c,_calc_tens
   subi   r16,246
в r16 кладете двоичное значение, вызываете процедуру, из r18, r17, r16 забираете десятичные цифры. Поскольку у Вас число со знаком, то в случае если оно отрицательно (старший бит = 1), предварительно нужно взять его модуль (инвертировать и добавить единицу), а знак сохранить где-нибудь в другом регистре.
Дальше к каждой полученной двоично-десятичной цифре добавляете 0x30, получаете ASCII коды этих цифр. Дальше отправляете их на индикатор, тут уже сами разбирайтесь. Минус и запятую в виде ASCII кодов тоже отправляете в нужном месте.
Tom91 писал(а):SSSS SXXX XXXX XXXX
Вероятно, это значение лучше сперва прокрутить влево на 4 бита, чтобы старший байт был целой частью, младший - дробной (SXXXXXXX XXXX0000)
Tom91
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт окт 08, 2010 15:43:55

Re: Как перевести код (DS18B20)

Сообщение Tom91 »

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

Код: Выделить всё

com lbyte  
inc lbyte 
Вероятно, это значение лучше сперва прокрутить влево на 4 бита, чтобы старший байт был целой частью, младший - дробной (SXXXXXXX XXXX0000)
я старшие 4 бита даже считывать не собираюсь, а первые 3 пропускаю, S хранится отдельно

Дальше к каждой полученной двоично-десятичной цифре добавляете 0x30, получаете ASCII коды этих цифр.
непонятно почему тогда (код ниже) прибавляют не 30 ??? (исходник выше)

Код: Выделить всё

	subi digit1, -48				; подготовка к пересылке
		subi digit2, -48
		subi digit3, -48
		subi digit4, -48
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Как перевести код (DS18B20)

Сообщение stas00n »

Tom91 писал(а): тоесть если число отрицательное, то:

Код: Выделить всё

com lbyte  
inc lbyte 
Да. Но короче

Код: Выделить всё

neg lbyte
Tom91 писал(а): я старшие 4 бита даже считывать не собираюсь, а первые 3 пропускаю, S хранится отдельно
Уверены, что правильный результат получится? Я просто не работал с этими датчиками, не знаю в каком виде он данные дает.

Tom91 писал(а): непонятно почему тогда (код ниже) прибавляют не 30 ??? (исходник выше)

Код: Выделить всё

	subi digit1, -48				; подготовка к пересылке
		subi digit2, -48
		subi digit3, -48
		subi digit4, -48
Как раз 30 и прибавляют :) Точнее, не 30, а 0x30, что в десятичном виде составляет 48, а поскольку в AVR нет инструкции сложения с константой, но есть вычитание, то сложение выполнено в виде вычитания "минус константы". В данном случае (когда гарантировано 0 <= digitx <= 9) можно то же самое сделать операцией ИЛИ с константой, т.е. "дописать" тройку в старший нибл:

Код: Выделить всё

       ori      digit1, 0x30
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Как перевести код (DS18B20)

Сообщение stas00n »

Tom91 писал(а):я старшие 4 бита даже считывать не собираюсь, а первые 3 пропускаю, S хранится отдельно
Тогда диапазон корректного измерения температуры будет от минус 16 до плюс 15 градусов, устраивает?
Tom91
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт окт 08, 2010 15:43:55

Re: Как перевести код (DS18B20)

Сообщение Tom91 »

stas00n, а не могли бы вы пояснить свой код преобразований, тоесть описать алгоритм его работы...

Код: Выделить всё

_bin2bcd:
   ldi      r17,255
   ldi      r18,255
_calc_hundreds:
   inc      r18
   subi   r16,100
   brbc   sreg_c,_calc_hundreds
   subi   r16,156
_calc_tens:
   inc      r17
   subi   r16,10
   brbc   sreg_c,_calc_tens
   subi   r16,246
stas00n писал(а):
Tom91 писал(а):я старшие 4 бита даже считывать не собираюсь, а первые 3 пропускаю, S хранится отдельно
Тогда диапазон корректного измерения температуры будет от минус 16 до плюс 15 градусов, устраивает?
Почему?

SSSS SXXX XXXX XXXX - это 2байтный код с датчика обеспечивает 12разрядное разрешение, где S - показатель знака
Для 9 разрядного разрешения биты 0,1,2 откидываются что я и сделал, старшие 4 бита просто повторяют значения S, посути они ненужны, или я что-то не так понял?
В результате у меня остаётся только 9бит: S XXXX XXXX (приращение 0,5"С)
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Как перевести код (DS18B20)

Сообщение stas00n »

Tom91 писал(а):stas00n, а не могли бы вы пояснить свой код преобразований, тоесть описать алгоритм его работы...
Так наверное будет понятней:

Код: Выделить всё

_bin2bcd:
   ldi      r17, -1
   ldi      r18, -1
_calc_hundreds:
   inc      r18
   subi   r16,100
   brbc   sreg_c,_calc_hundreds
   subi   r16, -100
_calc_tens:
   inc      r17
   subi   r16,10
   brbc   sreg_c,_calc_tens
   subi   r16, -10
Просто асемблер у меня когда-то не дружил с отрицательными числами, поэтому я заменял их положительными "аналогами", процессору-то пофигу...
Алгоритм такой: сперва считаем сотни, для этого вычитаем из преобразуемого числа 100; если результат положительный (не было переноса) инкрементируем разряд сотен, если перенос случился, значит результат отрицательный и подсчет сотен закончен, переходим к подсчету десятков, предварительно вернув последнюю вычтенную сотню "назад"; аналогично с десятками, инкрементируем регистр десятков вычитая из числа по 10 и сравнивая результат с нулем (смотрим на бит переноса); потом возвращаем "назад" последний вычтенный десяток, после этого единицы получаются сами собой в r16. Регистры десятков и сотен инициализируются значением минус один, т.к. инкрементируются они до первой операции вычитания (так цикл короче получается).
Tom91 писал(а):Для 9 разрядного разрешения биты 0,1,2 откидываются что я и сделал, старшие 4 бита просто повторяют значения S, посути они ненужны, или я что-то не так понял?
Дык, "откидывать" надо младшие биты младшего байта, а вы откинули старшие, которые имеют наибольший вес. Там 12-битное знаковое число, содержащее целую (8 бит) и дробную (4 бита) части выровнено вправо, что в принципе, верно, а запятая получается между 3 и 4 битом младшего байта. Если сдвинуть значение влево на 4 бита, запятая придется аккурат между старшим и младшим байтом. Надо смотреть, как удобней считать будет.
Последний раз редактировалось stas00n Ср янв 19, 2011 00:02:18, всего редактировалось 1 раз.
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Как перевести код (DS18B20)

Сообщение stas00n »

Tom91
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт окт 08, 2010 15:43:55

Re: Как перевести код (DS18B20)

Сообщение Tom91 »

Дык, "откидывать" надо младшие биты младшего байта, а вы откинули старшие, которые имеют наибольший вес. Там 12-битное знаковое число, содержащее целую (8 бит) и дробную (4 бита) части выровнено вправо, что в принципе, верно, а запятая получается между 3 и 4 битом младшего байта. Если сдвинуть значение влево на 4 бита, запятая придется аккурат между старшим и младшим байтом. Надо смотреть, как удобней считать будет.
Вот именно что число 12 битное, а выгоняем из него 16 битное, тоесть:
SSSS SXXX XXXX XXXX - исходное число (16бит), откинул старшую тетраду:
SXXX XXXX XXXX - сама температура (12бит), откинул 0,1,2 биты :
S XXXX XXXX - температура (9бит)

Или я что-то не так понял?

+125'C 0000 0111 1101 0000
+25.0625'C 0000 0001 1001 0001
-55'C 1111 1100 1001 0000
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Как перевести код (DS18B20)

Сообщение stas00n »

В принципе и так можно, тогда двигать лучше на 3 бита вправо, заполняя старшие биты знаками (S). Вообще, как угодно, зависит от того, где предпочтительней запятую ставить. В любом случае, в один байт не укладываетесь, значит вычисления будут уже 16-битные..
Tom91
Встал на лапы
Сообщения: 108
Зарегистрирован: Пт окт 08, 2010 15:43:55

Re: Как перевести код (DS18B20)

Сообщение Tom91 »

Так SXXXX XXXX это сдвигаю вправо и кладу в r16 (S-учёт знака, тоесть если отриц перевожу, инверсия + 1), на выходе получаю
r18,r17,r16 - целые грудусы, но как быть с дробными, к тому же приращение при 9 битах 0,5"С Тоесть если всё правильно понимаю после запятой 0 или 5
Как реализовать такой алгорит
Последний раз редактировалось Tom91 Ср янв 19, 2011 01:41:42, всего редактировалось 1 раз.
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Как перевести код (DS18B20)

Сообщение stas00n »

Выровняйте, как я в начале рекомендовал сдвигом влево на 4 бита, младшие биты заполнить нулями, получится старший байт - целая часть, младший - дробная, запятая посередине; если старший бит целой части (15-й) равен единице, то бишь число отрицательно, берем модуль. Целую часть преобразуем вышеописанной процедурой, дробную еще проще - смотрим на старший бит дробной части (7-й), если он равен 0, то десятичная цифра после запятой 0, иначе - 5. Вообще, веса разрядов дробной части располагаются (слева направо) так: 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128, 1/256, - суть так же как и целой части, - следующий (влево) вдвое больше предыдущего, поэтому оперировать числами с фиксированной запятой можно так же как целыми.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»