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 winavr; małe opóźnienie w programie (uart)

puntigamer 07 Wrz 2009 01:27 3482 33
REKLAMA
  • #1 6989418
    puntigamer
    Poziom 13  
    Hej
    Przesyłam do atmegi8 za każdym razem 3bajty informacji. Prędkość układu to 38400. Atmega ma kwarc 16MHz. Powiedzcie mi, czy dobrze obliczyłem, że przesył 1 bajtu trwa około 208qs ??
    Mam następujący problem. Wysyłam tych 3bajtowych ciągów dosyć dużo i do tej pory między odbieraniem bajtów w kodzie pisałem
    . Było dobrze dopóki nie zwiększyłem liczby informacji przesyłanych do qC. Chciałbym wstawić mniejsze opóźnienie między odbiorem bajtów, ale takie aby następny bajt zdążył dotrzeć. Jak to zrobić?


    Mam też pytanie o przerwania.
    Mam przerwania od licznika 16bitowego oraz 8 bitowego (programowy pwm).
    Teraz uart nie działa na przerwaniach i jest dobrze. Mam nieskończoną pętle w głównym programie Jak myślicie czy byłyby problemy jeśli włączyłbym przerwania od uartu i odbiór bajtów oprogramował w tych przerwaniach? Nie spowoduje to problemów w funkcjonowaniu programowego pwm?

    Pozdrawiam
  • REKLAMA
  • #3 6989668
    sepako
    Poziom 14  
    Jeśli chodzi o czas przesyłu jednego bajtu przy prędkości 38400 bit/sek to wyniesie on ok 260us
    10/38400 (zakładając 1 bit startu i 1 bit stopu) dla zegara 16 MHz błąd wynosi 0.2% wiec
    ten czas niewiele się zmieni. Nie wiem na jaką odległość przesyłane są te dane ale można sie pokusić o znaczne zwiększenie prędkości. A co do przerwania od RX.uart to warto z niego skorzystać i nie powinno być problemu z PWM.
  • #4 6989753
    GrEG0
    Poziom 14  
    Mozesz smialo robic odbior uart na przerwaniach. Ja tez wykorzystuje programowy PWM , do tego kilka innych przerwan i wszystko smiga jak ma.
  • #5 6989842
    GienekS
    Poziom 32  
    puntigamer napisał:

    Mam też pytanie o przerwania.
    Mam przerwania od licznika 16bitowego oraz 8 bitowego (programowy pwm).
    Teraz uart nie działa na przerwaniach i jest dobrze. Mam nieskończoną pętle w głównym programie Jak myślicie czy byłyby problemy jeśli włączyłbym przerwania od uartu i odbiór bajtów oprogramował w tych przerwaniach? Nie spowoduje to problemów w funkcjonowaniu programowego pwm?

    Pozdrawiam

    Z programowym PWM jeżeli są włączone przerwania to na pewno Ci to pędzie pływać. A dlaczego nie wykorzystasz istniejących sprzętowych PWM ? Nie było by tego problemu.
  • REKLAMA
  • #6 6990006
    puntigamer
    Poziom 13  
    Freddie, ok wiem, ze to zależy od czasu działania przerwania uartu. Przeciez z tego co napisałem łatwo wywnioskować, że przerwanie od uartu jesli nastąpi miedzy przerwaniami od pwm'a to wymaga szybkosci takiej aby zakończyło się przed następnym wywołaniem przerwania od timera. ale opoznienie miedzy bajtami musze zrobić jakoś inaczej. Pomożecie? a Co jeśli przerwanie od uartu nastąpi 0,3 ms wcześniej niż następujące przerwanie pwm? zostanie wstrzymane, serwo dostanie troszkę później pozycje (żaden problem, bo może je dostawać między około 18 a 22ms). a jako, że zeruję liczniki po pętli to nie powinno się rozjeżdżać prawda?

    sepako - faktycznie zapomniałem o dodatkowych bitach kontrolnych w obliczeniach :) dzięki. co do zwiększenia szybkości, to spróbuje. zatrzymalem sie na tej, bo przy testowaniu w hyper terminalu nie moglem wybrać odpowiedniejszej wiekszej dającej taki mały błąd. muszę skorzystać z innej aplikacji do testowania chyba. kabel ma 1 -1,5 m. Na ten czas wg mnie sam przesył danych i ich przetworzenie (jako całość) było bezbłędne. A teraz chyba są problemy w aplikacji po przesłaniu poprawnego bajtu synchro następne dwa są zakłócane Wywołaniem OnTimer od Timera.: wątek tutaj. Program PC

    GienekS - Sprzętowy PWM na atmedze8 ma jedynie dwa kanały do porównywania OCR (1A i 1B) więc mogę obsłużyć jedynie dwa serwomechanizmy, bo o nich tutaj mowa.
  • #7 6990040
    _Robak_
    Poziom 33  
    Ja w sterowniku do serwomechanizmow mialem dosc spory przesyl danych po uarcie i zaden kanal z 24 nie wariowal :) Wszystkie serwa dzialaly ok, jedyny problem jaki bym widzial to rozjechanie sie licznika ktory odmierza 20ms (jesli takowy w ogole masz ;) ). Da sie to bardzo latwo wyregulowac akurat ;) Po prostu na poczatku przerwania ustawiasz ze TCNTn=ilosc wlasnie zliczonych cykli-ilosc cykli ktore by licznik zdazyl zliczyc bez przerwan z uarta.
  • #8 6990059
    puntigamer
    Poziom 13  
    Jeszcze pytanie o przerwanie uartu. Jest ono generowane jak bajt bedzie w buforze. Czy odbiór następnych 2 bajtów mogę zrobić w tymże przerwaniu? (stąd muszę zrobić pętlę opóźniającą ). te 3 bajty potem są jednością i je odkodowuje, więc musze zawsze miec ich 3.

    Robak
    Ja mam dokładnie tak:
    Licznik 8 bitówy odmierza czasy 2,5ms (nie może odmierzać 20ms bo jest za płytki:) w tym przerwaniu cyklicznie ustawiam wartosc OCR1A okreslonego serwa (8x2,5), podnoszę pin w stan wysoki i uruchamiam licznik 16 bitowy. gdy zliczy sie okreslona ilosc (sygnal dal serwa) wywoluje sie przerwanie od licznika16bit i zmieniam stan pinu na niski.)
    Czyli faktycznie licznik 8bit może się rozjeżdżać (przy uarcie na przerwaniach, a na razie tego nie zaimplementowalem)
  • #10 6990103
    puntigamer
    Poziom 13  
    jeśli w przerwaniu odbieram tylko 1 bajt to mogą być duże problemy.
    Np odbiorę poprawnie bajt synchro w 1 przerwaniu. W 2 będę myslał, że teraz przyleci bajt 2 z np pozycją, a potem bajt 3 z nr serwa.
    A qC przy odbieraniu zachowa się tak :
    odbierze 3 bajty do bufora, okaże sie , że 3cim jjest bajt synchro (jakis tam błąd 0,2%...) odbiorę ten 3ci bajt jako , że czeka w kolejce i będę myslał tak jak wyżej napisałem. A przecież jeśli bufor będzie przepełniony to zacznie gubić następne bajty i wcale nie muszę otrzymać bajtu nr 2 jako następnego.
    Nie wiem czy mnie rozumiecie : )


    Ponawiam prośbę:
    czy mógłby ktoś mi pomóc napisać wstawkę asm do odbierania danych przez rs? a tak naprawdę wstawkę, która pozwoli mi w zależności od moich ustawień (16mhz, szybkosc uart) dodać opóźnienie na poziomie minimalnie większym aniżeli szybkość przesyłania bajtu po rs.

    while(1)
      {  
       if ( (UCSRA & (1<<RXC))   ) //odbieranie z RS232
            { 
    		//syn = UDR;
    		
    			if ((egz.ba.bajt1 = UDR) == 0xFF)
    			{
    			
    			_delay_ms(1);    //tutaj mam kaszanę, za długie oczekiwanie!!!
    			egz.ba.bajt2 = UDR;
    
    			_delay_ms(1);
    			egz.ba.bajt3 = UDR;
    			
    			}	
    			//}
    		}


    Jeśli ta wstawka i zwiększenie szybkości rs nie pomoże, wezmę się za uart na przerwaniach
  • #11 6990162
    _Robak_
    Poziom 33  
    zawsze masz jeszcze bardziej precyzyjne _delay_us()
  • #12 6990176
    Balu
    Poziom 38  
    To zmień delay_ms na us:) I nie marudź A jak nie to zrób jak bozia kazała, odbieranie wszystkiego w przerwaniu z parsowaniem w ramki a w petli głównej sprawdzaj tylko flage jakąś czy jest nowa ramka jak tak, odczyt i wykonanie.
  • #13 6990326
    puntigamer
    Poziom 13  
    _delay_us() ...
    The maximal possible delay is 768 us / F_CPU in MHz.
    czyli, że przy 16mhz mogę maksymalnie dostać opóźnienie 48us ? :)

    Balu
    napisałeś "ramki" czyli w moim przypadku 3 bajtów? :)
    no bo jesli można w 1 przerwaniu pobrać całe 3 bajty to przestawie sie na przerwania:)

    cos takiego?
    przerwanieUart
    {
    if (bajt 1(udr) == synchro)
         {
    pobierz następne 2 bajty bo na pewno one dojdą
    flaga true  //o poprawnych danych;
         }
    else
    {flaga false
    }
    }
    
    petla główna:
    while(1)
      {
    if (flaga)  // jest nowa ramka
    {
    wyłuskanie info z tych 2 bajtów i zapis do tablicy
    }
    
    }


    tylko, znowu, czy jesli w trakcie "wyłuskiwania" w pętli głównej nastąpi przerwanie od uartu nie będzie kłopotu z nadpisaniem wartości? przerwani nie moge wylaczyc bo przecie liczniki...

    a jeśli mozna tylko 1 bajt odebrać w przerwaniu to nie wiem jak to zsynchronizować...
  • #14 6990345
    Freddie Chopin
    Specjalista - Mikrokontrolery
    puntigamer napisał:
    _delay_us() ...
    The maximal possible delay is 768 us / F_CPU in MHz.
    czyli, że przy 16mhz mogę maksymalnie dostać opóźnienie 48us ? :)

    Czy ktoś kiedyś przeczytał CAŁY ten akapit, czy zawsze zakłada się, że tylko pierwsze zdanie ma sens, a reszta jest zbędna?

    4\/3!!
  • REKLAMA
  • #15 6990377
    _Robak_
    Poziom 33  
    Ale z moich obserwacji wynika ze powyzej tej wartosci odliczanie jest na prawde niedlokladne ;)
  • #17 6990419
    Balu
    Poziom 38  
    puntigamer czytaj co się pisze, jedno przerwanie - jeden byte...tak, da się odbierasz ustawiając Sobie wew. flagi w przerwaniu np. jak są 3 byte parsujesz(czyli po 3 wywołaniach przerwania!) i ustawiasz flage ramka kompletna. wtedy glowny program cos robi
  • REKLAMA
  • #18 6990483
    _Robak_
    Poziom 33  
    Freddie Chopin napisał:
    Tak czy siak - jaki problem napisac funkcję:

    
    void delay(int x)
    {
    while(x--)
    delay_us(1);
    }
    


    ?

    4\/3!!


    Zakladam ze kolega znajac to "ograniczenie" poradzilby sobie z tym ;)
    W kazdym razie wracajac do tematu, zakladajac ze ci sie nic nie zgubi po drodze to pomysl kolego Balu jest chyba idealnym rozwiazaniem Twojego problemu ;) Mozesz tez np wysylac jako 4ty bajt sume kontrolna zeby byc pewnym ze odebrales wszystko co trzeba
  • #19 6990502
    puntigamer
    Poziom 13  
    Cytat:
    The macro F_CPU is supposed to be defined to a
    constant defining the CPU clock frequency (in Hertz).

    The maximal possible delay is 768 us / F_CPU in MHz.

    If the user requests a delay greater than the maximal possible one,
    _delay_us() will automatically call _delay_ms() instead. The user
    will not be informed about this case.


    Nie bede polemizował w to czy funkcja napisana jest poprawnie bo na pewno.
    Powiedzcie mi tylko(jesli F_CPU podaje sie w hertz'ach -#define... ) kiedy funkcja przyjmnie wartosc tmp < 1? Sensowene liczby wychodzą tylko przy F_CPU podanych w MHz . Cytalem wszystko ale nie doczytałem sie aby zdefiniowac fcpu jako np 16.000;

    poza tym na przykład (us):
    (16/ 998) * 54 = 0,87 <1 -> a napisane, że dla 16MHz max delay to 48 a jesli chcemy wiekszy to wykonane zostanie :
    else if (__tmp > 255)
    	{
    		_delay_ms(__us / 1000.0);
    		return;
    	}

    tyle, że ten warunek zostanie spełniony dopiero przy __us = około 62.

    Gdzie zle licze, albo czego nie biorę pod uwagę.
    Bądźcie cierpliwi : )

    No właśnie. wiem, żę mogę napisać pętlę i nie będzie problemu, ale chciałbym zrozumieć coś przed uzyciem a nie omijać problemy.

    Dodano po 10 [minuty]:

    Freddie wczesniej napisał mi 1 przerwanie 1 bajt. Umiem czytać, chciałem sie upwenic : )

    Wiec sprawa pętli rozwiązana (w ogole wyleciała mi z głowy funkcja delay us.. )
    Sprawe problemu dot wartosci delayus zostawiam sobie na przyszlosc...

    Jeszcze co do tego
    Cytat:
    odbierasz ustawiając Sobie wew. flagi w przerwaniu np. jak są 3 byte parsujesz(czyli po 3 wywołaniach przerwania!) i ustawiasz flage ramka kompletna.


    w woli wyrozumiałości możesz mi to jaśniej wytłumaczyć? widze ciemność : ) a pewnie to prosta sprawa
  • #20 6990577
    _Robak_
    Poziom 33  
    Jesli dobrze zrozumialem ;) W przerwaniu poza odbiorem danej inkrementujesz jakas zmienna. W programiw glownym jesli bedzie ona wynosila 3 to wiesz ze cala ramka jest odebrana i ozesz ja zczytac z bufora, nasteobnie zerujesz zmienna.
  • #21 6990622
    Balu
    Poziom 38  
    Dokładnie jak napisał robak:)
    A zgubienie jakiegoś bajtu i rozsynchronizowanie a co za tym idzie resynch zapewniasz Sobie przez nagłówek ramki czyli dla Ciebie własnie bajt synchronizacji i ew. opóźnienie (jak np. w ciągu 100ms nie przyjdzie nowy bajt, to zerujesz licznik_odebranych - jeśli nie był równy zero -> zgubiony kawałek ramki, jeśli był to i tak wszystko jedno:)
  • #22 6990725
    puntigamer
    Poziom 13  
    To pod warunkiem, że zawsze będzie po kolei tak:
    bajt1(synchro), bajt2, bajt3;

    a jeśli zacznie się tak: bajt2, bajt3, bajt1, bajt2, bajt3, bajt1 itd.. ?

    Jestem raczej pewny, że układ wyśle po kolei 1,2,3, ale kto wie czy w buforze na ślepo mam wierzyć, że pierwsza przybyta ramka to synchro? przecież w takim razie ten bajt byłby mi nie potrzebny. Muszę brać pod uwagę zgubienie lub błąd bajtu. Musze dać sprawdzanie, czy aby ta odebrana ramka to jest synchro i dopiero inkrementować jo ?

    Sprawdzanie ramki synchro w przerwaniu, czy w programie głównym? Bo jesli w prog gł to może się zdarzyć, że przy takim układzie bajtów wysłanych po kolei (2 i++,3 i++,1 i++) nigdy nie bedzie prawdą, zę bajt 2 to synchro.

    Juz mysle by zrobić to tak.


    ISR(UART)
    {
    
      switch (flaga)
    
      {
      case 0:     
    			   
       	if (bajt1 = UDR) ==0xFF) flaga++;	
       break;
    
      case 1:     
    	bajt2 = UDR;
    	flaga++
       break;
    
      case 2:     
    	bajt3 = UDR;
    	flaga++
       break;
       }
    
    }
    
    
    main()
    
    while(1)
    {
    
    if (flaga==3)
    {
    //następuja wszystkie operacje dotyczące danych zapisanych w zmiennych bajt1-3;
    flaga=0;   //ponowne umozliwienie pobierania bajtow w przerwaniu
    }


    Będzie? Coś byście do tego jeszcze dodali?
  • #23 6990748
    Freddie Chopin
    Specjalista - Mikrokontrolery
    "volatile" do deklaracji flagi, profilaktycznie pisze od razu, zanim powstanie kolejny temat o tym.

    Pozatym - widzę mistrzostwo pisania optymalnego kodu na elektrodzie.

    char bajty[3];

    bajty[flaga] = UDR;
    if (flaga == 0)
    {... // sprawdzenie }
    flaga++;

    4\/3!!
  • #25 6990926
    puntigamer
    Poziom 13  
    Nie wiem, nie jestem specjalistą, ale trudno mi się zgodzić z tym, że Twój kod przerwania jest bardziej optymalny (jeśli już na optymalność wkraczamy, a w przerwaniach ona jest priorytetowa).

    1. Instrukcja switch działa trochę szybciej od if. Chociaż nie wiem czy instrukcja switch sprawdza warunek tyle razy ile jest case'ów (oczywiście do napotkania tego odpowiedniego, czy od razu prowadzi do tego odpowiedniego).
    2. I tak przecież instrukcja if u Ciebie wykonuje sprawdzenie warunku (flaga == 0) za każdym wywołaniem przerwania.
    3. No i chyba najważniejsze. Jeśli po zresetowaniu flagi w main, nastąpi pierwsze przerwanie oraz pierwszy w kolejce bajt nie będzie bajtem synchro, to:
    przerwanie zapisze go pod bajt[0], sprawdzi, czy flaga ==0, następnie przejdzie do wykonywania instrukcji sprawdzania (tutaj idąc uproszczeniem z mojego kodu powinno być wstawione "if (bajty[flaga]==0xFF) i cos jeszcze". jeśli to się nie zgadza powinna nastąpić reakcja (a na pewno nie inkrementowanie, które jest poza instrukcją if i wykonywane za każdym przerwaniem.

    Dodano po 5 [minuty]:

    Hehehe klocek;P no tak, ale nigdzie nie zainkrementuje wiecej flagi powyżej 3 : )
    Ostatni case (jeśli flaga ==2 to udr oraz flaga++ )

    Ważne jest to, aby po flaga=0 przerwanie pobierało wartości z bufora i inkrementowało flagę jedynie jeśli będzie to synchro. Jeśli nie wysyłałbym nigdy bajtu synchro do uC to flaga nigdy nie będzie miała wartości 1 co za tym idzie nigdy nie będzie wykonywany zaden pozniejszy case ani instrukcje z main'a.

    Jeśli wyślę mu same bajty synchro, lub jakkolwiek inaczej niż "synchro, dana, dana...", to walidację tych dwóch bajtów następnych muszę wykonać w main'ie.

    Dodano po 1 [minuty]:

    ale dam pustego defaulta ; p : D

    Dodano po 1 [minuty]:

    zartowalem. defaulta co by flage ustawial na 0 ; )
  • #27 6991160
    Freddie Chopin
    Specjalista - Mikrokontrolery
    puntigamer napisał:
    Nie wiem, nie jestem specjalistą, ale trudno mi się zgodzić z tym, że Twój kod przerwania jest bardziej optymalny (jeśli już na optymalność wkraczamy, a w przerwaniach ona jest priorytetowa).

    Osiągnięcie czegoś trudnego to wielki sukces, więc warto się starać.

    Cytat:
    1. Instrukcja switch działa trochę szybciej od if. Chociaż nie wiem czy instrukcja switch sprawdza warunek tyle razy ile jest case'ów (oczywiście do napotkania tego odpowiedniego, czy od razu prowadzi do tego odpowiedniego).

    Bzdura, jedna i druga jest realizowana w procesorze tak samo - przez porównanie i skok warunkowy. Switch musi sprawdzić każdy warunek, aż do złapania tego odpowiedniego.

    Cytat:
    2. I tak przecież instrukcja if u Ciebie wykonuje sprawdzenie warunku (flaga == 0) za każdym wywołaniem przerwania.

    To straszne - jedno porównanie.
    U ciebie zaś przy pierwszym przerwaniu jest jedno, przy drugim dwa, przy trzecim trzy - średnio 2, czyli 2x tyle co u mnie jeśli chcesz się tak licytować.

    Cytat:
    3. No i chyba najważniejsze. Jeśli po zresetowaniu flagi w main, nastąpi pierwsze przerwanie oraz pierwszy w kolejce bajt nie będzie bajtem synchro, to:
    przerwanie zapisze go pod bajt[0], sprawdzi, czy flaga ==0, następnie przejdzie do wykonywania instrukcji sprawdzania (tutaj idąc uproszczeniem z mojego kodu powinno być wstawione "if (bajty[flaga]==0xFF) i cos jeszcze". jeśli to się nie zgadza powinna nastąpić reakcja (a na pewno nie inkrementowanie, które jest poza instrukcją if i wykonywane za każdym przerwaniem.

    No kolejna tragedia... Błagam... Nigdzie nie pisałem że to jest idealny i najoptymalniejszy kod dla ciebie i masz sobie go wkleić i będzie super - pokazałem ci tylko, że wykonujesz 3 instrukcje, które są IDENTYCZNE, niemniej jednak będą one zajmowały 3x tyle kodu (+/-) co jedna, robiąca to samo z tablicą.

    Pozatym - ty piszesz ten program, czy teoretyzujesz na temat tego "co będzie jak źle dane wyślę"? Jak ci tak zależy, to jest milion sposobów sprawdzenia tego, akurat rozwiązanie które miałeś na początku (czyli pętle opóźniające) jest najgłupszym jakie jest tylko możliwe i ma dokładnie tą samą wadę którą "rzekomo mają" przerwania...

    Napisałeś już z 8 postów na temat sprawy, która jest skrajnie prosta...

    4\/3!!
  • #28 6992120
    puntigamer
    Poziom 13  
    ISR(USART_RXC_vect)          //przerwanie usart przy odebraniu znaku
    {
    
      switch (flaga)
    
      {
      case 0:     
    			   
       	if ((rxbuff[0] = UDR) ==50 ) flaga++;	
       break;
    
      case 1:     
    	rxbuff[1] = UDR;
    	flaga++;
       break;
    
      case 2:     
    	rxbuff[2] = UDR;
    	flaga++;
       break;
       
      default:
        smiec = UDR;
        flaga=0;
       break;
    
    
       }
    }

    //   Przerwania   
       TIMSK=_BV(OCIE1A)|_BV(OCIE1B)|_BV(OCIE2);
       TIFR =_BV(OCF1A)|_BV(OCF1A)|_BV(OCF2);
    
    //   Ustawienie UART
       UBRRL=25;
       UCSRC|=(_BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0));
       UCSRB= (1<<RXEN)|(1<<TXEN); 
       UCSRB |= (1 << RXCIE);   //RXCIE przerwanie od uartu
    sei();

    while(1)
    	{      //sprawdzic jeszcze zakres wartosci zmiennych nr_serwa i pozycja, czy na pewno mieszcza sie w zakresie!!!
       
    		if (flaga==3)
    		{ 
    			flaga=0;
    ...... inne instrukcje ustawiajace serwa
    }}



    czy cos jest proste to rzecz wzgledna.
    chyba w ogole przerwanie nie nastepuje, albo cos innego jest nie tak. mozecie spojrzec?
  • #30 6992648
    puntigamer
    Poziom 13  
    #include <avr/io.h>
    //#define F_CPU 16000000
    #include <avr/interrupt.h> 
    #include <util/delay.h>
    int volatile  nr=0;
    int volatile wartosc[7] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40};     	//tab numerów pinów
    int volatile polozenie[7] = {350,375,375,375,375,375,375}; 				//tablica 7 wartosci bo kazde serwo podłączone jest oddzielnie
    //int i ;																	//jesli chcialbys podlaczyc serwo8 to musis z zmienic tutaj na 8, w przerwaniu od licznika2 
    												//ustawic if (nr==8), oraz zmienic liczbe do ktorej odlicza licznik2 na OCR2=0x9C; czyli 2,5ms * 8 = 20ms
    int volatile flaga=0;
    char smiec;
    int rxbuff[3] = {0,0,0};
    
    
    // tutaj jeszcze napisane sa przerwania od liczników
    
    
    
    int main()
    {
    
    
    
    struct slowo
    	{
    		unsigned int synchro	: 8;
    		unsigned int nr_serwa	: 3;
    		unsigned int 			: 3;
    		//unsigned int asd	: 3;
    		unsigned int pozycja	: 10;
    		
    		
    		
    	} ;
    
    	struct dwa_bajty
    	{
    		unsigned int bajt1	: 8;
    		unsigned int bajt2	: 8;
    		unsigned int bajt3	: 8;
    	} ;
    
    	union unia
    	{
    		//unsigned long cale_slowo;
    		slowo sl;
    		dwa_bajty ba;
    	} egz;
    
    
    
    
    
    
    //tutaj jest ustawianie licznikow
    
    
    //   Przerwania   od licznikow
       TIMSK=_BV(OCIE1A)|_BV(OCIE1B)|_BV(OCIE2);
       TIFR =_BV(OCF1A)|_BV(OCF1A)|_BV(OCF2);
        
       DDRB=0xFF;
    
    
    //   Ustawienie UART
       UBRRL=25;
       UCSRC|=(_BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0));
       UCSRB= (1<<RXEN)|(1<<TXEN); 
       UCSRB |= (1 << RXCIE);   //RXCIE przerwanie od uartu
    sei();
    
    
    _delay_ms(2);
     
    
    while(1)
    	{     
       
    		if (flaga==3)
    		{ 
    			flaga=0;
    						
    			
    			//if ( (rxbuff[0] == 50) && (rxbuff[1] != 0xFF) && (rxbuff[2] != 0xFF) )
    			//{
    			
    			egz.ba.bajt1 = rxbuff[0];
    			egz.ba.bajt2 = rxbuff[1];
    			egz.ba.bajt3 = rxbuff[2];
    	   
    				if (egz.sl.nr_serwa == 1) 					//1 i 6 (liczac od 0)         (czyli drugi i ostatni(7) pin) to serwa wspołpracujące   UWAGA!!!!!!!!
    					{                   					//jeśli nr_serwa = 1 to podaj także na serwo 6   liczymy od 0
    						
    						polozenie[egz.sl.nr_serwa] = polozenie[6] = egz.sl.pozycja;
    					}
    				else
    					{
    						polozenie[egz.sl.nr_serwa] = egz.sl.pozycja;
    				
    					}
    			//}
    			
    		//flaga=0;
    	   
    		}
       
    		
    	}
    	
    	
       
    return 0;
    }
    
    


    Przerwań od liczników nie mam tu wyszczegółowionych ale zapewniam, że po
    polozenie[egz.sl.nr_serwa] = egz.sl.pozycja;
    liczniki, czyli progrmowy pwm dziala poprawnie (sprawdzone, bo wszystko działa na uarcie bez przerwania...... )

    juz zrobiłem rxbuff[3]... wczesniej od razu w przerwaniu było przekazanie do struktuwy.... w ogole zadnych reakcji na wysyłanie bajtów.
REKLAMA