﻿define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>/dev/head &#187; avr</title>
	<atom:link href="http://devhead.ru/cat/avr/feed" rel="self" type="application/rss+xml" />
	<link>http://devhead.ru</link>
	<description>Статьи и видео уроки</description>
	<lastBuildDate>Mon, 30 Jan 2017 11:12:34 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.37</generator>
	<item>
		<title>Опрос датчика температуры по 1-wire контроллером AVR на Си с avr-libc</title>
		<link>http://devhead.ru/read/opros-datchika-temperatury-po-1-wire-kontrollerom-avr-na-si-s-avr-libc</link>
		<comments>http://devhead.ru/read/opros-datchika-temperatury-po-1-wire-kontrollerom-avr-na-si-s-avr-libc#comments</comments>
		<pubDate>Mon, 29 Aug 2011 07:48:54 +0000</pubDate>
		<dc:creator><![CDATA[andreykyz]]></dc:creator>
				<category><![CDATA[Статьи]]></category>
		<category><![CDATA[1-wire]]></category>
		<category><![CDATA[avr]]></category>
		<category><![CDATA[avr-libc]]></category>
		<category><![CDATA[gcc]]></category>

		<guid isPermaLink="false">http://devhead.ru/read/opros-datchika-temperatury-po-1-wire-kontrollerom-avr-na-si-s-avr-libc/</guid>
		<description><![CDATA[Недавно мне по работе нужно было реализовать на AVR опрос датчика температуры Dallas DS18B20 для управления частотным приводом насоса системы охлаждения. В интернете нашел много статей как всё это сделать на ассемблере, но по некоторым обстоятельствам мне нужно было на Си. В начале добавим заголовочные файлы: &#160; #include &#60;avr/io.h&#62; #include &#60;util/crc16.h&#62; #include &#60;util/delay.h&#62; #include &#60;avr/interrupt.h&#62; [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Недавно мне по работе нужно было реализовать на AVR опрос датчика температуры <a href="http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf">Dallas DS18B20 </a>для управления частотным приводом насоса системы охлаждения. В интернете нашел много статей как всё это сделать на ассемблере, но по некоторым обстоятельствам мне нужно было на Си. <span id="more-1338"></span></p>
<p>В начале добавим заголовочные файлы:</p>
<p>&nbsp;</p>
<pre class="brush: cpp">#include &lt;avr/io.h&gt;
#include &lt;util/crc16.h&gt;
#include &lt;util/delay.h&gt;
#include &lt;avr/interrupt.h&gt;</pre>
<p>&nbsp;</p>
<p>После этого я обычно объявляю макросы для работы с отдельными выводами портов ввода/вывода. На моей схеме датчик был подкулючен через согласующий транзистор к разным выводам. У меня получился такой код:</p>
<p>&nbsp;</p>
<pre class="brush: cpp">#define RX() bit_is_set(PINC,0)
#define TX1() PORTC &amp;= ~_BV(1) //выходной сигнал инвертирован
#define TX0() PORTC |= _BV(1)</pre>
<p>&nbsp;</p>
<p>Из datasheet на датчики температуры фирмы Dallas ясно, что все команды общения с датчиком посылаются после инициализация. Она нужна для того чтобы датчик понял, что ему сейчас будет послана команда. И написал такую функцию:</p>
<p>&nbsp;</p>
<pre class="brush: cpp">/*Сброс и ожидание начала presence pulse*/
uint8_t oneWireInit() {
	cli();
	TX0();
	_delay_us(500);
	TX1();
	_delay_us(60);
	sei();
	return RX() ; //если на выводе 1 - ошибка
}</pre>
<p>&nbsp;</p>
<p>Далее напишем фунцию отправки массива данных. т.к. вся работа с датчиком происходит в пределах одного пространтва имен я объявил глобальный массив:</p>
<p>&nbsp;</p>
<pre class="brush: cpp">uint8_t frame[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};</pre>
<p>&nbsp;</p>
<p>как разделяемые данные для разных функций. И так функция отправки(как аргумент функция получает байт который необходимо отправить):</p>
<p>&nbsp;</p>
<pre class="brush: cpp">/* Передача 1 байта. Передача осуществляется
 * младшим битом вперед
 */
void oneWireTans(uint8_t data) {
	cli();
	for (uint8_t i = 0; i&lt;8;i++) {
		TX0(); //импульс сброса (1-15мкс) - начало интервала передачи
		_delay_us(5);
		if (data &amp; 0x01) {
			TX1();
		}
		else {
			TX0();
		}
		_delay_us(60);//пауза для считывания данных таблеткой (60-120мкс)
		TX1();//импульс сброса "1"(1мкс)
		_delay_us(10);
		data &gt;&gt;= 1;
	}
	sei();
}</pre>
<p>&nbsp;</p>
<p>Прием данных осуществляется в массив frame в качестве аргумента функция получает колличество байт, оно зависит от типа команды которую мы послали датчику:</p>
<p>&nbsp;</p>
<pre class="brush: cpp">/*Чтение length байт данных младшим байтом вперед*/
void oneWireRecv(uint8_t length) {
	cli();
	_delay_us(60);
	for (uint8_t i = 0;i&lt;length;i++) {
		frame[i] = 0x00; //Очистка буфера приема
		/*Цикл для приема очередного байта*/
		for (uint8_t j = 0;j&lt;8;j++) {
			frame[i] &gt;&gt;= 1;
			TX0();			//импульс сброса "0"(1-15мкс) - начало интервала приема
			_delay_us(10);
			TX1();			//импульс сброса "1"
			_delay_us(9);
			frame[i] |= RX() ? 0x80:0;
			_delay_us(50);
		}

	}
	sei();
}</pre>
<p>&nbsp;</p>
<p>В нутри каждой функции есть макросы cli() и sei() для запрета прерываний на время общения с датчиком.</p>
<p>Все базовые функции написаны. Теперь напишем функцию которая мопожет нам обстрагироваться от всех внутренних команд датчика и просто возвратит температуру. Я назавал функцию getT() --&gt; get Temperature вот её содержимое:</p>
<p>&nbsp;</p>
<pre class="brush: cpp">uint16_t getT() {

	/*Чение адреса термо датчика*/
	if (oneWireInit()) return 255;
	_delay_us(110);			//Ожидание конца presence pulse
	oneWireTans(0x33);		//Чтение ROM подчиненного устройства
	oneWireRecv(8);			//Читаем ROM

	/*Расчет CRC*/
	uint8_t crcResult = 0;
	for (uint8_t i = 0; i&lt;7;i++) {
		crcResult = _crc_ibutton_update(crcResult,frame[i]);
	}
	if (crcResult != frame[7]) return 254;

	/*даем команду конвертации температуры нужному устройсту*/
	if (oneWireInit()) return 253;
	_delay_us(110);			//Ожидание конца presence pulse
	oneWireTans(0x55);
	for (uint8_t i = 0; i&lt;8; i++) {
		oneWireTans(frame[i]);
	}
	oneWireTans(0x44);		//Команда конвертации и записи температуры в регистр

	/*Чтение температуры*/
	if (oneWireInit()) return 252;
	_delay_us(110);			//Ожидание конца presence pulse
	oneWireTans(0x55);
	for (uint8_t i = 0; i&lt;8; i++) {
		oneWireTans(frame[i]);
	}
	oneWireTans(0xBE);		//Комманда чтения регистра с температурой
	oneWireRecv(9);
	crcResult = 0;
	for (uint8_t i =0; i&lt;8;i++) {
		crcResult = _crc_ibutton_update(crcResult,frame[i]);
	}
	if(crcResult != frame[8]) return 251;

	//Store integer
	uint16_t digit=frame[0]&gt;&gt;4;
	digit|=(frame[1]&amp;0xf)&lt;&lt;4;
	//Store decimal digits
	uint8_t decimal=frame[0]&amp;0xf;
	decimal= (decimal*5)/8;

	/*Возвращается только цело значение*/
	return ((uint16_t)digit);
}</pre>
<p>&nbsp;</p>
<p>При проектировании я знал, что теперература возвращаемая датчиком не может быть больше 125С. И все значаения выше 200 я возвращал как сигнал о той или иной ошибке. Используем функцию так. Считываем значение в переменную. Если значение больше 200 значит произошла та или иная ошибка чтения. Если меньше значит все Ок и это искомая температура. Если есть предложения по улучшению кода, пишите в комментариях к статье.</p>
<p><a href="../../wp-content/uploads/2011/08/onewire.zip">Архив с исходниками.</a></p>
<p>Дополнительная информация:</p>
<ul>
<li><a href="http://www.nongnu.org/avr-libc/user-manual/pages.html">Документация по библиотеке avr-libc</a></li>
<li><a href="http://www.avrfreaks.net/">Форум посвященный AVR</a></li>
<li><a href="http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf">Datasheet Dallas 18B20</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://devhead.ru/read/opros-datchika-temperatury-po-1-wire-kontrollerom-avr-na-si-s-avr-libc/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->