Библиотека AVR для работы с 1-wire датчиком температуры DS18B20

При работе с датчиком по шине (да, да один провод — тоже шина) 1-wire следует особое внимание уделять временным задержкам.
Благо для AVR соответствующие функции написаны практически для всех IDE.

Работу с 1-wire я описывал, поэтому заострять внимание не будем..

// частота работы
#define F_CPU 1000000UL

#include <math.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>

/* Определяем куда подключен датчик */
#define THERM_PORT PORTC
#define THERM_DDR DDRC
#define THERM_PIN PINC
#define THERM_DQ PC0
/* Макросы для "дергания ноги" и изменения режима ввода/вывода */
#define THERM_INPUT_MODE() THERM_DDR&=~(1<<THERM_DQ)
#define THERM_OUTPUT_MODE() THERM_DDR|=(1<<THERM_DQ)
#define THERM_LOW() THERM_PORT&=~(1<<THERM_DQ)
#define THERM_HIGH() THERM_PORT|=(1<<THERM_DQ)

// сброс датчика
uint8_t therm_reset(){
        uint8_t i;
        // опускаем ногу вниз на 480uS
        THERM_LOW();
        THERM_OUTPUT_MODE();
        _delay_us(480);             // замените функцию задержки на свою
        // подымаем линию на 60uS
        THERM_INPUT_MODE();
        _delay_us(60);
        // получаем значение на линии в период 480uS
        i=(THERM_PIN & (1<<THERM_DQ));
        _delay_us(420);
        // возвращаем значение (0=OK, 1=датчик не найден)
        return i;
}


// функция отправки бита
void therm_write_bit(uint8_t bit){
        // опускаем на 1uS
        THERM_LOW();
        THERM_OUTPUT_MODE();
        _delay_us(1);
        // если хотим отправить 1, поднимаем линию (если нет, оставляем как есть)
        if(bit) THERM_INPUT_MODE();
        // ждем 60uS и поднимаем линию
        _delay_us(60);
        THERM_INPUT_MODE();
}

// чтение бита
uint8_t therm_read_bit(void){
        uint8_t bit=0;
        // опускаем на 1uS
        THERM_LOW();
        THERM_OUTPUT_MODE();
        _delay_us(1);
        // поднимаем на 14uS
        THERM_INPUT_MODE();
        _delay_us(14);
        // читаем состояние
        if(THERM_PIN&(1<<THERM_DQ)) bit=1;
        // ждем 45 мкс и возвращаем значение
        _delay_us(45);
        return bit;
}

// читаем байт
uint8_t therm_read_byte(void){
        uint8_t i=8, n=0;
        while(i--){
                // сдвигаем в право на 1 и сохраняем следующее значение
                n>>=1;
                n|=(therm_read_bit()<<7);
        }
        return n;
}

// отправляем байт
void therm_write_byte(uint8_t byte){
        uint8_t i=8;
        while(i--){
                // отправляем бит и сдвигаем вправо на 1
                therm_write_bit(byte&1);
                byte>>=1;
        }
}


// команды управления датчиком
#define THERM_CMD_CONVERTTEMP 0x44
#define THERM_CMD_RSCRATCHPAD 0xbe
#define THERM_CMD_WSCRATCHPAD 0x4e
#define THERM_CMD_CPYSCRATCHPAD 0x48
#define THERM_CMD_RECEEPROM 0xb8
#define THERM_CMD_RPWRSUPPLY 0xb4
#define THERM_CMD_SEARCHROM 0xf0
#define THERM_CMD_READROM 0x33
#define THERM_CMD_MATCHROM 0x55
#define THERM_CMD_SKIPROM 0xcc
#define THERM_CMD_ALARMSEARCH 0xec

#define THERM_DECIMAL_STEPS_12BIT 625 //.0625

// читаем температуру с датчика
void therm_read_temperature(char *buffer){
        uint8_t temperature[2];
        int8_t digit;
        uint16_t decimal;

        therm_reset();
        therm_write_byte(THERM_CMD_SKIPROM);
        therm_write_byte(THERM_CMD_CONVERTTEMP);

        while(!therm_read_bit());

        therm_reset();
        therm_write_byte(THERM_CMD_SKIPROM);
        therm_write_byte(THERM_CMD_RSCRATCHPAD);

        temperature[0]=therm_read_byte();
        temperature[1]=therm_read_byte();
        therm_reset();

        digit=temperature[0]>>4;
        digit|=(temperature[1]&0x7)<<4;

        decimal=temperature[0]&0xf;
        decimal*=THERM_DECIMAL_STEPS_12BIT;
        
        // я вывожу данные на порт
        PORTA = digit;
        PORTB = decimal >> 8;
        
        sprintf(buffer, "%+d.%04u C", digit, decimal);
}

int main(void)
{
        DDRA = 0xff;
        DDRB = 0xff;
        
        char buffer[100];
        
    while(1)
    {
        therm_read_temperature(buffer); 
    }
}

Не пугайтесь, тут ничего сложного. Чтобы понять все это ознакомтесь со статьей по ссылке выше и почитайте даташит на датчик.
Библиотека для AVR Studio. В Code Vision есть встроенная библиотека, если вы хотите использовать эту, замените функции задержки.

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий