logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega8][C][ds1820][led] problem z wyświetlaniem

gonich 17 Lut 2009 15:02 1839 2
REKLAMA
  • #1 6162930
    gonich
    Poziom 10  
    Witam wszystkich i na początku proszę o wyrozumiałość bo to mój pierwszy post na elektrodzie.

    Zbudowałem układ do pomiary temperatury z wykorzystaniem atmegi8 i czujnika temperatury ds1820. Wynik wyświetlany jest na 4 wyświetlaczach 7-segmentowych. Program napisałem w języku C (obsługę 1-wire zaczerpnąłem z mikrokontrolery.net) Wszystko działa jak należy z wyjątkiem wyświetlania.
    W programie przy odczytywaniu i zapisie bitów z na linii DQ wyłączane są przerwania obsługujące wyświetlanie co powoduje widoczne miganie wyświetlaczy. Nie potrafię sobie z tym poradzić proszę więc o wskazówki do ww problemu oraz konstruktywne uwagi do kodu.

    
    #include <avr/io.h>
    #include <avr/delay.h>
    #include <avr/interrupt.h>
    
    #define DQ 5
    #define SET_DQ DDRD &= ~_BV(DQ)
    #define CLR_DQ DDRD |= _BV(DQ)
    #define IN_DQ PIND & _BV(DQ)
    
    char cyfry[10] = {192,249,164,176,153,146,130,248,128,144};
    unsigned char  t0, t1, t2, t3;
    short int dl=0;
    unsigned char msb, lsb;
    
    void Inicjalizacja_portow(void)
    {
    	DDRB = 0xFF;
    	PORTB = 0xFF;
    	DDRC = 0xFF;
    	PORTC = 0xFF;
    }
    
    void Inicjalizacja_timer2(void)	
    {
    	TIMSK = _BV(TOIE2);  // wł±cz obsługę przerwań T/C0
    	//TIMSK =0x41;
    	TCNT2 = 0;         // warto¶ć pocz±tkowa T/C0
    	TCCR2 = 0x02; // preskaler 8   
    	sei(); 				//wł±cz globaln± obsługę przerwań
    }
    
    void delay(unsigned char t)
    {
    	do{asm("nop");}while(--t);
    }
    
    //******************************************************************************
    //****************** one wire **************************************************
    //******************************************************************************
    void ow_reset(void)	// procedura reset
    {
    	CLR_DQ; // stan niski na linii 1wire
    	delay(255); //
    	delay(119); // opóźnienie ok 480us
    	//delay(1);
    	SET_DQ;// stan wysoki na linii 1wire
    	delay(255); //
    	delay(119); // opóźnienie ok 480 us
    }
    
    // procedura zapisu bitu na linię 1wire
    void ow_write_bit(char b)
    {
    	cli(); // zablokowanie przerwań
    	CLR_DQ; // stan niski na linii 1wire
    	delay(7); //7 opóźnienie 10us
    	if(b) SET_DQ; // jeśli parametr jest niezerowy to ustaw stan wysoki na linii
    	delay(80); //80 opóźnienie 100us
    	SET_DQ; // stan wysoki na linii 1wire
    	sei(); // odblokowanie pzrerwań	
    }
    
    char ow_read_bit(void)
    {
    	cli();
    	CLR_DQ;
    	delay(1);
    	SET_DQ;
    	delay(11);//11
    	if(IN_DQ) return 1; else return 0;
    	sei();
    }
    
    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(6);
    	}
    	return(value);
    }
    
    void ow_write_byte(char val)
    {
    	unsigned char i;
    	unsigned char temp;
    	for (i=0; i<8; i++)
    	{
    		temp = val >> i;
    		temp &= 0x01;
    		ow_write_bit(temp);
    	}
    	delay(5);
    }
    
    void komunikacja(void)
    {
    	ow_reset();				//inicjalizacja przez Master ł±czno¶ci z ds1820
    	ow_write_byte(0xCC);	//pomiń sprawdzanie adresu (przeskocz ROM)
    	ow_write_byte(0x44);	//inicjalizacja pomioru temperatury
    	
    	_delay_ms(250);			//przy zasilaniu tylko DQ 500ms
    	//_delay_ms(250);		//przy zasilaniu VDD czas do zakończenia
    	//_delay_ms(250);		//cyklu pomiarowego
    	
    	ow_reset();				//ponowna inicjalizacja
    	ow_write_byte(0xCC);	//pomiń sprawdzanie adresu (przeskocz ROM)
    	ow_write_byte(0xBE);	//odczyt pamięci podręcznej
    	lsb = ow_read_byte();
    	msb = ow_read_byte();
    }
    
    void przeliczanie(void)
    {
    	if (msb > 0)
    	{
    		lsb=~lsb;
    		lsb++;
    		t0=3;
    		t1=(lsb/2)/10;
    		t2=(lsb/2)%10;
    		if(lsb%2==0)
    			t3=0;
    		else
    			t3=5;
    	}
    	else
    	{
    		t0=(lsb/2)/100;
    		if(lsb<200)
    			t1=(lsb/2)/10;
    		if(lsb>=200)
    			t1=(lsb/200);
    		t2=(lsb/2)%10;
    		if(lsb%2==0)
    			t3=0;
    		else
    			t3=5;
    	}
    }
    
    SIGNAL (SIG_OVERFLOW2)		
    //ISR (TIMER2_OVF_vect)		// to samo nowszy zapis
    {
    	dl++;
    	if(dl<=5)
    	{	
    		PORTC |= _BV(1);
    		PORTC |= _BV(2);
    		PORTC |= _BV(3);
    		PORTB = cyfry[t3];
    		PORTC = ~_BV(0);	
    	}		
    	if ((dl>=5)&&(dl<=10))
    	{
    		PORTC |= _BV(0);
    		PORTC |= _BV(2);
    		PORTC |= _BV(3);
    		PORTB = (cyfry[t2]) & 0x7f;  // & 0x7f - dodanie kropki 
    		PORTC &= ~_BV(1);	 
    	}
    	if((dl>=10)&&(dl<=15))
    	{
    		PORTC |= _BV(1);
    		PORTC |= _BV(0);
    		PORTC |= _BV(3);
    		PORTB = cyfry[t1];
    		PORTC &= ~_BV(2);
    	}
    	if((dl>=15)&&(dl<=20)&&(t0!=0))
    	{
    		PORTC |= _BV(1);
    		PORTC |= _BV(2);
    		PORTC |= _BV(0);	
    		if (msb > 0)
    			PORTB = 0xBF;
    		else
    			PORTB = cyfry[t0];
    		PORTC &= ~_BV(3);		
    	}
    	if( (dl==15) && (t0==0) )
    		dl=0;
    	else if (dl==20) dl=0;
    }
    
    int main(void)
    {
    	
    	Inicjalizacja_portow();
    	Inicjalizacja_timer2();	
    
    	while(1)
    	{	
    		komunikacja();
    		przeliczanie();
    	}
    	return 0;
    }
    
  • REKLAMA
  • #2 6163037
    kloszi
    Poziom 21  
    Widzę że odświeżasz wyświetlacz niezależnie od tego czy wynik się zmienił czy też nie. Lepiej zapamiętuj to co masz na wyświetlaczu i odświeżaj wtedy kiedy coś się zmieni.
  • #3 6163200
    gonich
    Poziom 10  
    Wyświetlanie realizowane jest przez multipleksowanie więc odświeżanie musi być ciągłe. Wydawało mi się wyłącznie przerwać na czas obliczania zmiennych t0-t3 pomoże ale nie pomogło
REKLAMA