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