Пишем программный код для подключения датчика температуры 18В20 к микроконтроллеру Atmega8 в среде программирования Atmel Studio.

Страница на этапе разработки

В данном уроке мы с Вами подключим датчик температуры 18B20

к микроконтроллеру Atmega8, в среде программирования Atmel Studio.

Датчик подключим к выходу порта PC0:

*****схема****

 

 

 

// Подключение цифровых датчиков температуры DS18B20 к AVR
#define F_CPU 4000000UL // Устанавливаем рабочую частоту контроллера
#include <avr/io.h>
#include <util/delay.h>

#define BAUD 9600L // Скорость обмена данными
#define UBRRL_value (F_CPU/(BAUD*16))-1 //Согластно заданной скорости подсчитываем значение для регистра UBRR


unsigned int TH, TL, Flag, t_flag;

void send_char(unsigned int n);
void init_USART();
void send_UART(char value);
unsigned char DS18B20_init(void);
unsigned char read_18b20(void);
void write_18b20(unsigned char data);

int main(void){

unsigned int buffer;
char temp_1,temp_2,temp_3; // Переменные для целого значения температуры
unsigned int point; // Переменная для дробного значения температуры
init_USART();


while(1){
if(Flag) send_UART(0x2D);//// Если датчик не ответил выводим «минус»

DS18B20_init(); // Инициализация DS18B20
write_18b20(0xCC); // Проверка кода датчика
write_18b20(0x44); // Запуск температурного преобразования
_delay_ms(1000); // Задержка на опрос датчика
DS18B20_init(); // Инициализация DS18B20
write_18b20(0xCC); // Проверка кода датчика
write_18b20(0xBE); // Считываем содержимое ОЗУ
TL = read_18b20(); // Читаем первые 2 байта блокнота
TH = read_18b20();
t_flag = 1; // Флаг знака температуры равен 1(плюс)

// Вычисляем отрицательную температуру
if(TH &(1 << 3)) // Проверяем бит знака температуры на равенство единице
{
signed int temp;
t_flag = 0; // Флаг знака равен 0(минус)
temp = (TH << 8)|TL;
temp = -temp; // Переводим дополнительный код в прямой
TL = temp;
TH = temp >> 8;
}

// Вычисляем целое значение температуры
buffer = ((TH << 4) & 0x70)|(TL >> 4);
temp_1 = buffer % 1000 / 100;
temp_2 = buffer % 100 / 10;
temp_3 = buffer % 10;

// Вычисляем дробное значение температуры
if(t_flag == 0) buffer = (TL & 0x0F) + 1; // Корректировка
else buffer = (TL & 0x0F);
point = buffer * 625 / 1000; // Точность преобразования(0.0625)
if (temp_1 != 0) send_char(temp_1);
send_char(temp_2);
send_char(temp_3);
send_UART(0x2C);// выводим запятую
send_char(point);

send_UART(0x0D); //переход в начало строки
send_UART(0x0A);//переход на новую строку
_delay_ms(500);
}
}

void send_char(unsigned int n){
switch (n){
case 0: send_UART(0x30); break;
case 1: send_UART(0x31); break;
case 2: send_UART(0x32); break;
case 3: send_UART(0x33); break;
case 4: send_UART(0x34); break;
case 5: send_UART(0x35); break;
case 6: send_UART(0x36); break;
case 7: send_UART(0x37); break;
case 8: send_UART(0x38); break;
case 9: send_UART(0x39); break;
}
}
void init_USART() {
UBRRL = UBRRL_value; //Младшие 8 бит UBRRL_value
UBRRH = UBRRL_value >> 8; //Старшие 8 бит UBRRL_value
UCSRB |=(1<<TXEN); //Бит разрешения передачи
UCSRC |=(1<< URSEL)|(1<< UCSZ0)|(1<< UCSZ1); //Устанавливем формат 8 бит данных
}
void send_UART(char value) {
while(!( UCSRA & (1 << UDRE))); // Ожидаем когда очистится буфер передачи
UDR = value; // Помещаем данные в буфер, начинаем передачу
}
unsigned char DS18B20_init(void){// Инициализация DS18B20
DDRC |= (1 << PC0); // PC0 — выход
PORTC &= ~(1 << PC0); // Устанавливаем низкий уровень
_delay_us(490);
DDRC &= ~(1 << PC0); // PC0 — вход
_delay_us(68);
Flag = (PINC & (1 << PC0)); // Ловим импульс присутствия датчика
// если Flag = 0 датчик подключен, Flag = 1 датчик не подключен
_delay_us(422);
return Flag;
}
unsigned char read_18b20(void){// Функция чтения байта из DS18B20
unsigned char i, data = 0;
for(i = 0; i < 8; i++)
{
DDRC |= (1 << PC0); // PC0 — выход
_delay_us(2);
DDRC &= ~(1 << PC0); // PC0 — вход
_delay_us(4);
data = data >> 1; // Следующий бит
if(PINC & (1 << PC0)) data |= 0x80;
_delay_us(62);
}
return data;
}
void write_18b20(unsigned char data){// Функция записи байта в DS18B20
unsigned char i;
for(i = 0; i < 8; i++)
{
DDRC |= (1 << PC0); // PC0 — выход
_delay_us(2);
if(data & 0x01) DDRC &= ~(1 << PC0);
else DDRC |= (1 << PC0);
data = data >> 1; // Следующий бит
_delay_us(62);
DDRC &= ~(1 << PC0); // PC0 — вход
_delay_us(2);
}
}