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

[c]TWI + PCF8583 + ATMEGA32

lokii 31 Paź 2009 22:26 2996 2
REKLAMA
  • #1 7200077
    lokii
    Poziom 13  
    Witam

    Jestem początkujący w technice mikroprocesorków i w programowaniu w c.

    Aktualnie męczę się z wpisaniem czasu do PCF.

    Przy próbie zapisu w momencie kiedy sekundy równe są 5 wyświetlanie czasu zamiera. Reszta układu działa, ale czas na wyświetlaczu pozostaje w formacie 00:00:05

    Wzorowałem się na :

    https://www.elektroda.pl/rtvforum/topic1338039.html

    Proszę o podpowiedź co robię nie tak ?

    Poniżej zamieszczam listing mojego testowego programu.

    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <HD44780.c>
    #include <stdlib.h>
    #include <makra.h>
    #include <DS18B20.c>
    #include <twi.c>
    #include <avr/interrupt.h>
    
    
    #define zegar 0xA0
    
    #define BUCZEK_ON  PORTA |= _BV(1); 
    #define BUCZEK_OFF  PORTA &= ~_BV(1); 
    
    #define GRZALKA_ON  PORTC &= ~_BV(7); 
    #define GRZALKA_OFF PORTC |= _BV(7); 
    
    //TR2_OFF PORTB &= ~_BV(3); 
    
    
    
    
      
    
    
    volatile int przerwanie=0;
    unsigned char czas[6] ={0,}; // zerowanie wszystkich elementów tablicy 
    unsigned char czasPCF8583 =0;
    unsigned char buf2;
    unsigned char buf3;
    unsigned char buf4;
    unsigned char buf5;
    unsigned char buf6;
    unsigned char buf7;
    int menu=0;
    int podmenu=0;
    
    void INT0_inicjacja(void) 
    { 
     
      MCUCR = 0b00000001;     
      GICR = 0b01000000;   
    } 
    
    
    
    ISR(INT0_vect)   
    	{ 
    		przerwanie=1;
    	}
    
    
    
    
    
    int main (void) 
    
    { 
    
    //Porty: PC0(SCL) PC1(SDA)  ->  wejścia TWI 
    DDRA =0b11111111;
    PORTA =0b11111111;
    
    
    DDRC =0b11111110;
    PORTC =0b11111101;
    
    DDRB = 0b00000000;
    PORTB = 0b11100000;
    
    //DDRC = 0b11111111;
    //PORTC = 0b10000001;
    
    
     
        
    unsigned char sprawdz;
    char temp1=0, temp2=0;
    float temp=0;
    float temp_zadana=30;
    float histereza=0.2;
    
    INT0_inicjacja(); 
    sei();
    
    LCD_Initalize();
    LCD_Clear(); 
    TWI_inicjacja(); 
    //TWI_zapis(zegar,0x04,0b00000001); // ustawienie początkowe zegara pcf8583 (zerowanie)
    //TWI_zapis(zegar,0x03,0b00110010);
    TWI_zapis(zegar,0x00,0b00000000);
    
    for(;;)
    {
    
    if (przerwanie==1)
    
    {
        czasPCF8583 =TWI_odczyt(zegar,0x04); 
        czas[0] =(czasPCF8583 & 0b00110000) >> 4;   // dziesatki_godzin          
        czas[1] =czasPCF8583 & 0b00001111;      // godziny 
        czasPCF8583 =TWI_odczyt(zegar,0x03); 
        czas[2] =czasPCF8583 >> 4;             // dziesatki_minut 
        czas[3] =czasPCF8583 & 0b00001111;      // minuty 
        czasPCF8583 =TWI_odczyt(zegar,0x02); 
        czas[4] =czasPCF8583 >> 4;             // dziesatki_sekund 
        czas[5] =czasPCF8583 & 0b00001111;      // sekundy
    	
    	
    	buf2= (czas[0]+0x30);
    	buf3= (czas[1]+0x30);	
    	buf4= (czas[2]+0x30);	
    	buf5= (czas[3]+0x30);	
    	buf6= (czas[4]+0x30);		
    	buf7= (czas[5]+0x30);	
    	
    	przerwanie=0;
    }	
    
    	sprawdz=RESET_PULSE();
    
    	if(sprawdz==1)
    	{
    	send_byte(0xCC);
    	send_byte(0x44);
    	//_delay_ms(750);
    	
    	sprawdz=RESET_PULSE();
    	
    	send_byte(0xCC);
    	send_byte(0xBE);
    	
    	temp1=read_byte();
    	temp2=read_byte();
    	
    	sprawdz=RESET_PULSE();
    	
    	temp = zamien_temp(temp2,temp1);
    	
    	dtostrf(temp, 3, 1, buf);
    
    		}
    		
    	LCD_GoTo(0, 0);
    	LCD_WriteData(buf2);
    	LCD_GoTo(1, 0);
    	LCD_WriteData(buf3);
    	
    	LCD_GoTo(2, 0);
    	LCD_WriteText(":");
    
    	
    	LCD_GoTo(3, 0);
    	LCD_WriteData(buf4);
    	LCD_GoTo(4, 0);
    	LCD_WriteData(buf5);
    	
    	LCD_GoTo(6, 0);         //wyswietlanie sekund
    	LCD_WriteData(buf6);
    	LCD_GoTo(7, 0);
    	LCD_WriteData(buf7);
    	
    	
    	LCD_GoTo(0, 1);
    	LCD_WriteText("T:");
    	LCD_WriteText(buf);
    	LCD_WriteText(" ");
    	
    char pomocnik[3];	
    	
    	
    
    itoa (menu, pomocnik, 10); 
    
    	
    	
    	LCD_GoTo(7, 1);
    	LCD_WriteText("m=");
    	LCD_WriteText((pomocnik));
    	
    	LCD_GoTo(11, 1);
    	LCD_WriteText("p=");
    	LCD_WriteData((podmenu));
    	
    	
    
    	float T1 = temp_zadana - histereza;
    	float T2 = temp_zadana + histereza;
    	
    	
    	if (temp  <=T1)
    		{ 
    			GRZALKA_ON;		
    		} 
    		
    		if (temp  >=T2)
    		{ 
    			GRZALKA_OFF;		
    		} 
    		
    		
    		
    		 
    	//MENU OK
    	
    	
    	if((PINB & _BV(PB1))==0)
    		{ 
        
    			_delay_ms(20); // opóźnienie 
        
    				if((PINB & _BV(PB1))==0)// ponowne sprawdzenie stanu przycisku - jeśli nadal jest naciśnięty, wykonaj kod 
    					{ 
    						menu++;
          
    				while((PINB & _BV(PB1))==0);// oczekiwanie na zwolnienie przycisku 
             
    					} 
    		}
    	 
    	 
    	 if((PINB & _BV(PB3))==0)
    		{ 
        
    			_delay_ms(20); // opóźnienie 
        
    				if((PINB & _BV(PB3))==0)// ponowne sprawdzenie stanu przycisku - jeśli nadal jest naciśnięty, wykonaj kod 
    					{ 
    						menu--;
    						
    						
    				while((PINB & _BV(PB3))==0);// oczekiwanie na zwolnienie przycisku 
             
    					} 
    		} 
    		
    		//MENU ESC
    		
    		
    		if((PINB & _BV(PB4))==0)
    		{ 
        
    			_delay_ms(20); // opóźnienie 
        
    				if((PINB & _BV(PB4))==0)// ponowne sprawdzenie stanu przycisku - jeśli nadal jest naciśnięty, wykonaj kod 
    					{ 
    						podmenu++;
          
    				while((PINB & _BV(PB4))==0);// oczekiwanie na zwolnienie przycisku 
             
    					} 
    		} 
    		
    		//MENU PLUS
    		
    		
    		if((PINB & _BV(PB2))==0)
    		{ 
        
    			_delay_ms(20); // opóźnienie 
        
    				if((PINB & _BV(PB2))==0)// ponowne sprawdzenie stanu przycisku - jeśli nadal jest naciśnięty, wykonaj kod 
    					{ 
    						podmenu--;
          
    				while((PINB & _BV(PB2))==0);// oczekiwanie na zwolnienie przycisku 
             
    					} 
    		} 
    		
    		//MENU MINUS
    		
    				
    		if (czas[5] == 0b00000101)
    		{
    							
    							TWI_zapis(zegar,0x00,0b10000000);									//* 1. stop zliczania i wyzerowanie dzielnika
    							TWI_zapis(zegar,0x04,0b00000000);	//* 2. wpis czasu do zegara godzin
    							TWI_zapis(zegar,0x03,0b00000000);	//* 3. wpis czasu do zegara minut       
    							TWI_zapis(zegar,0x02,0b00000000);	//* 4. wpis czasu do zegara sekund
    							TWI_zapis(zegar,0x01,0b00000000);									//* 4a. zerowanie setnych i dziesiętnych sekundy
    							TWI_zapis(zegar,0x00,0b00000000);									//* 5. start zliczania 
    															
    }		
    	}
    }
  • REKLAMA
  • #2 7204503
    p_zag
    Poziom 14  
    Witam
    Na początek to
    Cytat:

    //Porty: PC0(SCL) PC1(SDA) -> wejścia TWI

    DDRC =0b11111110;
    PORTC =0b11111101;

    skoro porty PC0(SCL) PC1(SDA) to wejścia TWI , ja bym je ustawił tak
    
    //Porty: PC0(SCL) PC1(SDA)  ->  wejścia TWI
      // 1 -> wyjście
      // 0 -> wejście
    DDRC =0b11111100;
      // 1 -> z podciągnięciem do VCC (pull-up)
      // 0 -> bez podciągniecia do VCC 
    PORTC =0b11111111;
    

    zrobiłem tak u siebie i zegar działa mi do dziś z odchyłką (spieszy się)1-2 sekundy na tydzień. Jest to ustawienie na stan wysoki wejść TWI, choć są też rezystory (u mnie po 6,2kOma) podciągające wejścia (SCL i SDA) do plusa zasilania atmegi.

    Cytat:

    //MENU MINUS


    if (czas[5] == 0b00000101)
    {

    TWI_zapis(zegar,0x00,0b10000000); //* 1. stop zliczania i wyzerowanie dzielnika
    TWI_zapis(zegar,0x04,0b00000000); //* 2. wpis czasu do zegara godzin
    TWI_zapis(zegar,0x03,0b00000000); //* 3. wpis czasu do zegara minut
    TWI_zapis(zegar,0x02,0b00000000); //* 4. wpis czasu do zegara sekund
    TWI_zapis(zegar,0x01,0b00000000); //* 4a. zerowanie setnych i dziesiętnych sekundy
    TWI_zapis(zegar,0x00,0b00000000); //* 5. start zliczania

    }
    }
    }

    ty w momencie gdy element tablicy czas[5] =0b00000101 (sekundy osiągną wartość równą 5) dokonujesz zapisu do pcf8583 całkowicie go zerując (karzesz mu liczyć od zera). U mnie cała tablica "unsigned char czas[6]" służy do przechowywania aktualnego odczytywanego czas z pcf8583 i pamięta czas do następnego odczytu. U ciebie tego brakuje.
    Ja sam odczyt czasu z pcf8583 , oraz odczyt temperatury (1Wire) zrobił bym w przerwaniu natomiast zapisy do pcf8583, obsługa klawiatury, itp w programie głównym.
    I jeszcze jedno co będzie jak ktoś naciśnie kilka klawiszy na raz, lub naciśnie klawisz i będzie go długo (np 1 minute) trzymał. A co będzie jak z jakiś powodów atmega się zawiesi (skok napięcia).
    Jak by co to będę tu zaglądał co jakiś czas żeby coś wyjaśnić z mojego programu.
    Mi też od razu zegar nie zadziałał, ale teraz za to chodzi bardzo dokładnie i stabilnie.
    Powodzenia
  • #3 7306595
    lokii
    Poziom 13  
    Przepraszam, że tak długo nie zagladałem. Z problemem sobie poradziłem stosując sie do zaleceń mojego przedmówcy.
REKLAMA