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

Atmega16 + Eclipse układ RTC zatrzymuje się po kilku minutach

jwalentek 25 Maj 2011 22:48 2254 13
REKLAMA
  • #1 9544683
    jwalentek
    Poziom 11  
    Witam Kolegów
    Mam taki problem z układem RTC DS1307 oraz Atmega16. Układ rtc odmierza czas, atmega16 co 1 sek odczytuje poprzez TWI i wyświetla na wyświetlaczu.
    Problem polega na tym, że po kilku minutach 5-8 min układ się zawiesza, tzn. nie odczytuje czasu, nic nie robi. Nie pomaga nawet resetowanie. Doszedłem, że program zawiesza się w momencie próby odczytu danych z rtc. Całą płytkę muszę wyłączyć na jakieś 10min , wtedy dopiero zaczyna działać, ale po kilku minutach jest to samo.

    Co może być przyczyną?

    AtMega16 - zegar wewn 8Mhz, komunikacja z DS1307 przez TWI.
  • REKLAMA
  • REKLAMA
  • #3 9544750
    janbernat
    Poziom 38  
    Jaka płytka- czy nie ma tam czasem akumulatorka?
  • #4 9544787
    jwalentek
    Poziom 11  
    Płytka Propox-a EVBAVR05. Jest akumulatorek, ale odłączony.

    Programu w tej chwili nie zamieszczę bo jest dość rozgrzebany i musiałbym sporo zakomentować aby nie zaciemniać kodu.

    Zapytałem, może ktoś spotkał coś takiego? Podejrzewam, że może dokładność zegara wewnętrznego Atmegi wpływa na utratę łączności z RTC. Ale dlaczego nie da sie zresetować układu??? trzeba czekac nawet 20 min czasami ??
  • #5 9544803
    dondu
    Moderator na urlopie...
    Odnośnie 10-20 minut czekania - zrób eksperyment. Po wyłączeniu zasilania zrób zwarcie Vcc do GND i uruchom ponownie.

    Co do głównego problemu bez co najmniej programu będzie to wróżenie z fusów.
  • REKLAMA
  • #6 9544890
    jwalentek
    Poziom 11  
    Zwarcie Vcc do GND pomogło, ale dopiero takie dłuższe zwarcie ( 5 sek).
    Wyświetlacz ocnkął się, wyświetla dane, ale !!! ciekawostka, zegar stoi.

    Załaczam kod, taki wprost z Eclipsa, bez bibliotek.
    Jestem w trakcie przeróbki z innego projektu, proszę o wyrozumiałość.

    
    /*
     * main.c
     *
     *  Created on: 2010-09-25
     *   
     *
     * PD7 - 1WIRE
     * PA0..PA7 - LD0..LD7  - ledy
     * PA7 - LTG - podświetlenie wyświetlacza
     * PB0-PB6 - SW0-SW6  - przyciski
     * PD0 - R/S
     * PD1 - E
     * PB6 - D4
     * PD3 - D5
     * PD4 - D6
     * PD5 - D7
     * RTC
     * PC0 - SCL
     * PC1 - SDA
     * PD2 - FT
     *
     */
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/eeprom.h>
    //#include <avr/pgmspace.h>
    //#include <util/delay.h>
    
    #include "LCD/lcd44780.h"
    #include "1Wire/ds18x20.h"
    #include "twi.h"
    #include "rtc_lib.h"
    
    #define LED1 (1<<PA0)
    #define LED2 (1<<PA1)
    #define LED3 (1<<PA2)
    #define LED4 (1<<PA3)
    #define LED5 (1<<PA4)
    #define LED6 (1<<PA5)
    #define LED7 (1<<PA6)
    
    #define LED1_ON PORTA &= ~LED1
    #define LED1_OFF PORTA |= LED1
    #define LED2_ON PORTA &= ~LED2
    #define LED2_OFF PORTA |= LED2
    #define LED3_ON PORTA &= ~LED3
    #define LED3_OFF PORTA |= LED3
    #define LED4_ON PORTA &= ~LED4
    #define LED4_OFF PORTA |= LED4
    #define LED5_ON PORTA &= ~LED5
    #define LED5_OFF PORTA |= LED5
    #define LED6_ON PORTA &= ~LED6
    #define LED6_OFF PORTA |= LED6
    #define LED7_ON PORTA &= ~LED7
    #define LED7_OFF PORTA |= LED7
    
    #define LED3_TOG PORTA ^= LED3
    #define KL1 (1<<PB0)
    #define KL2 (1<<PB1)
    #define KL3 (1<<PB2)
    #define KL4 (1<<PB3)
    
    //#define NULL 0
    #define DEFAULT 0
    
    volatile uint8_t Timer1, Timer2, Timer_podswietlenia, Timer_menu0;	/* timery programowe 100Hz */
    volatile uint8_t int0_flag;   // flaga przerwania INT0 od układu RTC
    uint8_t czujniki_cnt;		/* ilość czujników na magistrali */
    uint8_t subzero, cel, cel_fract_bits;
    uint8_t init, X, Y, sekundy;
    volatile uint8_t s_sek, m_min, h_hrs;
    
    void display_temp(uint8_t y, uint8_t x);
    
    /************** funkcja SuperDebounce do obsługi pojedynczych klawiszy ***************/
    void SuperDebounce(uint8_t * key_state, volatile uint8_t *KPIN,
    		uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,
    		void (*push_proc)(void), void (*rep_proc)(void) );
    
    void rtc_get_czas(void)  {
    	uint8_t temp_s;
    	uint8_t temp_m;
    	uint8_t temp_h;
    
    	uint8_t time_s[2];
    	uint8_t time_m[2];
    	uint8_t time_h[2];
    
    	set_reg_pointer(0x3F);
    	twistart();
    	twiwrite(0xD1);
    	s_sek = twiread(ACK);
    	m_min = twiread(ACK);
    	h_hrs = twiread(NOACK);
    	twistop();
    
    	if(!(temp_h&0x40))   {
    		itoa(temp_h,time_h,16);
    		if(temp_h<0x10) {lcd_char('0'); lcd_str(time_h);}
    			else {lcd_str(time_h);}	lcd_char('-');
    		itoa(temp_m,time_m,16);
    		if(temp_m<0x10) {lcd_char('0'); lcd_str(time_m);}
    			else {lcd_str(time_m);}   lcd_char('-');
    		itoa(temp_s,time_s,16);
    		if(temp_s<0x10) {lcd_char('0'); lcd_str(time_s);}
    			else lcd_str(time_s);
    	}
    	else
    	{
    		itoa((temp_h&0x1F),time_h,16);
    		if((temp_h&0x1F)<0x10) {lcd_char('0'); lcd_str(time_h);} else lcd_str(time_h);
    		lcd_char('+');
    		itoa(temp_m,time_m,16);
    		if(temp_m<0x10) {lcd_char('0'); lcd_str(time_m);} else lcd_str(time_m);
    		lcd_char('+');
    		itoa(temp_s,time_s,16);
    		if(temp_s<0x10) {lcd_char('0'); lcd_str(time_s);} else lcd_str(time_s);
    	}
    }
    
    void lcd_on(void) {
    	LED7_ON; /* podświetlenie wyświetlacza LCD */
    	Timer_podswietlenia = 200;   // na 3 sekundy, powinno byc 360
    	Timer_menu0 = 163;
    }
    volatile uint16_t licznik;
    uint8_t poziom_menu;
    uint8_t EEMEM eeTustaw[7];
    uint8_t Tustaw[7];
    
    void menu (void){
    	lcd_on(); 			/* podświetlenie wyświetlacza LCD */
    	lcd_cls();
    	lcd_str("Ustawienia:");
    	++poziom_menu;
    	if (poziom_menu==8) poziom_menu=1;
    	if (poziom_menu==1) {
    		lcd_locate(1,0);
    		lcd_str("CEL");
    		X = 1; Y = 10;
    		lcd_locate(X,Y);
    		Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
    		lcd_int(Tustaw[poziom_menu-1]);
    	}
    	if (poziom_menu==2) {
    		lcd_locate(1,0);
    		lcd_str("T 550 zew.:");
    		X = 1; Y = 11;
    		lcd_locate(X,Y);
    		Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
    		lcd_int(Tustaw[poziom_menu-1]);
    	}
    	if (poziom_menu==3) {
    		lcd_locate(1,0);
    		lcd_str("T CUT30 zew.:");
    		X = 1; Y = 13;
    		lcd_locate(X,Y);
    		Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
    		lcd_int(Tustaw[poziom_menu-1]);
    	}
    	if (poziom_menu==4) {
    		lcd_locate(1,0);
    		lcd_str("T grz1:");
    		X = 1; Y = 7;
    		lcd_locate(X,Y);
    		Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
    		lcd_int(Tustaw[poziom_menu-1]);
    	}
    	if (poziom_menu==5) {
    		lcd_locate(1,0);
    		lcd_str("T grz2:");
    		X = 1; Y = 7;
    		lcd_locate(X,Y);
    		Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
    		lcd_int(Tustaw[poziom_menu-1]);
    	}
    	if (poziom_menu==6) {
    		lcd_locate(1,0);
    		lcd_str("T grz3:");
    		X = 1; Y = 7;
    		lcd_locate(X,Y);
    		Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
    		lcd_int(Tustaw[poziom_menu-1]);
    	}
    	if (poziom_menu==7) {
    		lcd_locate(1,0);
    		lcd_str("Lokalizacja");
    		X = 1; Y = 7;
    		lcd_locate(X,Y);
    		Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
    		lcd_int(Tustaw[poziom_menu-1]);
    	}
    
    	init=1;
    }
    void menu_w_przod (void) {
    	if (init) menu();
    	lcd_on();
    	Timer_podswietlenia=100;  // powinno być 163
    }
    void licznik_rep(void) {
    	if(init) {
    		lcd_locate(X,Y);
    		lcd_int(++Tustaw[poziom_menu-1]);
    		eeprom_write_byte(&eeTustaw[poziom_menu-1], Tustaw[poziom_menu-1]);
    		lcd_str("  ");
    		lcd_on(); 			/* podświetlenie wyświetlacza LCD */
    	}
    }
    void licznik_wstecz_rep(void) {
    	if(init) {
    		lcd_locate(X,Y);
    		lcd_int(--Tustaw[poziom_menu-1]);
    		eeprom_write_byte(&eeTustaw[poziom_menu-1], Tustaw[poziom_menu-1]);
    		lcd_str("  ");
    		lcd_on(); 			/* podświetlenie wyświetlacza LCD */
    	}
    }
    void count_licznik(void){
    	if(init) {
    		lcd_locate(X,Y);
    		lcd_int(++Tustaw[poziom_menu-1]);
    		eeprom_write_byte(&eeTustaw[poziom_menu-1], Tustaw[poziom_menu-1]);
    		lcd_str("  ");
    		lcd_on(); 			/* podświetlenie wyświetlacza LCD */
    	}
    }
    void count_licznik_wstecz(void){
    	if(init) {
    		lcd_locate(X,Y);
    		lcd_int(--Tustaw[poziom_menu-1]);
    		eeprom_write_byte(&eeTustaw[poziom_menu-1], Tustaw[poziom_menu-1]);
    		lcd_str("  ");
    		lcd_on(); 			/* podświetlenie wyświetlacza LCD */
    	}
    }
    int main(void) {
    	DDRA |= (1<<PA7);	 // port PA7 jest wyjściem - podświetlenie wyświetlacza
    	DDRA |= LED1|LED2|LED3|LED4|LED5|LED6|LED7;
    	lcd_init();
    	LED1_OFF;LED2_OFF;LED3_OFF;LED4_OFF;LED5_OFF;LED6_OFF;LED7_OFF;
    	PORTB |= KL1|KL2|KL3|KL4;
    		rtc_init();
    		rtc_control_reg(0,0x01,0,0);  // ustawienie RTC wraz z Timerem 1Hz
    		rtc_set_time(0x00,0x07,0x16,0x00,0x00); //ustawienie godz 16:07:00 - działa !
    		rtc_set_date(Saturday,0x15,0x05,0x11);  // ustawienie daty 15/05/2011 - działa !
    
    	/* Timer2 – inicjalizacja Timera0 */
    	TCCR0 	|= (1<<WGM01);			// tryb pracy CTC
    	TCCR0 	|= (1<<CS02)|(1<<CS00);	// preskaler = 1024 -> 7812Hz -> 0,128ms
    	OCR0 	= 255;					// przerwanie porównania -> 30,63Hz -> 32ms
    	TIMSK 	|= (1<<OCIE0);			// Odblokowanie przerwania CompareMatch
    	/* Inicjalizacja przerwania INT0 */
    	MCUCR    |= (1<<ISC01);   //wyzwolenie zboczem opadającym
    	GICR     |= (1<<INT0);    //odblokowanie przerwania
    	PORTD    |= (1<<PD2);     // podciągnięcie pinu INT0 do VCC
    
    	sei();
    
    	int Zm=1;
    	while(1) {
    		uint8_t k1, k2, k3;
    
    		SuperDebounce(&k1, &PINB, KL1, 36, 36, menu_w_przod, menu );
    		SuperDebounce(&k2, &PINB, KL2, DEFAULT, DEFAULT, count_licznik, licznik_rep );
    		SuperDebounce(&k3, &PINB, KL3, DEFAULT, DEFAULT, count_licznik_wstecz, licznik_wstecz_rep );
    		if( !Timer2 ) {
    			Timer2=20;  //powinno byc 36 to by było 1 sek, na razie przyspieszamy
    			/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 0 zamieniaj data/godz */
    			if( 0 == (sekundy%3) ) {
    				if (!poziom_menu) {
    					if (Zm && !poziom_menu) {               // tu wstawic procedurę wyswietlająca aktualną datę/godzinę
    						lcd_locate(0,0);lcd_str(" Zm=1 ");
    						rtc_get_czas();
    						lcd_int(h_hrs); lcd_str("-");lcd_int(m_min);lcd_str("-"); lcd_int(s_sek);
    						lcd_locate(1,0);
    						rtc_get_time(1);
    						//lcd_str("H-46000 V12000  ");
    						Zm = 0;
    					}
    					else	{
    						lcd_locate(0,0);lcd_str(" Zm=0 ");
    						//rtc_get_date();
    						Zm = 1;
    				}
    				}
    			}
    			/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 1 wysyłaj rozkaz pomiaru do czujników */
    			//if( 1 == (sekundy%3) ) DS18X20_start_meas( DS18X20_POWER_EXTERN, NULL );
    			/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 2 czyli jedną sekundę po rozkazie konwersji
    			*  dokonuj odczytu i wyświetlania temperatur z 4 czujników jeśli są podłączone, jeśli nie
    			*  to pokaż komunikat o błędzie*/
    //			if( 2 == (sekundy%3) ) {
    //				if( DS18X20_OK == DS18X20_read_meas(gSensorIDs[0], &subzero, &cel, &cel_fract_bits) ) {
    //					display_temp(0,5);
    //					if (subzero) znak=-1; else znak=1;
    //					T[0] = znak*(cel*10 + cel_fract_bits);
    //				}
    //				else {
    //					lcd_locate(0,5);
    //					lcd_str(" err  ");
    //					LED1_OFF;
    //				}
    //
    //				if( DS18X20_OK == DS18X20_read_meas(gSensorIDs[1], &subzero, &cel, &cel_fract_bits) ) {
    //					display_temp(0,11);
    //					if (subzero) znak=-1; else znak=1;
    //					T[1] = znak*(cel*10 + cel_fract_bits);
    //				}
    //				else {
    //					lcd_locate(0,11);
    //					lcd_str(" err  ");
    //				}
    //				if( DS18X20_OK == DS18X20_read_meas(gSensorIDs[2], &subzero, &cel, &cel_fract_bits) ) {
    //					display_temp(1,5);
    //					if (subzero) znak=-1; else znak=1;
    //					T[2] = znak*(cel*10 + cel_fract_bits);
    //				}
    //				else {
    //					lcd_locate(1,5);
    //					lcd_str(" err  ");
    //				}
    //				if( DS18X20_OK == DS18X20_read_meas(gSensorIDs[3], &subzero, &cel, &cel_fract_bits) ) {
    //					display_temp(1,11);
    //					if (subzero) znak=-1; else znak=1;
    //					T[3] = znak*(cel*10 + cel_fract_bits);
    //				}
    //				else {
    //					lcd_locate(1,11);
    //					lcd_str(" err  ");
    //				}
    //			}
    		sekundy++;
    		if (sekundy>2) sekundy = 0;
    		};
    		if( !Timer_podswietlenia ) {
    			PORTA &= ~(1<<PA7); /* wył. podświetlenia wyświetlacza LCD */
    		};
    		if (!Timer_menu0 && poziom_menu) {   //timer wyjścia z menu po kilku sekundach
    			poziom_menu = 0;// wróć do menu 0
    			lcd_cls();
    			init = 0;
    			lcd_str("TRYB NORMALNY   ");
    		}
    	}
    }
    
    
    
    /************** funkcja SuperDebounce do obsługi pojedynczych klawiszy ***************
     * 					
     * ZALETY:
     * 		- nie wprowadza najmniejszego spowalnienia
     * 		- posiada funkcję REPEAT (powtarzanie akcji dla dłużej wciśniętego przycisku)
     * 		- można przydzielić różne akcje dla trybu REPEAT i pojedynczego kliknięcia
     * 		- można przydzielić tylko jedną akcję wtedy w miejsce drugiej przekazujemy 0 (NULL)
     *
     * Wymagania:
     * 	Timer programowy utworzony w oparciu o Timer sprzętowy (przerwanie 100Hz)
     *
     * 	Parametry wejściowe:
     * 	*key_state - wskaźnik na zmienną w pamięci RAM (1 bajt)
     *  *KPIN - nazwa PINx portu na którym umieszczony jest klawisz, np: PINB
     *  key_mask - maska klawisza np: (1<<PB3)
     *  rep_time - czas powtarzania funkcji rep_proc w trybie REPEAT
     *  rep_wait - czas oczekiwania do przejścia do trybu REPEAT
     *  push_proc - wskaźnik do własnej funkcji wywoływanej raz po zwolenieniu przycisku
     *  rep_proc - wskaźnik do własnej funkcji wykonywanej w trybie REPEAT
     **************************************************************************************/
    void SuperDebounce(uint8_t * key_state, volatile uint8_t *KPIN,
    		uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,
    		void (*push_proc)(void), void (*rep_proc)(void) ) {
    
    	enum {idle, debounce, go_rep, wait_rep, rep};
    
    	if(!rep_time) rep_time=3;
    	if(!rep_wait) rep_wait=6*3.6;
    
    	uint8_t key_press = !(*KPIN & key_mask);
    
    	if( key_press && !*key_state ) {
    		*key_state = debounce;
    		Timer1 = 4;
    	} else
    	if( *key_state  ) {
    
    		if( key_press && debounce==*key_state && !Timer1 ) {
    			*key_state = 2;
    			Timer1=4;
    		} else
    		if( !key_press && *key_state>1 && *key_state<4 ) {
    			if(push_proc) push_proc();						/* KEY_UP */
    			*key_state=idle;
    		} else
    		if( key_press && go_rep==*key_state && !Timer1 ) {
    			*key_state = wait_rep;
    			Timer1=rep_wait;
    		} else
    		if( key_press && wait_rep==*key_state && !Timer1 ) {
    			*key_state = rep;
    		} else
    		if( key_press && rep==*key_state && !Timer1 ) {
    			Timer1 = rep_time;
    			if(rep_proc) rep_proc();						/* KEY_REP */
    		}
    	}
    	if( *key_state>=3 && !key_press ) *key_state = idle;
    }
    ISR(TIMER0_COMP_vect)
    {
    static uint8_t n;
    	n = Timer1;		/* 100Hz Timer1 */
    	if (n) Timer1 = --n;
    	n = Timer2;		/* 100Hz Timer2 */
    	if (n) Timer2 = --n;
    	n = Timer_podswietlenia;
    	if (n) Timer_podswietlenia= --n;
    	n = Timer_menu0;
    	if (n) Timer_menu0= --n;
    }
    ISR(INT0_vect) {
    	int0_flag = 1;
    	LED3_TOG;
    }
    
  • #7 9544912
    janbernat
    Poziom 38  
    To po pierwsze- lutownica w dłoń i wywal ten akumulatorek.
    Po drugie- znajdź gniazdo na ogniwo 3V- jakis CR - no i ogniwo.
    Wlutuj.
    Ustaw zworki tak aby nie próbować ładować tego ogniwa- bo wybuchnie.
    Ten typ tak ma.
    DS1307 po stwierdzeniu że napięcie na baterii jest większe niż pewna róznica między napięciem zasilania a napięciem baterii "głuchnie".
    Sprawdź w pdf DS1307 jaka.
    To jest wrodzona wada płytek z Propoxu.
    Druga jest (była?) taka że mikroprzełączniki dają nie z Chin ale chyba z jakiejś wytwórni w dżungli afrykańskiej.
    Jak najszybciej je zmień.
    Kłopotliwe- ale trzeba.
    Poza tym płytki są super- ale któz jest bez wad...
  • REKLAMA
  • #9 9544959
    jwalentek
    Poziom 11  
    Dzięki, chyba problem rozwiązany, gdyż doczytałem w PDF, ze faktycznie układ nie działa poprawnie przy napięciu Vbat zbyt dużym. U mnie było aż 4.08V.
    Jutro to poprawię.

    Pozdrawiam
  • #10 9548273
    jwalentek
    Poziom 11  
    Koledzy mam następny problem z układem DS1307.

    Dlaczego resetując Atmegę16 resetują się również sekundy w układzie rtc ( zaczynają liczenie od 00). Przy ponownym wyłączeniu i włączeniu zasilania jest podobnie.
    Układ ma podtrzymanie bateryjne Lithum 3V.
    Poprawnie zlicza czas, zarówno na zasilaniu Vcc jak i na Vbat. Resetują sie tylko sekundy.
  • #11 9549203
    janbernat
    Poziom 38  
    Czy masz wyjęte zworki LOAD i BACKUP?
  • #12 9550823
    jwalentek
    Poziom 11  
    Oczywiście, zegar zasilany jest z baterii 3V.
  • #13 9554769
    janbernat
    Poziom 38  
    Czyli zamiast akumulatora masz wlutowane gniazdko na baterię i wsadzoną w nie baterię?
  • #14 9562917
    flapo213
    Poziom 21  
    Witaj,

    W Twoim kodzie nigdzie nie znalazłem funkcji obsługi I2C. Przy Avr-ach ważne jest jak sterujesz portami podczas komunikacji po I2C jak nieumiejętnie to zrobisz to będziesz doprowadzał do zwarć (porty open collector) co spowoduje niekontrolowane resety i np takie dziwne akcje jak masz. Proponuję o ile możesz zmienić hardware na sprzętowy I2C działa bardzo dobrze. Pozdrawiam
REKLAMA