При работе с датчиком по шине (да, да один провод — тоже шина) 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 есть встроенная библиотека, если вы хотите использовать эту, замените функции задержки.






