Termometr - ds1820 (wyświetlanie temperatury)

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Thomas_7
-
Posty: 9
Rejestracja: 03 sie 2007, 13:18
Lokalizacja: Lublin

Termometr - ds1820 (wyświetlanie temperatury)

Post autor: Thomas_7 » 21 lut 2009, 19:01

Witam.
Chciałem zrobić termometr na czujniku ds1820. Dane mają być wyświetlane na 3 wyświetlaczach 7-segmentowych. Napisałem funkcje do obsługi czujnika i sterowania wyświetlaczami, ale nie wiem jak wyświetlić temperaturę (dopiero zaczynam programować AVR-y). Chodzi mi o dokładność 0,5°C. Czy mógłby mi ktoś pomóc?

Narazie mój kod wygląda tak:

Kod: Zaznacz cały

 
//  ATmega8,  1MHz
//  PB0 - ds1820
//  PC0, PC1, PC2 - wyświetlacz +
//  PD0-PD6 - segmenty wyświetlacza (PD0-a, PD1-d, PD2-c, PD3-g, PD4-b, PD5-e, PD6-f)
//	
/////////////////////////////////////////////////////////////////////////////////////////////
#include <avr\io.h>
#include <inttypes.h>
#include <avr\interrupt.h>
#include <util/delay.h>

// Definicje wyprowadzeń
#define SEGPORT PORTD
#define SEGDDR DDRD 
#define WYSPORT PORTC 
#define WYSDDR DDRC
//*******************************************
#define WE 0
#define PORT_1Wire PINB
#define SET_1Wire DDRB&=~_BV(WE)
#define CLEAR_1Wire DDRB|-_BV(WE)

uint8_t g_AktWyswietlacz = 0; 
uint8_t g_WyswietlanyZnak[3]; 
uint8_t g_WlaczWyswietlacz[3] = {
	0x01, // wyświetlacz 1
	0x02, // wyświetlacz 2
	0x04  // wyświetlacz 3
	}; 
	
//*******************************************
//reset magistrali - oczekiwanie na impuls PRESENCE
unsigned char RESET_PULSE(void)
{
unsigned char PRESENCE;
CLEAR_1Wire; //poziom niski na magistralę
_delay_ms(500); //opóźnienie
SET_1Wire;  // ustawiamy magistralę w poziom wysoki
_delay_ms(30); // oczekiwanie na ustawienie linii w tan niski przez ds1820
// sprawdzenie stanu linii
if(bit_is_clear(PORT_1Wire, WE)) {PRESENCE=1;} else {PRESENCE=0;}
// 1-odebrano bit PRESENCE, 0- stan nieaktywności
_delay_ms(470); //
//sprawdzenie poziomu linii (czy ustawiona)
if(bit_is_set(PORT_1Wire, WE)) {PRESENCE=1;} else {PRESENCE=0;}
return PRESENCE; //zwracamy wartość do funkcji
}

//wysyłanie do układu pojedynczego bitu
void send(char bit)
{
CLEAR_1Wire; //ustawienie magistrali w stan niski
_delay_ms(5);
	if(bit==1) 
		SET_1Wire; //zwlonienie magistrali - wysłanie 1
	
	_delay_ms(80); //przetrzymanie - wysłanie zera
	SET_1Wire;
}

// odczytanie bitu z magistrali
unsigned char read(void)
{
unsigned char PRESENCE=0;
CLEAR_1Wire; //ustawienie czujnika w stan niski
_delay_ms(2);
SET_1Wire; // zwolnienie magistrali
_delay_ms(15);
// odbiór jedynki lub zera
if(bit_is_set(PORT_1Wire, WE)) PRESENCE=1; else PRESENCE=0;
return(PRESENCE);
}

// wysyłanie całego bajtu do układu
void send_byte(char wartosc)
{
unsigned char i; // zmienna licznikowa
unsigned char pom; // zmienna pomocnicza

for (i=0; i<8; i++)
	{
	pom=wartosc>>i; // przesunięcie bitowe w prawo
	pom &= 0x01; // skopiowanie bitu na magistralę
	send(pom); // wysłanie bitu na magistralę
	}
_delay_ms(100);
}

// zczytuje cały bajt z układu
unsigned char read_byte(void)
{
unsigned char i; // zmienna licznikowa
unsigned char wartosc=0; //zczytywana wartość

for(i=0; i<8; i++) //pętla wykonywana 8 razy
	{
		if(read()) wartosc|=0x01<<i; //zczytywanie po jednym bicie
		_delay_ms(15);
	}
return(wartosc); // zwrot wartości do funkcji
}

int main(void)
{
	
	// ustawienie portów
	SEGDDR = 0xff; 
	WYSDDR = 0xff;
	//**************************
	// Timer0
	TCCR0 = 1<<CS01|1<<CS00; 
	TIMSK = 1<<TOIE0; 
	//**************************
	// Globalne zezwolenie na przerwania
	sei(); 
	
	
	// Zdefiniowanie znaków w tablicy
	    int znak[10]; 
    
        znak[0] = 0b00001000;  //0
        znak[1] = 0b01101011;  //1
        znak[2] = 0b01000100;  //2
        znak[3] = 0b01100000;  //3
        znak[4] = 0b00100011;  //4
        znak[5] = 0b00110000;  //5
        znak[6] = 0b00010000;  //6
        znak[7] = 0b01101010;  //7
        znak[8] = 0b00000000;  //8
        znak[9] = 0b00100000;  //9
        znak[10]= 0b00010100;  //E


	// deklaracja zmiennych lokalnych
	unsigned char sprawdz; 
	char temp1=0, temp2=0;
	
	
	for(;;)
	{
		sprawdz=RESET_PULSE(); // reset
			if(sprawdz==1)
			{
				send_byte(0xCC); // SKIP ROM
				send_byte(0x44); // CONVERT T
				_delay_ms(750); // odczekaj 750ms - czas konwersji
				
				sprawdz=RESET_PULSE(); //wysłanie impulsu reset
				send_byte(0xCC); // SKIP ROM
				send_byte(0xBE); // READ SCRATCHPAD
				
				temp1=read_byte(); // odczytanie LSB
				temp2=read_byte(); //odczytanie MSB
				
				sprawdz=RESET_PULSE(); // zwolnienie magistrali
				
				float temp=0; // zmienna do obliczeń
				temp=(float)(temp1+(temp2*256))/16; // obliczenie temperatury
				
			}
			else // jeśli nie wykryto PRESENCE_PULSE (sprawdz=0)
			{
                                                 // wyświetl  'EEE'  - błąd
				g_WyswietlanyZnak[0] = znak[10];
				g_WyswietlanyZnak[1] = znak[10];
				g_WyswietlanyZnak[2] = znak[10];
			}
	}

	return 0; 
}

//___________________________________________________________________________________
// Obsługa przerwań
SIGNAL(SIG_OVERFLOW0)
{

	TCNT0 = 200;  // częstotliwość przełączania wyświetlaczy 
	
	WYSPORT = 0x00;  // Wygaszenie wyświetlaczy
	
	SEGPORT = g_WyswietlanyZnak[g_AktWyswietlacz];   // Wysłanie odpowiedniego znaku 
	WYSPORT = g_WlaczWyswietlacz[g_AktWyswietlacz];   // Włączenie odpowiedniego wyświetlacza
	
	++g_AktWyswietlacz;   // Zwiększenie stanu zmiennej wskazującej na obsługiwany wyświetlacz
	if(g_AktWyswietlacz > 2)
		g_AktWyswietlacz = 0; 
}

ODPOWIEDZ