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 i AT90CAN128] [C] USART synchroniczny - problem

Krzysiek_k1984 04 Lip 2008 08:54 3792 11
REKLAMA
  • #1 5310025
    Krzysiek_k1984
    Poziom 13  
    Witam.

    Od dłuższego czasu siedzę nad komunikacją USART synchroniczną pomiędzy ATmega16 i AT90CAN128 i nie potrafię dojść dlaczego nie działa. ATmega16 taktowany jest zewnętrznym kwarcem 3,686400 MHz, a AT90 z wewnętrznego oscylatora RC 8MHz. Docelowo będzie taktowany z pinu OC1A w atmedze, dlatego zdecydowałem się na transmisję synchroniczną. Atmega mierzy napięcie na potencjometrze i temperaturę (DS18B20). Całość wyświetlana jest na LCD. To wszystko śmiga. Napięcie i temperatura będą w przyszłości wysyłane po magistrali CAN przez at90. Chciałem sprawdzić czy komunikacja pomiędzy uP przebiega poprawnie, dlatego gdy przycisnę klawisz podpięty do portu PD7 następuje wysłanie część zmierzonej temperatury (tylko całości) do at90, a ten powinien mi otrzymane dane odesłać. Niestety po naciśnięciu klawisza (PD7) atmega jakby się zawiesza. Tzn. na wyświetlaczu nie wyświetlają się napisy (ODEBRANE DANE itp.) tylko pozostaje widoczny cały czas wcześniejszy tekst. Po zakomentowaniu 2 linii (rs_getch(); temp2=UDR;) program przechodzi dalej powodując zmianę na wyświetlaczu. Nie wiem już co może być źle w programie. Z góry dzięki za wszelkie sugestie co zrobiłem źle.

    Kod programu AT90CAN128:
    
    #include<avr/io.h>
    #include<compat/deprecated.h>
    #include<avr/interrupt.h>
    #include "rssynch.h"
    
    
    signed char temp2=0;
    
    ISR(USART0_RX_vect) //przerwanie gdy odbiór zakończony
    {
    	rs0_getch();
    	temp2=UDR0;
    	if(temp2>0)
    	{
    		cbi(DDRE, PE2); 	//sygnał XCK jako wyjście
    		rs0_putch(temp2);	//wyślij otrzymane dane
    		temp2=0;
    	}
    }
    
    int main()
    {
    	sbi(DDRE, PE2);		//XCK jako wejście
    	rs0_init(600);
    	UCSR0B=(1<<RXCIE0);	//dostępne przerwanie gdy odbiór zakończony
    	sei();
    	while(1);
    	{	
    	}
    	return 0;
    }
    


    Biblioteka rssynch dla AT90:
    
    #include"rssynch.h"
    
    
    void rs0_init(long int baud)
    {
    	UBRR0H=(unsigned char)((F_CPU/(2*baud)-1)>>8);
    	UBRR0L=(unsigned char)(F_CPU/(2*baud)-1);
    	UCSR0B=(1<<RXEN0) | (1<<TXEN0);	//odblokowanie: odbiornika, nadajnika
    	UCSR0C=(1<<UMSEL0) | (3<<UCSZ0) | (1<<UCPOL0);
    	//praca synchroniczna, tryb 8 bitowy
    }
    
    
    void rs0_putch(unsigned char data)
    {
    	//czekaj aż zwolni się bufor transmisji
    	while (!(UCSR0A & (1<<UDRE0)));
    	UDR0=data;
    }
    
    
    unsigned char rs0_getch(void)
    {
    	//czekaj na dane aż zostaną odebrane
    	while(!(UCSR0A & (1<<RXC0)));
    	return UDR0;
    }
    


    Niedziałająca część programu w ATmega16:
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <compat/deprecated.h>
    #include <stdio.h>
    #include "lcd.h"
    #include "ow.h"
    #include "rssynch.h"
    
    
    //******************************************
    //**-------- DELKARACJA ZMIENNYCH --------**
    //******************************************
    
    unsigned int nap, calk, ulamek; //wynik z przetwornika A/C
    
    char napis[20];					//bufor w którym wyświetlam
    unsigned char buf[9];			//bufor 9 bajtowy od temp.
    signed char temp;				//temperatura całości
    int	ulamek_temp;	 			//temperatura po przecinku
    signed char temp2;
    
    unsigned char tryb=0;			//tryb pracy - klawisz 3
    
    
    //******************************************
    //**------------ WYŚWIETLANIE ------------**
    //******************************************
    
    void wyswietl()
    {
    	lcd_gotoxy(0,0);			//linia 1
    	switch(tryb)
    	{
    		case 0:	sprintf(napis,"Napiecie=%1d.%02dV", calk,ulamek);
    		break;
    		case 1: sprintf(napis, "ODEBRANE DANE   ");
    	}
    	lcd_putstr(napis);
    
    	lcd_gotoxy(0,1);			//linia 2
    	switch(tryb)
    	{
    		case 0:	sprintf(napis, "%2d.%02d\xDF\x43   POMIAR",temp,ulamek_temp);
    		break;
    		case 1: sprintf(napis, "%2d       ", temp2);
    	}
    	lcd_putstr(napis);
    }
    .
    .
    .
    .
    int main()
    {
    	DDRB=0xFE;					//11 11 11 10 -> PB0 - XCK jako wyjście
    	PORTB=0x00;					//00 00 00 00 -> stan niski na porcie B
    
    	DDRC=0x00;					//00 00 00 00
    	PORTC=0x00;					//00 00 00 00
    
    	DDRD=0x00;					//00 00 00 00 -> port D jako wyjście
    	PORTD=0x8C;					//10 00 11 00 -> klawisze na porcie D w stan wysoki
    
    	lcd_init();					//inicjalizacja LCD
    	lcd_cls(); 					//czyszczenie LCD
    
    	init_AC();					//inicjalizacja A/C
    	rs_init(2400);				//inicjalizacja RS'a
    .
    .
    .
    .
    while(1)
    	{
    		if(bit_is_clear(PIND, PD7))		//klawisz 3
    		{
    			if(tryb<1)	
    			{
    				tryb++;
    
    				if(tryb)
    				{
    					rs_putch(temp);
    
    					sbi(DDRB, PB0);		//XCK jako wejście
    					rs_getch();
    					temp2=UDR;
    				}
    			}
    			else		tryb=0;
    		
    			wyswietl();
    			do {}					//czekaj aż klawisz zostanie puszczony
    			while(bit_is_clear(PIND, PD7));
    		}
    	}
    	return 0;
    }
    


    Plik rssynch dla ATmega16:
    
    #include"rssynch.h"
    
    
    void rs0_init(long int baud)
    {
    	UBRR0H=(unsigned char)((F_CPU/(2*baud)-1)>>8);
    	UBRR0L=(unsigned char)(F_CPU/(2*baud)-1);
    	UCSR0B=(1<<RXEN0) | (1<<TXEN0);	//odblokowanie: odbiornika, nadajnika
    	UCSR0C=(1<<UMSEL0) | (3<<UCSZ0) | (1<<UCPOL0);
    	//praca synchroniczna, tryb 8 bitowy
    }
    
    
    void rs0_putch(unsigned char data)
    {
    	//czekaj aż zwolni się bufor transmisji
    	while (!(UCSR0A & (1<<UDRE0)));
    	UDR0=data;
    }
    
    
    unsigned char rs0_getch(void)
    {
    	//czekaj na dane aż zostaną odebrane
    	while(!(UCSR0A & (1<<RXC0)));
    	return UDR0;
    }
    


    Nie umieściłem całego kodu programu dla ATmega, gdyż ta część co jest wykropkowana działa poprawnie;)
  • REKLAMA
  • Pomocny post
    #2 5310230
    piotrkopec
    Poziom 17  
    Kolego, delikatna masakra
    z listingu 1:
    if(temp2>0)
       { 

    jeśli temperatura 0 to nie odpowiadamy i atmega wisi?
    cbi(DDRE, PE2);    //sygnał XCK jako wyjście
          rs0_putch(temp2);   //wyślij otrzymane dane 

    i może wypadałoby przestawić XCK spowrotem na weście?
    z listingu 3:
             if(tryb<1)   
             {
                tryb++;
    
                if(tryb)
                { 

    tryb jest typu unsigned char więc jedyną możliwą wartością wartością mniejszą od 1 jest 0 która po ++ wyniesie 1 i na pewno if(tryb) przejdzie dalej
    tutaj również zapominasz o powrotnym przestawieniu XCK

    sprawdzanie które dziecko w kółeczku pierdnęło jest trudne jeśli dzieciaki się kręcą( takie chińskie przysłowie;) ).
    Najpierw niech at90 zaświeci choć diodę jeśli odbierze dane( nie wiadomo czy cokolwiek odbiera) i wyśle je do megi a potem podobnym sposobem sprawdź komunikację powrotną.
    Jak komunikacja będzie działała to pomyśl nad timeoutami
    Więcej nie widzę
    Pozdrawiam
    Piotrek
  • #3 5310307
    Krzysiek_k1984
    Poziom 13  
    OK dzięki:) Rzeczywiście trochę namieszałem.

    Program z AT90 zmieniłem w taki sposób:
    
    #include<avr/io.h>
    #include<compat/deprecated.h>
    #include<avr/interrupt.h>
    #include "rssynch.h"
    
    
    unsigned char temp2=0;
    
    ISR(USART0_RX_vect)		//przerwanie gdy odbiór zakończony
    {
    	rs0_getch();
    	temp2=UDR0;
    
    	cbi(DDRE, PE2); 	//sygnał XCK jako wyjście
    	rs0_putch(temp2);	//wyślij otrzymane dane
    }
    
    
    ISR(USART0_TX_vect)		//przerwanie gdy zakończona transmisja
    {
    	sbi(DDRE, PE2);		//sygnał XCK jako wejście
    }
    
    
    int main()
    {
    	sbi(DDRE, PE2);		//XCK jako wejście
    	rs0_init(600);
    	//dostępne przerwania gdy odbiór i transmisja zakończona
    	UCSR0B|=(1<<RXCIE0)|(1<<TXCIE0);
    	sei();
    	while(1);
    	{	
    	}
    	return 0;
    }
    


    Mam nadzieje, że nie ma w nim więcej błędów. Pozmieniam jeszcze program w atmega i też umieszcze ;)

    Dodano po 37 [minuty]:

    Kod z ATMEGA16:
    
    //******************************************
    //**-------- DELKARACJA ZMIENNYCH --------**
    //******************************************
    
    unsigned int nap, calk, ulamek; //wynik z przetwornika A/C
    
    char napis[20];					//bufor w którym wyświetlam
    unsigned char buf[9];			//bufor 9 bajtowy od temp.
    signed char temp;				//temperatura całości
    int	ulamek_temp;	 			//temperatura po przecinku
    signed char temp2;
    
    unsigned char tryb=0;			//tryb pracy - klawisz 3
    
    
    //******************************************
    //**------------ WYŚWIETLANIE ------------**
    //******************************************
    
    void wyswietl()
    {
    	lcd_gotoxy(0,0);			//linia 1
    	switch(tryb)
    	{
    		case 0:	sprintf(napis,"Napiecie=%1d.%02dV", calk,ulamek);
    		break;
    		case 1: sprintf(napis, "ODEBRANE DANE   ");
    	}
    	lcd_putstr(napis);
    
    	lcd_gotoxy(0,1);			//linia 2
    	switch(tryb)
    	{
    		case 0:	sprintf(napis, "%2d.%02d\xDF\x43   POMIAR",temp,ulamek_temp);
    		break;
    		case 1: sprintf(napis, "  %2d            ", temp2);
    	}
    	lcd_putstr(napis);
    }
    .
    .
    .
    .
    ISR(USART_RXC_vect)				//przerwanie gdy odbiór zakończony
    {
    	rs_getch();
    	temp2=UDR;
    	wyswietl();
    	cbi(DDRB, PB0); 			//sygnał XCK jako wyjście
    }
    
    ISR(USART_TXC_vect)				//przerwanie gdy transmisja zakończona
    {
    	sbi(DDRB, PB0);				//sygnał XCK jako wejście
    }
    
    int main()
    {
    	DDRB=0xFE;					//11 11 11 10 -> PB0 - XCK jako wyjście
    	PORTB=0x00;					//00 00 00 00 -> stan niski na porcie B
    
    	DDRC=0x00;					//00 00 00 00
    	PORTC=0x00;					//00 00 00 00
    
    	DDRD=0x00;					//00 00 00 00 -> port D jako wyjście
    	PORTD=0x8C;					//10 00 11 00 -> klawisze na porcie D w stan wysoki
    
    	lcd_init();					//inicjalizacja LCD
    	lcd_cls(); 					//czyszczenie LCD
    
    	init_AC();					//inicjalizacja A/C
    	rs_init(2400);				//inicjalizacja RS'a
    	
    	//odblokowanie przerwań zakończenia transmisji i odbioru
    	UCSRB|=(1<<RXCIE) | (1<<TXCIE);
    	sei();						//dostepne wszystkie globalne przerwania
    .
    .
    .
    .
    	while(1)
    	{
    		if(bit_is_clear(PIND, PD7))		//klawisz 3
    		{
    			if(tryb==0)	
    			{
    				tryb++;
    				if(tryb)
    				{
    					rs_putch(temp);
    				}
    			}
    			else		tryb=0;
    		
    			wyswietl();
    			do {}					//czekaj aż klawisz zostanie puszczony
    			while(bit_is_clear(PIND, PD7));
    		}
    	}
    	return 0;
    }
    


    Coś zaczęło działać ;) Zastanawia mnie tylko fakt, że dopiero po piątym naciśnięciu klawisza na LCD pojawia się prawidłowa temperatura. Wcześniej w miejscu, gdzie jest wyświetlana widnieje 0. Jeśli zmierzona temperatura wynosi 26 stopni to gdy pięć razy nacisnę klawisz (PD7) pojawia się 26, tak samo z innymi wartościami temperatury. Macie jakieś pomysły co jeszcze mam źle?
  • #4 5313594
    Krzysiek_k1984
    Poziom 13  
    Postanowiłem zrobić taki test:
    Po wysłaniu przez atmega do at90 temperatury ten powinien zwrócić ciąg danych. Pierwsza dana to temperatura, druga 56, trzecia 40, czwarta 24 i piąta 8. Ciąg danych następnie wyświetlany jest na LCD i oto co dostałem.

    [ATmega16 i AT90CAN128] [C] USART synchroniczny - problem

    Czyli jakby 1 dana (ta wysłana przez atmega i zwrócona) zostaje zgubiona, a druga jest przesunięta.
    Jeżeli zamiast odebranej temperatury odeślę inną wartość (wpisaną na sztywno) to pojawia się ona na drugim miejscu LCD. Skąd może wynikać takie przesunięcie i co może być źle w programie?

    AT90CAN128:
    
    #include<avr/io.h>
    #include<compat/deprecated.h>
    #include<avr/interrupt.h>
    #include <util/delay.h>
    #include "rssynch.h"
    
    
    unsigned char temp2=0;
    unsigned char	temp3=0, temp4=0,temp5=0,temp6=0;
    
    ISR(USART0_RX_vect)		//przerwanie gdy odbiór zakończony
    {	
    	rs0_getch();
    	//temp2=UDR0;
    	temp2=60;
    	temp3=56;
    	temp4=40;
    	temp5=24;
    	temp6=8;
    	UCSR0B|=~(1<<TXCIE0);
    	cbi(DDRE, PE2); 	//sygnał XCK jako wyjście
    	rs0_putch(temp2);	//wyślij otrzymane dane
    	rs0_putch(temp3);
    	rs0_putch(temp4);
    	rs0_putch(temp5);
    	rs0_putch(temp6);
    	UCSR0B|=(1<<TXCIE0);
    
    }
    
    
    ISR(USART0_TX_vect)		//przerwanie gdy zakończona transmisja
    {
    	sbi(DDRE, PE2);		//sygnał XCK jako wejście
    }
    
    int main()
    {
    	sbi(DDRE, PE2);		//XCK jako wejście
    	rs0_init(600);
    	//dostępne przerwania gdy odbiór i transmisja zakończona
    	UCSR0B|=(1<<RXCIE0)|(1<<TXCIE0);
    	sei();
    	while(1);
    	{	
    	}
    	return 0;
    }
    



    Część programu ATmega16:

    
    //******************************************
    //**-------- DELKARACJA ZMIENNYCH --------**
    //******************************************
    
    unsigned int nap, calk, ulamek; //wynik z przetwornika A/C
    
    char napis[20];					//bufor w którym wyświetlam
    unsigned char buf[9];			//bufor 9 bajtowy od temp.
    unsigned char temp;				//temperatura całości
    int	ulamek_temp;	 			//temperatura po przecinku
    unsigned char temp2,temp3,temp4,temp5,temp6;
    
    unsigned char tryb=0;			//tryb pracy - klawisz 3
    
    
    //******************************************
    //**------------ WYŚWIETLANIE ------------**
    //******************************************
    
    void wyswietl()
    {
    	lcd_gotoxy(0,0);			//linia 1
    	switch(tryb)
    	{
    		case 0:	sprintf(napis,"Napiecie=%1d.%02dV", calk,ulamek);
    		break;
    		case 1: sprintf(napis, "ODEBRANE DANE   ");
    	}
    	lcd_putstr(napis);
    
    	lcd_gotoxy(0,1);			//linia 2
    	switch(tryb)
    	{
    		case 0:	sprintf(napis, "%2d.%02d\xDF\x43   POMIAR",temp,ulamek_temp);
    		break;
    		case 1: sprintf(napis, "%2d.%2d.%2d.%2d.%2d  ", temp2,temp3,temp4,temp5,temp6);
    	}
    	lcd_putstr(napis);
    }
    .
    .
    .
    .
    ISR(USART_RXC_vect)				//przerwanie gdy odbiór zakończony
    {
    	UCSRB|=~(1<<RXCIE);
    	rs_getch();
    	temp2=UDR;
    	rs_getch();
    	temp3=UDR;
    	rs_getch();
    	temp4=UDR;
    	rs_getch();
    	temp5=UDR;
    	rs_getch();
    	temp6=UDR;
    	UCSRB|=(1<<RXCIE);
    	cbi(DDRB, PB0); 			//sygnał XCK jako wyjście
    	wyswietl();
    }
    
    ISR(USART_TXC_vect)				//przerwanie gdy transmisja zakończona
    {
    	sbi(DDRB, PB0);				//sygnał XCK jako wejście
    }
    
    
    int main()
    {
    	DDRB=0xFE;					//11 11 11 10 -> PB0 - XCK jako wyjście
    	PORTB=0x00;					//00 00 00 00 -> stan niski na porcie B
    
    	DDRC=0x00;					//00 00 00 00
    	PORTC=0x00;					//00 00 00 00
    
    	DDRD=0x00;					//00 00 00 00 -> port D jako wyjście
    	PORTD=0x8C;					//10 00 11 00 -> klawisze na porcie D w stan wysoki
    
    	lcd_init();					//inicjalizacja LCD
    	lcd_cls(); 					//czyszczenie LCD
    
    	init_AC();					//inicjalizacja A/C
    	rs_init(2400);				//inicjalizacja RS'a
    	
    	//odblokowanie przerwań zakończenia transmisji i odbioru
    	UCSRB|=(1<<RXCIE) | (1<<TXCIE);
    	sei();						//dostepne wszystkie globalne przerwania
    
    while(1)
    	{
    		if(bit_is_clear(PIND, PD7))		//klawisz 3
    		{
    			if(tryb==0)	
    			{
    				tryb++;
    				if(tryb)
    				{
    					rs_putch(temp);
    				}
    			}
    			else		tryb=0;
    		
    			wyswietl();
    			do {}					//czekaj aż klawisz zostanie puszczony
    			while(bit_is_clear(PIND, PD7));
    		}
    	}
    	return 0;
    }
    
  • REKLAMA
  • #5 5316058
    piotrkopec
    Poziom 17  
    Kolego, dość swobodnie posługujesz się przerwaniami ale zapominasz o tym, że globalne zmienne które są używane w przerwaniach( u Ciebie dane z odbioru) powinny być deklarowane jako volatile( u Ciebie "volatile unsigned char temp2,temp3..."). Dlaczego? Miliardy wyrwanych włosów->setki postów->wyszukiwarka.
    Nie zwróciłem wcześniej uwagi.
    Miłej Niedzieli
  • #6 5316112
    Krzysiek_k1984
    Poziom 13  
    Niestety to jednak nie w tym tkwi problem. Zmieniłem troszkę program dlatego opisze jeszcze raz o co chodzi ;)

    Usunąłem wszystkie błędy programu i o dziwo komunikacja jako tako działa, ale oczywiście jest jedno "ale" z którym jakoś nie potrafię sobie poradzić i nie wiem dlaczego tak się dzieje. ATmega16 (do niej podłączony jest klawisz i LCD) mierzy temperaturę, wysyła ją po naciśnięciu klawisza do AT90CAN128 po USART'ie synchronicznym. AT90 odsyła mi daną temperaturę i 4 kolejne bajty - tak dla sprawdzenia komunikacji. Pierwsze zdjęcie pokazuje co widnieje na LCD po włączeniu układu. Naciskając klawisz ATmega wysyła temperaturę, a AT90 mi ją odsyła z innymi danymi. Tak więc na pierwszym miejscu LCD powinna być owa temperatura, a na kolejnych miejscach jej wartość zwiększona o 10, 20 i dwie stałe 24 i 8. Czyli w sumie powinno ukazać się 5 zmiennych w takiej kolejności: temperatura, temperatura+10, temperatura+20, 24, 8. U mnie niestety pokazuje się to co widoczne jest na zdjęciu nr 2 "po jednym naciśnięciu klawisza". O dziwo gdy klawisz nacisnę jeszcze dwa razy wysłana temperatura wkońcu się pojawi tylko nie wiem dlaczego na drugim miejscu LCD. Powinna być na pierwszym.

    Włączenie układu:
    [ATmega16 i AT90CAN128] [C] USART synchroniczny - problem

    Po jednokrotnym naciśnięciu klawisza:
    [ATmega16 i AT90CAN128] [C] USART synchroniczny - problem

    Po drugim naciśnięciu klawisza:
    [ATmega16 i AT90CAN128] [C] USART synchroniczny - problem

    Po trzecim naciśnięciu klawisza:
    [ATmega16 i AT90CAN128] [C] USART synchroniczny - problem

    Kod AT90CAN128:
    
    #include<avr/io.h>
    #include<compat/deprecated.h>
    #include<avr/interrupt.h>
    #include <util/delay.h>
    #include "rssynch.h"
    
    
    
    volatile unsigned char temp2=0, temp3=0, temp4=0,temp5=0,temp6=0;
    
    
    
    //*******************************************
    //**---- PODPROGRAM OBSŁUGI PRZERWANIA ----**
    //**-------- GDY ODBIÓR ZAKOŃCZONY --------**
    //*******************************************
    
    ISR(USART0_RX_vect)
    {	
    	UCSR0B&=~(1<<RXCIE0);	//zablokowane przerwanie gdy odbiór zakończony
    
    	cbi(DDRE, PE2); 	//sygnał XCK jako wyjście
    	rs0_getch();
    	temp2=UDR0;
    	temp3=temp2+10;
    	temp4=temp3+20;
    	temp5=24;
    	temp6=8;
    
    	rs0_putch(temp2);	//wyślij otrzymane dane
    	rs0_putch(temp3);
    	rs0_putch(temp4);
    	rs0_putch(temp5);
    	rs0_putch(temp6);
    
    	UCSR0B|=(1<<TXCIE0);//dostępne przerwanie gdy transmisja zakończona
    
    }
    
    
    
    //*******************************************
    //**---- PODPROGRAM OBSŁUGI PRZERWANIA ----**
    //**------ GDY TRANSMISJA ZAKOŃCZONA ------**
    //*******************************************
    
    ISR(USART0_TX_vect)
    {
    	UCSR0B&=~(1<TXCIE0);//blokowanie przerwania gdy transmisja zakończona
    	sbi(DDRE, PE2);		//sygnał XCK jako wejście
    	UCSR0B|=(1<<RXCIE0);//dostępne przerwania gdy odbiór zakończony
    }
    int main()
    {
    	sbi(DDRE, PE2);		//XCK jako wejście
    	rs0_init(1000);
    
    	//dostępne przerwania gdy odbiór zakończony
    	UCSR0B|=(1<<RXCIE0);
    	sei();
    	while(1);
    	{	
    	}
    	return 0;
    }
    



    Część kodu ATmega16:
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <compat/deprecated.h>
    #include <stdio.h>
    #include "lcd.h"
    #include "ow.h"
    #include "rssynch.h"
    
    
    // || ******************************************
    // || **-------- DELKARACJA ZMIENNYCH --------**
    // \/ ******************************************
    
    unsigned int nap, calk, ulamek; //wynik z przetwornika A/C
    
    char napis[20];					//bufor w którym wyświetlam
    unsigned char buf[9];			//bufor 9 bajtowy od temp.
    volatile unsigned char temp;				//temperatura całości
    int	ulamek_temp;	 			//temperatura po przecinku
    volatile unsigned char temp2=0,temp3=0,temp4=0,temp5=0,temp6=0;
    
    unsigned char tryb=0;			//tryb pracy - klawisz 3
    
    
    
    // || ******************************************
    // || **------------ WYŚWIETLANIE ------------**
    // \/ ******************************************
    
    void wyswietl()
    {
    	lcd_gotoxy(0,0);			//linia 1
    	switch(tryb)
    	{
    		case 0:	sprintf(napis,"Napiecie=%1d.%02dV", calk,ulamek);
    		break;
    		case 1: sprintf(napis, "ODEBRANE DANE   ");
    	}
    	lcd_putstr(napis);
    
    	lcd_gotoxy(0,1);			//linia 2
    	switch(tryb)
    	{
    		case 0:	sprintf(napis, "%2d.%02d\xDF\x43   POMIAR",temp,ulamek_temp);
    		break;
    		case 1: sprintf(napis, "%2d.%2d.%2d.%2d.%2d  ", temp2,temp3,temp4,temp5,temp6);
    	}
    	lcd_putstr(napis);
    }
    .
    .
    .
    .
    // || *******************************************
    // || **---- PODPROGRAM OBSŁUGI PRZERWANIA ----**
    // || **-------- GDY ODBIÓR ZAKOŃCZONY --------**
    // \/ *******************************************
    
    ISR(USART_RXC_vect)
    {
    	UCSRB&=~(1<<RXCIE);			//wyłączenie przerwania gdy odbiór zakończony
    	rs_getch();
    	temp2=UDR;
    	rs_getch();
    	temp3=UDR;
    	rs_getch();
    	temp4=UDR;
    	rs_getch();
    	temp5=UDR;
    	rs_getch();
    	temp6=UDR;
    	cbi(DDRB, PB0); 			//sygnał XCK jako wyjście
    	wyswietl();
    }
    
    
    
    // || *******************************************
    // || **---- PODPROGRAM OBSŁUGI PRZERWANIA ----**
    // || **------ GDY TRANSMISJA ZAKOŃCZONA ------**
    // \/ *******************************************
    
    ISR(USART_TXC_vect)				//przerwanie gdy transmisja zakończona
    {
    	UCSRB&=~(1<<TXCIE);			//wyłaczenie przerwania gdy transmisja zakończona
    	sbi(DDRB, PB0);				//sygnał XCK jako wejście
    	UCSRB|=(1<<RXCIE);			//włączenie przerwania gdy odbiór zakończony
    }
    
    
    
    int main()
    {
    	DDRB=0xFE;					//11 11 11 10 -> PB0 - XCK jako wyjście
    	PORTB=0x00;					//00 00 00 00 -> stan niski na porcie B
    
    	DDRC=0x00;					//00 00 00 00
    	PORTC=0x00;					//00 00 00 00
    
    	DDRD=0x00;					//00 00 00 00 -> port D jako wyjście
    	PORTD=0x8C;					//10 00 11 00 -> klawisze na porcie D w stan wysoki
    
    	lcd_init();					//inicjalizacja LCD
    	lcd_cls(); 					//czyszczenie LCD
    
    	init_AC();					//inicjalizacja A/C
    	rs_init(1200);				//inicjalizacja RS'a
    	
    
    	//USTAWIENIA TIMERA 2
    	//tryb pracy - normalny (zlicza w górę do MAX)
    	//preskaler /1024
    	TCCR2=(1<<CS22)|(1<<CS21)|(1<<CS20);
    	TIMSK=(1<<TOIE2);			//dostępne przerwanie od przepełnienia
    
    	sei();						//dostepne wszystkie globalne przerwania
    while(1)
    	{
    		if(bit_is_clear(PIND, PD7))		//klawisz 3
    		{
    			if(tryb==0)	
    			{
    				tryb++;
    				if(tryb)
    				{
    					TIMSK&=~(1<<TOIE2);	//zablokowane przerwanie od przepełnienia T2
    					TCCR2&=~((1<<CS22) | (1<<CS21) | (1<<CS20));	//zatrzymanie T2
    					
    					rs_putch(temp);
    					//odblokowanie przerwania zakończenia transmisji
    					UCSRB|=(1<<TXCIE);
    				}
    			}
    			else	tryb=0;
    		
    			wyswietl();
    
    			while(bit_is_clear(PIND, PD7));
    		}
    	}
    	return 0;
    }
    


    Temperatura mierzona jest w przerwaniu od przepełnienia timera 2. Po naciśnięciu klawisza timer jest zatrzymywany, a więc wynik już się nie zmienia. Co jeszcze mógłbym mieć źle? Nie rozumie tego co się dzieje ;/
  • REKLAMA
  • #8 5316510
    Krzysiek_k1984
    Poziom 13  
    Rzeczywiście :) WIELKIE DZIĘKI ZA POMOC :D :D :D Teraz działa prawidłowo ;)
  • #9 5320072
    Krzysiek_k1984
    Poziom 13  
    Niestety znowu mam problem. Zmieniłem źródło taktowania AT90CAN128 na
    EXT. CLOCK (CKSEL = 0000 SUT=01) i niestety komunikacja pomiędzy uP nie działa poprawnie. Pojawiają się jakieś przypadkowe liczby. Sygnał taktujący, który podawany jest na wejście to 57 600Hz. Szybkość pracy ustawiłem dla AT90 na rs0_init(1200); , a dla ATmegi rs_init(512); Próbowałem też z innymi prędkościami, ale nigdy poprawne dane nie dotarły. Co jeszcze może być źle?

    Dodano po 1 [minuty]:

    Aha Atmega16 taktowany jest tak jak wcześniej 3686400Hz
  • REKLAMA
  • #10 5320174
    Balu
    Poziom 38  
    Cytat:

    Sygnał taktujący, który podawany jest na wejście to 57 600Hz.

    Tzn? Na jakie wejście? mówisz o tym, że taki zegar podałeś? Czy że tak szybko chcesz komunikację mieć?
  • #11 5320210
    Krzysiek_k1984
    Poziom 13  
    Sygnał taktujący podawany jest na pin XTAL1 AT90CAN128. Generowany jest przez ATmega16 (TIMER1 wyjście OC1A) więc mogę go sobie zmienić. Myślałem że to przez ten sygnał komunikacja nie działa dlatego jest taka mała częstotliwość.

    Dodano po 1 [godziny] 20 [minuty]:

    Wróciłem do wcześniejszych ustawień:

    AT90CAN128: taktowany z wewnętrznego kwarcu 8MHz, BAUD = 600
    ATmega16: taktowana 3,686400MHz, BAUD = 2400

    Komunikacja działa.

    Po zmianie
    AT90CAN128: taktowany sygnałem o cz. 1,843200, BAUD = 600
    ATmega16: taktowana 3,686400MHz, BAUD = 600

    Komunikacja nie działa:/
    Nie zależy mi na szybkości, gdyż mam do przesłania tylko 4 bajty, ale AT90 musi być taktowany z wyjścia OC1A timera 1 ATmegi.

    Dodano po 10 [minuty]:

    Hehehe ;) Nie mam pytań. A wszystko moja wina. Zapomniałem ustawić sobie PD5 w Atmega jako wyjście.
  • #12 5322456
    Krzysiek_k1984
    Poziom 13  
    Aha i jeszcze taka mała rada na przyszłość. W programie miałem ustawione, że ten uP który nadaje, sygnał XCK bierze z drugiego uP. Najlepiej sygnał taktujący ustawić na sztywno z mikroprocesora, który ma niższy kwarc. Nie zaobserwowałem wtedy błędów w transmisji ;)
REKLAMA