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]ATmega 128 dzialania na tablicach

jerraz 14 Maj 2010 09:22 2088 18
REKLAMA
  • #1 8073692
    jerraz
    Poziom 10  
    Witam serdecznie,
    pisze program na aTmega 128, mam już napisaną zdecydowanie wieksza czesc kodu ale gubie sie przy operacjach na tablicach.
    Otoz, dostaje pomiary z 5 czujnikow. Kazda paczka danych od jednego czujnika sklada sie z 2 bajtow- starszego oraz mlodszego. Po wyborze odpowiedneigo czujnika, z ktorego chce czytac dane nastepuje ich zczytanie i zapisanie do tablicy. Chce zrobic cos takiego,zeby kazdy czujnik cztany byl przykladowo 5 razy. Starszy bajt wpisywany do pierwszej kolumny tablicy, a mlodszy do drugiej kolumny tablicy (wszystko w pierwszym wierszu). Nastepnie Staram sie zeby dalej w tej samej petli dokonywana byla suma, sumuje starsze bajty, sumuje mlodsze bajty, licze srednia ze starszego bajtu, mlodszego i chce wysylac po uarcie. Wszystko odbywa sie w przerwaniu. Niestety robie cos zle, nie do konca wiedzac gdzie jest moj blad.

    Prosze o podpowiedz/pomoc. Z gory dzieki za sugestie/podpowiedzi.

    Moj kod, wklejam tylko to co uznalem za stosowne.

    
    #define rozmiar_wierszy 4
    #define rozmiar_kolumn 1
    
    // definicje zmiennych użytych w programie  
    
    volatile char wynik_msb = 0;
    volatile char wynik_lsb = 0;
    unsigned int preskaler;
    int k;
    int raw_data0_tab[rozmiar_wierszy][rozmiar_kolumn];
    int raw_data1_tab[rozmiar_wierszy][rozmiar_kolumn];
    int raw_data2_tab[rozmiar_wierszy][rozmiar_kolumn];
    int raw_data3_tab[rozmiar_wierszy][rozmiar_kolumn];
    int raw_data4_tab[rozmiar_wierszy][rozmiar_kolumn];
    int wyniki_sred_msb;
    int wyniki_sred_lsb;
    //volatile unsigned char flaga;
    volatile char flaga; 
    
    
    SIGNAL (SIG_OUTPUT_COMPARE1A)				//obsługa przerwania od T1
    {
    
    int suma_lsb = 0;
    int suma_msb = 0;
    int wyniki_sred_msb = 0; 
    int wyniki_sred_lsb = 0;
    
    	for(k=0; k<=4; ++k)					// wybieranie który czujnik ma zostać obsłużony
    	{
    
    		if(k==0)
    		{
    			for (int p=0; p<=rozmiar_wierszy; p++)
    			{
    			czujnik0;
    
    			off_SS;
    
    			spiTransmisja(0xFF);				// czytanie pierwszego bajtu danych
    			wynik_msb=SPDR;
    			//raw_data0_tab[p][0]=wynik_msb;		// wpisanie wynik_msb do tablicy
    
    			spiTransmisja(0xFF);				// czytanie drugiego bajtu danych
    			wynik_lsb=SPDR;
    			//raw_data0_tab[p][1]=wynik_lsb;		// wpisanie wynik_lsb do tablicy
    
    			set_SS;
    			suma_msb +=wynik_msb;
    			suma_lsb +=wynik_lsb;
    			//suma_msb += raw_data0_tab[p][0];	// suma elementow bajtu msb
    			//suma_lsb += raw_data0_tab[p][1];	// suma elementow bajtu lsb
    			}
    		
    		wyniki_sred_msb = suma_msb/rozmiar_wierszy;		// srednia 5 elementow bajtu msb
    		wyniki_sred_lsb = suma_lsb/rozmiar_wierszy;		// srednia 5 elementow bajtu lsb
    		flaga = 0;
    		PORTA &=~_BV(PA2);
    		}
    
    }
    }
    
    
  • REKLAMA
  • #2 8073796
    loocasm
    Poziom 15  
    Wyjeżdżasz z indeksowaniem tablic poza ich granice - jeśli tablica ma rozmiar 4 x 1 to znaczy, że możesz indeksować jej elementy od 0 do 3 w jednej płaszczyźnie i tylko 0 w drugiej. Rozmiar tablicy to ilość jej elementów, a że w C indeksowanie jest od 0 to możesz dojść z indeksem tylko do rozmiar-1.
  • REKLAMA
  • #4 8074192
    tadzik85
    Poziom 38  
    zamiast <= uzyj < w petli for

    Bez wielkiego kombinowania.
  • #5 8074269
    tmf
    VIP Zasłużony dla elektroda
    W dodatku żle uśredniasz. Oddzielnie dodajesz bajty starsze, a oddzielnie młodsze. A co jeśli wystąpi przepełnienie z młodszych? Druga rzecz - czy do tych tablic odwołujesz się poza przerwaniem? Jeśli tak to pojawia się analogiczna sytuacja z volatile i dodatkowo z zapewnieniem atomowości dostępu do danej typu integer. A trzecia rzecz - kosmetyczna - zamiast stosować tablicę i rozbijać elementy na starsze i młodsze połówki przez indeksowanie lepiej zastosować unię. To może przy okazji też polepszyć optymalizację - nie będzie konieczności mnożenia indeksów.
  • #6 8075343
    GSM
    Poziom 25  
    Witam,

    tadzik85 napisał:
    zamiast <= uzyj < w petli for

    Bez wielkiego kombinowania.


    przy użyciu < zamiast <= należy wywalić to odejmowanie jedynki od rozmiaru...

    Pozdrawiam,
    GSM
  • #7 8075403
    tadzik85
    Poziom 38  
    GSM napisał:
    Witam,

    tadzik85 napisał:
    zamiast <= uzyj < w petli for

    Bez wielkiego kombinowania.


    przy użyciu < zamiast <= należy wywalić to odejmowanie jedynki od rozmiaru...

    Pozdrawiam,
    GSM


    To odnosi się do oryginału a tam żadnego odejmowania jedynki nie ma
  • REKLAMA
  • #8 8078320
    jerraz
    Poziom 10  
    Do tmf, jak Ty to widzisz? Ja nigdy nie urzywalem unii, niebardzo wiem jak ona dziala. Mozesz wrzucic kod po porpawkach? Z gory dzieki.
  • #9 8078447
    tmf
    VIP Zasłużony dla elektroda
    Deklarujesz typ, który umożliwia wygodny dostęp do obu bajtów słowa:
    typedef union
    {
    struct
    {
    uint8_t Low;
    uint8_t High;
    }
    uint16_t data;
    } access;

    Teraz jak zadeklarujesz zmienną o typie access to dostęp do poszczególnych bajtów zamiast indeksu i tablicy wielowymiarowej uzyskujesz poprzez zmienna.Low i zmienna.High, sama tablica staje się jednowymiarową tablicą o typie access. Jednocześnie możesz prowadzić uśredniania i inne działania bezpośrednio na zmiennej, z pominięciem rozbicia na młodszy i starszy bajt.
    Co do unii, ogólnie wystarczy zapamiętać jedną rzecz - każde pole unii ma ten sam adres, czyli pola unii pokrywają się, co umożliwia traktowanie ich jako różnych typów - w tym wypadku jako uint16_t lub dwóch zmiennych o typie uint8_t.
  • #10 8097737
    jerraz
    Poziom 10  
    tmf napisał:
    Teraz jak zadeklarujesz zmienną o typie access to dostęp do poszczególnych bajtów zamiast indeksu i tablicy wielowymiarowej uzyskujesz poprzez zmienna.Low i zmienna.High, sama tablica staje się jednowymiarową tablicą o typie access. Jednocześnie możesz prowadzić uśredniania i inne działania bezpośrednio na zmiennej, z pominięciem rozbicia na młodszy i starszy bajt.


    Nie do końca chyba rozumiem całość przesłania. Musze operować na starszy i młodszy bo w takiej postaci muszę je wysyłać. Rozumiem ze teraz będę się odwoływał do tego za pomocą Low oraz High, ale jak dokonywać na tych zmiennych sumowania oraz uśredniania?
  • REKLAMA
  • #11 8097771
    tadzik85
    Poziom 38  
    Operacji arytmetycznych dokonujesz na access.data
    a wysyłasz access.Low i access.High.

    w pierwszym przypadku masz dostęp do liczby 16-bitowej w drugim do każdego bajtu osobno składającego się na tą zmienną
  • #13 8119917
    jerraz
    Poziom 10  
    Unia nie do końca rozwiązuje mojego problemu. Sprawa wygląda tak, że dostaje pomiary z 5 czujników. Jeżeli wybrany czujnik nacisku obciążę jakąś znaną i dużą masą przykładowo 350g, to pojawiają się "piki".
    [C]ATmega 128 dzialania na tablicach
    Liczenie średniej nic mi nie da, ponieważ wynik będzie obarczony błędem. Pomyślałem żeby zrobić to trochę inaczej. Stworzyć większą tablicę dla każdego czujnika (przykładowo 20 wierszy na 2 kolumny). Zbieram pomiar dla pierwszego czujnika, wypełniam nimi moją tablicę, następnie uporządkować od najmniejszego do największego (bądź odwrotnie), następnie odrzucić 5 najmniejszych, 5 największych a z tych 10,które zostaną wyliczyć średnią i dopiero wysłać po UART jako starszy i młodszy bajt. Jak tego dokonać na tablicach? Chyba że ma ktoś inny prostszy sposób. Wydaję mi się że najlepsza byłaby do tego tablica dynamiczna, tylko zastanawia mnie jedna kwestia. Jak dokonać czegoś takiego, że mam tablicę i segreguję je wierszami (wiersz to jest starszy i młodszy bajt) i są one "całością"? Z góry dzięki za jakąkolwiek pomoc/wskazówki/podpowiedzi.

    Pozdrawiam


    
    
    #define RDY	PB4
    #define TIMER_CLOCK 2
    
    
    //#include <avr/interrupt.h>						// dolaczenie standardowych bibliotek obslugi przerwan bez blokady (obsluguje signal.h)
    #include <avr/signal.h>						// dolaczenie standardowych bibliotek obslugi przerwan z blokada
    #include "cpuCnfg.h"							// konfiguracja procesora
    #include <inttypes.h>
    #define rozmiar_wierszy 6
    #define rozmiar_kolumn 2
    
    // definicje zmiennych użytych w programie  
    
    volatile char wynik_msb=0;
    volatile char wynik_lsb=0;
    unsigned int preskaler;
    int k;
    int raw_data0_tab[rozmiar_wierszy][rozmiar_kolumn];
    int raw_data1_tab[rozmiar_wierszy][rozmiar_kolumn];
    int raw_data2_tab[rozmiar_wierszy][rozmiar_kolumn];
    int raw_data3_tab[rozmiar_wierszy][rozmiar_kolumn];
    int raw_data4_tab[rozmiar_wierszy][rozmiar_kolumn];
    int wyniki_sred_msb;
    int wyniki_sred_lsb;
    unsigned char volatile flaga;
    
    // ustawienie timera który steruje przerwaniem w programie
    
    //----------ustawienie przerwania dla rozpoczecia pomiaru od timera-------------------------------------------
    void Start(void)					
    {
    	TIMSK |= _BV(OCIE1A); 						//zezwolenie na przerwanie
    }
    //----------wylaczenie przerwania pomiaru, koniec pomiaru od timera-------------------------------------------
    void Stop(void)
    {
    	TIMSK &= ~(_BV(OCIE1A)); 					// blokada przerwania
    }
    
    
    
    int main(void)
    {
    _delay_ms(10);								
    
    // konfiguracja portów uzywanych w programie 
    
    // kierunek SPI, porty ustawione jako wyjścia
    	DDRB |= _BV(PB0);		// SS	
    	DDRB |= _BV(PB1);		// SCK
    	DDRB |= _BV(PB3);		// MISO
    
    // kierunek portów sterowania dekoderami 74HC138, porty ustawiona jako wyjścia
    	DDRB |= _BV(PB5);		
    	DDRB |= _BV(PB6);
    	DDRB |= _BV(PB7);
    
    
    // ustawienie kierunku UARTA oraz przecisków 							
    	DDRD = 0xFC;								
    	DDRE = 0x02;								
    	PORTD = 0xFF;								
    	PORTE = 0x03;								
    
    // ustawienie diody podłączonej do portu PA0 i PA1	
    	DDRA |= _BV(PA0)|_BV(PA1);			 
    	PORTA |= _BV(PA0)|_BV(PA1) ;
    	
    
    
    // inicjalizacja SPI i UARTA
    	spiInit();									// wywolanie SPI
    	usartInit(MYUBRR);							// wywolanie USART0
    
                        		
    
    // ustawienie timera wykorzystywanego do przerwania 
    	TCCR1B = _BV(CS10) | _BV(CS11) | _BV(WGM12);// rejestr timera
    	preskaler = 2;
    	OCR1A = ((FOSC/2/preskaler/TIMER_CLOCK) - 1 );	// preskaler timera
    
    
    // zerowanie tablic 
    
    for (int e=0; e<=rozmiar_wierszy; e++ )
    	{
    for (int f=0;f<=rozmiar_kolumn; f++)
    		{
    raw_data0_tab[e][f] = 0;
    raw_data1_tab[e][f] = 0;
    raw_data2_tab[e][f] = 0;
    raw_data3_tab[e][f] = 0;
    raw_data4_tab[e][f] = 0;
    		}
    	}
    
    // zezwolenie na przerwania
    	sei();
    
    /***************************************************************************************************************
    * pomiar
    ***************************************************************************************************************/
    
    while(1)
    {
    
    	if(bit_is_clear(PIND, 4))          		// nacisniecie przycisku S1 rozpoczyna pomiar
    	{
    
    	Start();						
    	PORTA &=~_BV(PA0);						// włączenie diody led podpiętej pod port PA0							
    	}							
    
    	if(bit_is_clear(PIND, 5))          		// nacisniecie przycisku S2 kończy pomiar
    	{
    
    	Stop();
    	PORTA |=_BV(PA0);						// wyłączenie diody led podpiętej pod port PA0
    	}
    
    }
    } 
    
    SIGNAL (SIG_OUTPUT_COMPARE1A)				//obsługa przerwania od T1
    {
    
    PORTA &=~_BV(PA1);
    
    int suma_lsb = 0;
    int suma_msb = 0;
    int wyniki_sred_msb = 0; 
    int wyniki_sred_lsb = 0;
    
    	for(k=0; k<=4; ++k)					// wybieranie który czujnik ma zostać obsłużony
    	{
    
    		if(k==0)
    		{
    			for (int p=0; p < rozmiar_wierszy; p++)
    			{
    			czujnik0;
    
    			off_SS;
    
    			spiTransmisja(0xFF);				// czytanie pierwszego bajtu danych
    			wynik_msb=SPDR;
    			raw_data0_tab[p][0]=wynik_msb;		// wpisanie wynik_msb do tablicy
    
    			spiTransmisja(0xFF);				// czytanie drugiego bajtu danych
    			wynik_lsb=SPDR;
    			raw_data0_tab[p][1]=wynik_lsb;		// wpisanie wynik_lsb do tablicy
    
    			set_SS;
    
    			suma_msb += raw_data0_tab[p][0];	// suma elementow bajtu msb
    			suma_lsb += raw_data0_tab[p][1];	// suma elementow bajtu lsb
    			}
    			
    		wyniki_sred_msb = suma_msb/rozmiar_wierszy;		// srednia 5 elementow bajtu msb
    		wyniki_sred_lsb = suma_lsb/rozmiar_wierszy;		// srednia 5 elementow bajtu lsb
    		flaga = 0;
    		}
    
    
    		if(k==1)
    		{
    			for (int p=0; p < rozmiar_wierszy; p++)
    			{
    			czujnik1;
    
    			off_SS;
    
    			spiTransmisja(0xFF);				// czytanie pierwszego bajtu danych
    			wynik_msb=SPDR;
    			raw_data1_tab[p][0]=wynik_msb;		// wpisanie wynik_msb do tablicy
    
    			spiTransmisja(0xFF);				// czytanie drugiego bajtu danych
    			wynik_lsb=SPDR;
    			raw_data1_tab[p][1]=wynik_lsb;		// wpisanie wynik_lsb do tablicy
    
    			set_SS;
    
    			suma_msb += raw_data1_tab[p][0];	// suma elementow bajtu msb
    			suma_lsb += raw_data1_tab[p][1];	// suma elementow bajtu lsb
    			}
    
    		wyniki_sred_msb = suma_msb/rozmiar_wierszy;		// srednia elementow bajtu msb
    		wyniki_sred_lsb = suma_lsb/rozmiar_wierszy;		// srednia elementow bajtu lsb
    		flaga = 1;
    		}
    		
    
    
    		if(k==2)
    		{
    			for (int p=0; p < rozmiar_wierszy; p++)
    			{
    			czujnik2;
    
    			off_SS;
    
    			spiTransmisja(0xFF);				// czytanie pierwszego bajtu danych
    			wynik_msb=SPDR;
    			raw_data2_tab[p][0]=wynik_msb;		// wpisanie wynik_msb do tablicy
    
    			spiTransmisja(0xFF);				// czytanie drugiego bajtu danych
    			wynik_lsb=SPDR;
    			raw_data2_tab[p][1]=wynik_lsb;		// wpisanie wynik_lsb do tablicy
    
    			set_SS;
    
    			suma_msb += raw_data2_tab[p][0];	// suma elementow bajtu msb
    			suma_lsb += raw_data2_tab[p][1];	// suma elementow bajtu lsb
    			}
    		wyniki_sred_msb = suma_msb/rozmiar_wierszy;		// srednia elementow bajtu msb
    		wyniki_sred_lsb = suma_lsb/rozmiar_wierszy;		// srednia elementow bajtu lsb
    		flaga = 2;
    		}
    
    		if(k==3)
    		{
    			for (int p=0; p < rozmiar_wierszy; p++)
    			{
    			czujnik3;
    
    			off_SS;
    
    			spiTransmisja(0xFF);				// czytanie pierwszego bajtu danych
    			wynik_msb=SPDR;
    			raw_data3_tab[p][0]=wynik_msb;		// wpisanie wynik_msb do tablicy
    
    			spiTransmisja(0xFF);				// czytanie drugiego bajtu danych
    			wynik_lsb=SPDR;
    			raw_data3_tab[p][1]=wynik_lsb;		// wpisanie wynik_lsb do tablicy
    
    			set_SS;
    
    			suma_msb += raw_data3_tab[p][0];	// suma 5 elementow bajtu msb
    			suma_lsb += raw_data3_tab[p][1];	// suma 5 elementow bajtu lsb
    			}
    		wyniki_sred_msb = suma_msb/rozmiar_wierszy;		// srednia 5 elementow bajtu msb
    		wyniki_sred_lsb = suma_lsb/rozmiar_wierszy;		// srednia 5 elementow bajtu lsb
    		flaga = 3;
    		}
    
    		if(k==4)
    		{
    			for (int p=0; p < rozmiar_wierszy; p++)
    			{
    			czujnik4;
    
    			off_SS;
    
    			spiTransmisja(0xFF);				// czytanie pierwszego bajtu danych
    			wynik_msb=SPDR;
    			raw_data4_tab[p][0]=wynik_msb;		// wpisanie wynik_msb do tablicy
    
    			spiTransmisja(0xFF);				// czytanie drugiego bajtu danych
    			wynik_lsb=SPDR;
    			raw_data4_tab[p][1]=wynik_lsb;		// wpisanie wynik_lsb do tablicy
    
    			set_SS;
    
    			suma_msb += raw_data4_tab[p][0];	// suma 5 elementow bajtu msb
    			suma_lsb += raw_data4_tab[p][1];	// suma 5 elementow bajtu lsb
    			}
    		wyniki_sred_msb = suma_msb/rozmiar_wierszy;		// srednia 5 elementow bajtu msb
    		wyniki_sred_lsb = suma_lsb/rozmiar_wierszy;		// srednia 5 elementow bajtu lsb
    		flaga = 4;
    		}
    	
    		if (flaga==0||flaga==1||flaga==2||flaga==3||flaga==4)								//jezeli mamy gotwe usrednione dane do wyslania
    	{
    		usartTransmisja(flaga);							// wysłanie danych za pomocą UARTA do komputera PC
    		usartTransmisja(wyniki_sred_msb);
    		usartTransmisja(wyniki_sred_lsb);
    		flaga = 6;
    		wyniki_sred_msb = 0;
    		wyniki_sred_lsb = 0;
    	}
    
    	}
    PORTA |=_BV(PA1);
    }
    
    
    
    
    
  • #14 8121900
    hotdog
    Poziom 26  
    zmienne suma_msb i suma_lsb powinny być wyzerowane w pętli for która przebiega po "k" . inaczej masz przekłamanie wyników.

    No chyba że ja źle rozumiem co chcesz zrobić

    Pozdrawiam
  • Pomocny post
    #15 8123116
    tadzik85
    Poziom 38  
    Wróć do unii na pewno.
    Dynamiczne tablice nie są ci potrzebne.

    Z wyliczaniem tak średniej nie widzę problemu. Zbierasz 20 wyników. Sortujesz np bąbelkowi. Sumujesz 10 elementów tablicy licząc od 5. dzielisz przez 10.

    Struktura jest ci potrzebna bo gdy operujesz operacji na bajtach popełniasz błąd w przypadku przepełnień. Tak samo w przypadku dodawania 10 elementów nie zapomnij o tym ze wynik będzie o 4 bity dłuższy. Jeśli czynniki mają po max 12 bitów wynik jako int wystarczy.

    Ale jak już wraz z kolegami wspomnieliśmy unia jest potrzebne, no chyba, że ręcznie będziesz przeliczał 2 bajty na int.
  • #16 8124707
    jerraz
    Poziom 10  
    Nie mam zielonego pojęcia jak Wy to widzicie na unii. Ja zrobiłem to mniej więcej tak:
    Mile widziane jakieś poprawki, wskazówki, itp ;-)
    Z góry dzięki za pomoc.
    pozdrawiam

    
    #define RDY	PB4
    #define TIMER_CLOCK 2
    
    
    //#include <avr/interrupt.h>						// dolaczenie standardowych bibliotek obslugi przerwan bez blokady (obsluguje signal.h)
    #include <avr/signal.h>						// dolaczenie standardowych bibliotek obslugi przerwan z blokada
    #include "cpuCnfg.h"							// konfiguracja procesora
    #include <inttypes.h>
    #define rozmiar_wierszy 20 //6
    // definicje zmiennych użytych w programie  
    
    unsigned int preskaler;
    volatile unsigned int k;
    volatile unsigned char flaga;
    volatile unsigned int wynik_msb=0;
    volatile unsigned int wynik_lsb=0;
    
    volatile unsigned short pomiary_0[rozmiar_wierszy];
    volatile unsigned short pomiary_1[rozmiar_wierszy];
    volatile unsigned short pomiary_2[rozmiar_wierszy];
    volatile unsigned short pomiary_3[rozmiar_wierszy];
    volatile unsigned short pomiary_4[rozmiar_wierszy];
    
    
    // ustawienie timera który steruje przerwaniem w programie
    
    //----------ustawienie przerwania dla rozpoczecia pomiaru od timera-------------------------------------------
    void Start(void)					
    {
    	TIMSK |= _BV(OCIE1A); 						//zezwolenie na przerwanie
    }
    //----------wylaczenie przerwania pomiaru, koniec pomiaru od timera-------------------------------------------
    void Stop(void)
    {
    	TIMSK &= ~(_BV(OCIE1A)); 					// blokada przerwania
    }
    
    
    
    int main(void)
    {
    _delay_ms(10);								
    
    // konfiguracja portów uzywanych w programie 
    
    // kierunek SPI, porty ustawione jako wyjścia
    	DDRB |= _BV(PB0);		// SS	
    	DDRB |= _BV(PB1);		// SCK
    	DDRB |= _BV(PB3);		// MISO
    
    // kierunek portów sterowania dekoderami 74HC138, porty ustawiona jako wyjścia
    	DDRB |= _BV(PB5);		
    	DDRB |= _BV(PB6);
    	DDRB |= _BV(PB7);
    
    
    // ustawienie kierunku UARTA oraz przecisków 							
    	DDRD = 0xFC;								
    	DDRE = 0x02;								
    	PORTD = 0xFF;								
    	PORTE = 0x03;								
    
    // ustawienie diody podłączonej do portu PA0 i PA1	
    	DDRA |= _BV(PA0)|_BV(PA1);			 
    	PORTA |= _BV(PA0)|_BV(PA1) ;
    	
    
    
    // inicjalizacja SPI i UARTA
    	spiInit();									// wywolanie SPI
    	usartInit(MYUBRR);							// wywolanie USART0
    
                        		
    
    // ustawienie timera wykorzystywanego do przerwania 
    	TCCR1B = _BV(CS10) | _BV(CS11) | _BV(WGM12);// rejestr timera
    	preskaler = 2;
    	OCR1A = ((FOSC/2/preskaler/TIMER_CLOCK) - 1 );	// preskaler timera
    
    
    // zerowanie tablic 
    
    for (int e = 0; e < rozmiar_wierszy; e++ )
    	{
    pomiary_0[e]=0;
    pomiary_1[e]=0;
    pomiary_2[e]=0;
    pomiary_3[e]=0;
    pomiary_4[e]=0;
    }
    
    
    // zezwolenie na przerwania
    	sei();
    
    /***************************************************************************************************************
    * pomiar
    ***************************************************************************************************************/
    
    while(1)
    {
    
    	if(bit_is_clear(PIND, 4))          		// nacisniecie przycisku S1 rozpoczyna pomiar
    	{
    
    	Start();						
    	PORTA &=~_BV(PA0);						// włączenie diody led podpiętej pod port PA0							
    	}							
    
    	if(bit_is_clear(PIND, 5))          		// nacisniecie przycisku S2 kończy pomiar
    	{
    
    	Stop();
    	PORTA |=_BV(PA0);						// wyłączenie diody led podpiętej pod port PA0
    	}
    
    }
    } 
    
    SIGNAL (SIG_OUTPUT_COMPARE1A)				//obsługa przerwania od T1
    {
    
    PORTA &=~_BV(PA1);
    
    unsigned int suma = 0;
    unsigned int srednia = 0; 
    
    
    	for(k=0; k<=4; ++k)					// wybieranie który czujnik ma zostać obsłużony
    	{
    
    		if(k==0)
    		{
    			for (int p=0; p < rozmiar_wierszy; p++)
    			{
    			czujnik0;
    
    			off_SS;
    
    			spiTransmisja(0xFF);				// czytanie pierwszego bajtu danych
    			wynik_msb=SPDR;
    
    			spiTransmisja(0xFF);				// czytanie drugiego bajtu danych
    			wynik_lsb=SPDR;
    
    			set_SS;
    
    			pomiary_0[p] = (unsigned short)(wynik_msb <<8 ) | wynik_lsb;
    			}
    			
    			for(int i=rozmiar_wierszy;i>0;i--)
    			{ 
    			for(int j=0;j<i;j++)
    				{
    				if(pomiary_0[j]<pomiary_0[j+1])
    					{
    					int liczba; 
    					liczba=pomiary_0[j+1]; 
    					pomiary_0[j+1]=pomiary_0[j]; 
    					pomiary_0[j]=liczba; 
    					} 
    				} 
    			} 
    
    			for (int i=5; i<(rozmiar_wierszy-5); i++)
    			{
    			suma +=pomiary_0[i];
    			}
    			srednia = suma/10; 
    
    		flaga = 0;
    		}
    //+++++++++++++++++++++++++++++++++++++++++++++++
    //reszta czujnikow
    //+++++++++++++++++++++++++++++++++++++++++++++++
    		if (flaga==0||flaga==1||flaga==2||flaga==3||flaga==4)								//jezeli mamy gotwe usrednione dane do wyslania
    	{
    
    		wynik_msb = srednia>>8;
    		wynik_lsb = srednia;
    
    		usartTransmisja(flaga);							// wysłanie danych za pomocą UARTA do komputera PC
    		usartTransmisja(wynik_msb);
    		usartTransmisja(wynik_lsb);
    		flaga = 6;
    		for (int e = 0; e < rozmiar_wierszy; e++ )
    		{
    		pomiary_0[e]=0;
    		pomiary_1[e]=0;
    		pomiary_2[e]=0;
    		pomiary_3[e]=0;
    		pomiary_4[e]=0;
    		}
    		wynik_msb = 0;
    		wynik_lsb = 0;
    		srednia = 0;
    		suma = 0;		
    
    	}
    
    	}
    PORTA |=_BV(PA1);
    }
    
  • Pomocny post
    #17 8125239
    Dr.Vee
    VIP Zasłużony dla elektroda
    Tak też jest dobrze, unia to tylko nieprzenośny sposób ułatwienia sobie zadania :)

    Kilka błędów - użyj uint16_t zamiast unsigned short. Jak już tmf wspomniał do uśredniania musisz użyć większego rozmiaru zmiennej żeby wykluczyć przepełnienie, a na avr int ma rozmiar taki sam jak short. Użyj uint32_t.

    Poza tym całe to testowanie flag i numeru czujnika to jakiś koszmarek. Zrób sobie tablicę czujników i po niej iteruj - rozmiar kodu zmniejszy Ci się 3-4 razy.

    No i nie mów, że wszystkie te operacje (sortowanie, uśrednianie itp) wykonujesz w procedurze obsługi przerwania?

    Pozdrawiam,
    Dr.Vee
  • #18 8125422
    jerraz
    Poziom 10  
    Dr.Vee napisał:

    Kilka błędów - użyj uint16_t zamiast unsigned short. Jak już tmf wspomniał do uśredniania musisz użyć większego rozmiaru zmiennej żeby wykluczyć przepełnienie, a na avr int ma rozmiar taki sam jak short. Użyj uint32_t.

    Poza tym całe to testowanie flag i numeru czujnika to jakiś koszmarek. Zrób sobie tablicę czujników i po niej iteruj - rozmiar kodu zmniejszy Ci się 3-4 razy.

    No i nie mów, że wszystkie te operacje (sortowanie, uśrednianie itp) wykonujesz w procedurze obsługi przerwania?

    Pozdrawiam,
    Dr.Vee

    Mogę zastąpić unsigned short uint16_t, ale jaka bibliotekę do tego potrzebuje? Bo samo dodanie powodowało błędy. Nie do końca wiem jak zrobić sobie taką tablicę czujników i po niej iterować... A wszystkie te procedury wykonuje w przerwaniu. Próbowałem zrobić coś takiego, że zbieram pomiary w przerwaniu, a całe to przetwarzanie wykonywać poza przerwaniem, ale nie działało mi to. Po prostu nie widział mi flag, które wystawiam i w konsekwencji nic nie wysyłał. ;/
    Jakbyś mógł podpowiedzieć był bym wdzięczny. Z góry dzięki za pomoc.
    Pozdrawiam
  • Pomocny post
    #19 8125513
    Dr.Vee
    VIP Zasłużony dla elektroda
    Odpowiednie typedefy są w nagłówku stdint.h
    Co do podziału pomiędzy przerwanie a program główny to pewnie zapomniałeś modyfikatora volatile przy deklaracji zmiennych, które są dzielone pomiędzy przerwaniem a main().
    Co do "tablicy czujników":
    struct czujnik
    {
        uint8_t     adres;      /* do wyboru czujnika na szynie */
        uint8_t     ileProbek;
        uint16_t    probki[ROZMIAR];
    };
    
    /* globalna deklaracja 5 czujników razem z tablicami pomiarów */
    /* warto przenieść inicjalizację do main ze względu na zużycie pamięci */
    static struct czujnik czujniki[5] = 
    {
        { 1, 0, {0} },
        { 2, 0, {0} },
        { 3, 0, {0} },
        { 4, 0, {0} },
        { 5, 0, {0} },
    };
    
    static void pobierzJedenPomiar(struct czujnik* cz)
    {
        uint8_t low, high;
    
        ustawAdresCzujnika(cz->adres);
    
        high = czytajSPI();
        low = czytajSPI();
    
        /* zabezpiecz się przed przepełnieniem tablicy */
        if (cz->ileProbek < ROZMIAR)
        {
            cz->probki[cz->ileProbek] = (high << 8) | low;
            cz->ileProbek += 1;
        }
    }
    
    int main(void)
    {
        for (;;)
        {
            uint8_t i;
            for (i = 0; i < 5; ++i)
            {
                pobierzJedenPomiar(&czujniki[i]);
            }
        }
    }

    Pozdrawiam,
    Dr.Vee
REKLAMA