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

[C] Nie wykonuje instrukcji po pętli

long_os 03 Kwi 2010 21:32 1506 8
  • #1 7917445
    long_os
    Poziom 10  
    Witam !

    Mam taki programik napisany w Avr-gcc.
    #include <avr/io.h>
    #include <inttypes.h>		//alternatywne typy zmiennych
    #include <avr/pgmspace.h>	//adresowanie zmiennych w obszarze programu
    #include <avr/interrupt.h>	//obsługa przerwań
    #include <util/delay.h>
    #include "ffft.h"			//funkcje Fouriera
    #include "usart.c"			//obsługa USART
    
    #define ADC_ON  ADCSRA|= _BV(ADSC)|_BV(ADEN)|_BV(ADPS2)|_BV(ADPS0) 
    #define TIMER0_ON TCNT0 = 0x30
    
    int16_t capture[FFT_N];				/* Wave capture buffer */
    complex_t bfly_buff[FFT_N];			/* FFT buffer */
    uint16_t spectrum[FFT_N/2];			/* Spectrum output buffer */
    
    volatile uint8_t probka = 0;		//zliczanie pobranych próbek
    volatile uint8_t fla = 0;
    //7 - bufor zapisany próbkami, dane gotowe do transmisji
    //6 - trwa analiza Fouriera
    //5 - trwa wysyłanie danych
    //0 - zablokuj wysyłanie USART
    
    #define f_buf_trans 7
    #define f_analyze 6
    #define f_usart_sending 5
    #define f_usart_disable 0
    
    void init(void){
    
    	//inicjalizacja trybu zliczania TIMERA 1--------------------------------------
    	//stan OC1A (PB1) zmieniany na przeciwny - generacja przebiegu 444 kHz
    	//na potrzeby filtra
    	DDRB = _BV(PINB1);				//PB1 jako wyjście
    	OCR1A = 0x12;					//załadowanie wartości do rejestru timera
    	TCCR1A = _BV(COM1A0) | _BV(FOC1A);	//preskaler timera1=0; force output 1
    	TCCR1B = _BV(CS10) |_BV(WGM12);		//tryb pracy CTC, resetowanie Timera 1 po każdym przepełnieniu
    	
    	//inicjalizacja przetwornika ADC-----------------------------------------------
    	ADMUX = _BV(REFS0) | _BV(MUX2) | _BV(ADLAR); 	//wejście ADC4, pin PC4, wynik przesunięty do lewej
    	
    	//konfiguracja Timera 0 - generacja przerwań 9,6 kHz wyzwalacjących próbkowanie ADC
    	//dla preskalera 8 musi odliczyć 208 razy
    	TIMER0_ON;		//załadowanie wartości od której będzie odliczał - jeszcze 208 razy
    	TCCR0 = _BV(CS01);	//ustawienie preskalera na 8
    	TIMSK = _BV(TOIE0);	//zezwolenie na przerwania
    	sei();		//zezwolenie na przerwania
    	
    	//Aktywacja USART-----------------------------------------------
    	UBRRL = 0x67;					//transmisja 9600 dla kwarcu 16 MHz
    	UCSRB = (1<<RXEN)|(1<<TXEN);
    	UCSRC = _BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0);
    }
    
    ISR(SIG_OVERFLOW0){
    	TIMER0_ON;
    	ADC_ON;
    	while(!(ADCSRA & _BV(ADIF)));
    	capture[probka] = ADC;
    	++probka;
    }
    void send_usart(void){
    	if(!(fla & _BV(f_usart_disable))){
    		for(uint8_t i=0;i<FFT_N/2;i++){
    			while (!(UCSRA & (1 << UDRE)));
    			UDR = spectrum[i];
    			while (!(UCSRA & (1 << UDRE)));
    			UDR = (spectrum[i]>>8);
    		}
    		while (!(UCSRA & (1 << UDRE)));
    			UDR = 0xFF;
    		while (!(UCSRA & (1 << UDRE)));
    			UDR = 0xFF;
    	fla = _BV(f_usart_disable);
    	}
    }
    
    int main(void){
    	init();
    	while(1){
    		if(probka>FFT_N-1){					//jeśli zapełniłeś cały bufor wejściowy
    			probka=0;							//zapełniaj od początku
    			fft_input(capture, bfly_buff);		//przepisz do Fouriera
    			fft_execute(bfly_buff);				//zrób Fouriera
    			fft_output(bfly_buff, spectrum);	//zwróć wyniki obliczeń			
    			send_usart();
    		}	
    	}
    	return 0;
    }
    

    Kompilację przeszedł sprawnie, jednak podczas podglądu a Avr Studio, oraz pracy w procesorze z niewiadomych przyczyn nie wykonuje tych instrukcji:
    while (!(UCSRA & (1 << UDRE)));
    			UDR = 0xFF;
    		while (!(UCSRA & (1 << UDRE)));
    			UDR = 0xFF;
    	fla = _BV(f_usart_disable);

    chciałem w ten sposób zabezpieczyć się, żeby wysyłał na USART tylko raz tablicę spectrum. Co jest nie tak ? Dodam, że do konsoli nie docierają wogóle znaki 'FF'.
  • #2 7918034
    michalko12
    Specjalista - Mikrokontrolery
    Dwie sprawy. Przedstawiłeś kawałek kodu w którym tylko ustawiasz te f_usart_disable i oczekujesz, aż ktoś zgadnie co dalej z tym robisz?

    Skoro fla przetrzymuje więcej flag to taki zapis
    fla = _BV(f_usart_disable);
    jest trochę nie na miejscu.
    fla |= _BV(f_usart_disable);
  • #3 7918194
    long_os
    Poziom 10  
    Przedstawiłem cały kod. Narazie nie korzystam z innych flag. Problemem jest to, że nawet to co jest nie do końca działa.
    Tak na marginesie- właśnie po to żeby się nie trzeba było domyślać wrzuciłem cały listing:)
  • #5 7919779
    long_os
    Poziom 10  
    Przerwanie, patrząc na symulację AVR Studio, wykonuje się. Do podprogramu wysyłania po UART tez wchodzi. Nie wykonuje jedynie tych instrukcji które wyróżniłem. Co ciekawe,instrukcji za wywołaniem funkcji wysyłania też nie wykonuje:/
  • #6 7920561
    rpal
    Poziom 27  
    Wyłącz optymalizację kodu i wtedy pogadamy :) Jeśli pętla się nie wykonuje tylko program przechodzi za nią widać warunek jej wykoniania nie jest spełniony i trzeba go rozbic na kawałki aby sprawdzić co jest tego powodem a nie składać operacji na bitach i operacji logiocznych w całoś. Może byc że zapomniałeś o klamrach bo tego nie wiemy. A może kompilator w nieodpowiednio ustawionej optymalizacji po prostu ignoruje to co napisałeś ?
  • #7 7921288
    long_os
    Poziom 10  
    Wszak napisałem, że nie realizuje intrukcji ZA pętlą, a nie w funkcji warunkowej... Poza tym zamieściłem w pierwszym poście cały listing - widać na nim czy są wszystkie klamry.
  • #8 7921547
    BoskiDialer
    Poziom 34  
    Nigdzie nie widzę jaką wartość ma FFT_N, jednak zakładam, że jest to potęga dwójki (użycie fft) oraz jest mniejsze lub równe 128 (inaczej warunek "if(probka>FFT_N-1)" nie był by nigdy spełniony (probka ma 8bit). Samo wysyłanie wygląda poprawnie, kompilator mi się rzucał na deklarowaniu zmiennej i wewnątrz inicjalizacji pętli, przez co kompilacja nie przechodziła do końca (jest to error, nie warning) - może cały czas wgrywasz jakąś starą wersję softu ze względu na to, że kompilator nie może skompilować nowej? Wyciągnij deklarację zmiennej "i" przed samą pętlę.
    Cytat:
    tmp.c:45: error: 'for' loop initial declaration used outside C99 mode
  • #9 7933546
    long_os
    Poziom 10  
    Teraz dla odmiany VMLAB pokazuje coś takiego:
    [PC = $0040, Time =   33.21 ms, {MEM}]: Read access outside the Data Memory adddress limit
    
    o co chodzi ?
REKLAMA