Walczę właśnie z DS18B20. Mój procek to AT90S2313 na płytce ZL1AVR, a kwarc 8 MHz. 1-Wire wychodzi tam na pin nr 3 portu D, a pin VCC DS18B20 jest podłączony do 5V. Port B służy do obsługi wyświetlacza. (To info dla tych co nie znają ZL1AVR
) Program pisałem w AVR-GCC na podstawie informacji ze strony www.mikrokontrolery.net i książki "Mikrokontrolery AVR w Praktyce" Radosława Dolińskiego.
Problem mój polega na tym, że nie za bardzo wiem jak wyświelić temperaturę zmierzoną przez DS 18B20. Nie wiem, czy problem polega na tym, że źle odczytuję (np. źle dobrane opóźnienia/odstępy), czy źle wypisuję (było kilka koncepcji, ale żadna nie wypaliła więc wyciąłem fragmenty kodu odpowiadające za wyślwietlanie temperatury). Jeśli ktoś ma jakieś pomysły na to jak wypisać na LCD temperaturę w oparciu o moje funcje lub zweryfikować moje funcje odpowiedzialne za obsługę 1-Wire (szczególnie opóźnenia i funkcję ow_read_bit) to prosze o pomoc.
Jeszcze jedno. Co musiałbym zmienić w algorytmie, aby umóżliwić sobie pracę z DS18S20?
P.S. Funkcje do obsługi LCD są przetestowane więc powinny być ok.
Problem mój polega na tym, że nie za bardzo wiem jak wyświelić temperaturę zmierzoną przez DS 18B20. Nie wiem, czy problem polega na tym, że źle odczytuję (np. źle dobrane opóźnienia/odstępy), czy źle wypisuję (było kilka koncepcji, ale żadna nie wypaliła więc wyciąłem fragmenty kodu odpowiadające za wyślwietlanie temperatury). Jeśli ktoś ma jakieś pomysły na to jak wypisać na LCD temperaturę w oparciu o moje funcje lub zweryfikować moje funcje odpowiedzialne za obsługę 1-Wire (szczególnie opóźnenia i funkcję ow_read_bit) to prosze o pomoc.
Jeszcze jedno. Co musiałbym zmienić w algorytmie, aby umóżliwić sobie pracę z DS18S20?
P.S. Funkcje do obsługi LCD są przetestowane więc powinny być ok.
#include <avr/io.h>
#include <stdlib.h>
#include <avr/delay.h>
#include <avr/signal.h>
// Zmienne do obslugi LCD ******************************************************************
unsigned char row = 0;
unsigned char column = 0;
unsigned char lcd_rs = 2; //definicja bitu portu dla linii RS
unsigned char lcd_e = 3; //definicja bitu portu dla linii E
unsigned char CR = 0x0a; //definicja znaku CR (przejście do nowej linii)
//******************************************************************************************
#define DQ 3
#define CLR_DQ DDRD |= _BV(DQ)
#define SET_DQ DDRD &= ~_BV(DQ)
#define IN_DQ PIND & _BV(DQ)
const unsigned char tau = 10.38; //przybliżony przelicznik argumentu na ms
// Funkcje do obslugi LCD******************************************************************
void wait(unsigned long w) //procedura wytracania czasu
{
unsigned char tp;
for(;w>0;w--)
{
for(tp=255;tp!=0;tp--);
}
}
void lcd_send_i(unsigned char instruction) //zapisz instrukcję sterującą do LCD
{
PORTB = (PORTB & 0xFB); //cbi(PORTB,lcd_rs);
PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
PORTB = ((PORTB & 0x0f) | (instruction & 0xf0)); //przygotuj starszy półbajt do LCD
asm("nop"); //wymagane wydłużenie impulsu
asm("nop");
asm("nop");
PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e); impuls strobujący
wait(10L); //czekaj na gotowość LCD ok. 100us
PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
PORTB = ((PORTB & 0x0f) | ((instruction & 0x0f)<<4));//przygotuj młodszy półbajt do LCD
asm("nop");
asm("nop");
asm("nop");
PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e);
wait(10L); //czekaj na gotowość LCD ok. 100us
}
void lcd_send_d(char data) //zapisz daną do LCD
{
PORTB = (PORTB | 0x04); //sbi(PORTB,lcd_rs);
PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
PORTB = ((PORTB & 0x0f) | (data & 0xf0)); //przygotuj starszy półbajt do LCD
asm("nop"); //wymagane wydłużenie impulsu
asm("nop");
asm("nop");
PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e); //impuls strobujący
wait(10L); //czekaj na gotowość LCD
PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
PORTB = ((PORTB & 0x0f) | ((data & 0x0f)<<4)); //przygotuj młodszy półbajt do LCD
asm("nop");
asm("nop");
asm("nop");
PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e); impuls strobujący
wait(10L); //czekaj na gotowość LCD
}
void write(char string) //procedura umieszcza znak na wyświetlaczu
{
lcd_send_d(string); //wyświetl znak na LCD
if(++column==16) //czy bieżąca kolumna mieści się na wyświetlaczu?
{
column=0; //jeśli nie, to ustaw początkową...
if(++row==2) //i przejdź do nowego wiersza
{
row=0; //jeśli nowy wiersz jest poza wyświetlaczem, ustaw początkowy
}
}
}
void lcd_clr(void) //czyść ekran
{
lcd_send_i(0x01); //polecenie czyszczenia ekranu dla kontrolera LCD
wait(1.64*tau); //rozkaz 0x01 wykonuje się 1.64ms
row = 0;
column = 0;
}
void lcd_xy(unsigned char w, unsigned char k) //ustaw współrzędne kursora
{
lcd_send_i((w*0x40+k)|0x80); //standardowy rozkaz sterownika LCD
} //ustawiający kursor w określonych współrzędnych}
void write_text(char * s)
{
while(*s) // do napotkania 0
{
lcd_send_d(*s); // zapisz znak wskazywany przez s na LCD
s++; // zwiększ s (przygotuj nastepny znak)
//if (++column==16)
//{
// lcd_xy(1,0);
//}
}
}
//1-Wire*********************************************************************************
void delay_us(unsigned char us)
{
do
{
asm("nop");
} while(--us!=0);
}
void ow_reset(void) //reset 1-Wire
{
CLR_DQ; // stan niski na linii 1wire
delay_us(255);
delay_us(255);
delay_us(255); // opóźnienie ok 480us
SET_DQ;// stan wysoki na linii 1wire
delay_us(255);
delay_us(255);
delay_us(255); // opóźnienie ok 480us
}
void ow_write_bit(unsigned char bit) // zapisu bitu na linię 1wire
{
CLR_DQ; // stan niski na linii 1wire
delay_us(20); // opóźnienie 11us
if(bit) SET_DQ; // jeśli parametr jest niezerowy to ustaw stan wysoki na linii
delay_us(119); // opóźnienie 100us
SET_DQ; // stan wysoki na linii 1wire
}
void ow_write_byte(unsigned char value)
{
unsigned char i;
unsigned char temp;
for (i=0; i<8; i++)
{
temp = value >> i;
temp &= 0x01;
ow_write_bit(temp);
}
delay_us(10);
}
unsigned char ow_read_bit(void)
{
CLR_DQ;
delay_us(1);
SET_DQ;
delay_us(27);
if(IN_DQ) return 1; else return 0;
//Moze cos dodac - delay
}
unsigned char ow_read_byte(void)
{
unsigned char i;
unsigned char value = 0;
for (i=0;i<8;i++)
{
if(ow_read_bit()) value|=0x01<<i;
delay_us(12);
}
return(value);
}
//****************************************************************************************
int main(void)
{
// Inicjalizacja LCD ********************************************************************
unsigned char i;
DDRB = 0xFF; //PORTB - wy
PORTB = 0x03; //port z podciąganiem
DDRD |= _BV(3);
DDRD |= _BV(4);
PORTD |= _BV(DQ);
//>>>>>>>>>>>>>>>>>> inicjacja wyświetlacza LCD <<<<<<<<<<<<<<<<<<<<<<
wait(45*tau); //opóźnienie ok. 45ms dla ustabilizowania się napięcia
//zasilania LCD (katalogowo min. 15 ms)
//lcd_rs już wcześniej było ustawione w stanie "0"
for(i=0;i<3;i++) //3-krotne wysłanie 3-
{
PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
PORTB=((PORTB&0x0f)|0x30); //wyślij 3- do LCD
asm("nop");
asm("nop");
asm("nop");
PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e); //impuls strobujący
wait(5*tau); //ok. 5ms
}
PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
PORTB=(PORTB&0x0f)|0x20; //wyślij 2- do LCD
asm("nop"); //wymagane wydłużenie impulsu
asm("nop");
asm("nop");
PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e); //impuls strobujący
wait(10L); //od tego momentu można sprawdzać gotowość LCD
//w tym programie nie będzie sprawdzania gotowości
lcd_send_i(0x28); //interfejs 4-bitowy, 2 linie, znak 5x7
lcd_send_i(0x08); //wyłącz LCD, wyłącz kursor, wyłącz mruganie
lcd_send_i(0x01); //czyść LCD
wait(1.64*tau); //wymagane dla instrukcji czyszczenia ekranu opóźnienie
lcd_send_i(0x06); //bez przesuwania w prawo
lcd_send_i(0x0c); //włącz LCD, włącz kursor, włącz mruganie
//*******************************************************************************************
char msb, lsb, temp;
unsigned char d1, d2;
char znaki[17] = {192,249,164,176,153,146,130,248,128,144};
while(1)
{
wait(5000);
ow_reset();
ow_write_byte(0xCC);
ow_write_byte(0x44);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
ow_reset();
ow_write_byte(0xCC);
ow_write_byte(0xBE);
lsb = ow_read_byte();
msb = ow_read_byte();
lsb = lsb >> 4;
msb &= 0x07;
msb = msb << 4;
temp = lsb | msb;
d2 = temp / 10;
d1 = temp % 10;
// WYSWIETLANIE
wait(2000);
}
}