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;
}