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][C] problem z ponownymi pomiarami

gulgul 05 Sty 2010 23:07 1579 2
REKLAMA
  • #1 7491991
    gulgul
    Poziom 10  
    Witam,
    jestem początkujący jeżeli chodzi o programowanie mikrokontrolerów, więc poniższy kod nie jest przepiękny. Proszę o poprawę...

    Główny problem:
    układzik jest to dalmierz ultradźwiękowy uzyskujący spory zasięg. Jednak by mógł też mierzyć odległość przedmiotów blisko umieszczonych muszę przełączać próg komparatora atmegi. Robię to za pomocą portu B5 i dodatkowego układu podłączonego do niego. Dodatkowo zmniejszam czas strefy martwej(opóźnienie).
    Każdy pomiar jest wykonywany po przyciśnięciu przycisku i wyświetlany na wyświetlaczu. Pobierana też jest temperatura, ale jeszcze nie wpływa na dokładność odległości.

    Układ działa dobrze, dopóki nie przełączę portu B5. Gdy to zrobię, układ zamiast zrobić 2 pomiary(1 dalekosiężny i drugi już bliski) robi ich duuużo, aż atmega się zawiesza(sprawdzałem na oscyloskopie). Podejrzewam, że to jakiś problem z komparatorem, ale na moim stopniu zaawansowania to mogą to być też inne problemy.

    Bardzo proszę o pomoc i poprawę kodu.
    
    #include <avr/io.h>                // dostęp do rejestrów
    #include <avr/interrupt.h>        // funkcje sei(), cli()
    #include <avr/signal.h>                // definicje SIGNAL, INTERRUPT
    #include <util/delay.h>
    #include <stdlib.h>
    #include <avr/pgmspace.h>
    #include "lcd.h"
    
    #define DDR_GEN			DDRB
    #define PORT_GEN		PORTB
    #define PORT_GEN_PIN	3
    
    #define KOMPARATOR_ON   ACSR |= _BV(ACIS1) | _BV(ACIS0) | _BV(ACIE);
    #define KOMPARATOR_OFF	ACSR |= _BV(ACD);
    
    #define ZASIEG_MAX		16000
    #define ZASIEG_MIN		900
    
    	
    	volatile int opoznienie;
    	volatile int czas=0;
    	volatile int value;
    	volatile long pomiar;
    	int flag=3;
    	
    
    
    
    void za_daleko(void){
    	cli();
    	KOMPARATOR_OFF;
    	TCCR2=0;
    	lcd_init(LCD_DISP_ON);
    	lcd_clrscr();
    	lcd_puts("Obiekt jest poza\nzasiegiem");
    }
    
    
    void wynik_pomiaru(void){
    	float odl;
    
    	char buffer[7];
    	
    			lcd_init(LCD_DISP_ON);
    	lcd_clrscr();
    	odl=0.017*(opoznienie+12.5*czas);
    	
    	if(odl<(0.017*opoznienie)+1){
    		
    		if(flag==2){
    
    	lcd_puts("Obiekt jest za\nblisko czujnika");
    		}else{ flag=1;
    		flag=2;
    		opoznienie=10;
    		PORTB &= !_BV(5);
    
    		Pomiar();
    		}
    	}else{	
    	
    		lcd_puts("Temp: ");
    
    		dtostrf( pomiar ,3,1, buffer);
    		lcd_puts(buffer);
    		lcd_putc(0xDF);
    		lcd_puts("C");
    		lcd_puts("\nOdl: ");
    		dtostrf( odl ,3,1, buffer);
    		lcd_puts(buffer);
    		lcd_puts(" cm");
    	}
    }
    
    
    SIGNAL(SIG_COMPARATOR)
    {
    	cli();
    
    	KOMPARATOR_OFF;
    	TCCR2=0;
    
    	wynik_pomiaru();
    }
    
    ISR(TIMER2_COMP_vect){
    	czas++;
    	if(czas>ZASIEG_MAX) za_daleko();
    	
    
    }
    
    void gen40kHz(void){
    	PORT_GEN |= _BV(PORT_GEN_PIN);
    	_delay_us(12.5);
    	PORT_GEN ^= _BV(PORT_GEN_PIN);
    	_delay_us(12.5);
    }
    
    void ping(void){
    	DDR_GEN |= _BV(PORT_GEN_PIN);
    	for(int i=0;i<10;i++){
    		gen40kHz();
    	}
    	DDR_GEN &= !_BV(PORT_GEN_PIN);
    
    }
    
    
    void Timer_init(void){
    	OCR2=99;
    	TCCR2 = _BV(WGM21) | _BV(CS20);
    	TIMSK |= (1 << OCIE2);
    }
    
    void Pomiar(void){
    	
    		cli();
    		czas=0;
    		  lcd_init(LCD_DISP_OFF);
    
    		  
    			DDRD |=_BV(PD6);
    			PORTD&=!_BV(PD6);
    			DDRD&=!_BV(PD6) ; 
    		  
    				   
    		  ping();
    
    			_delay_us(opoznienie); 
    			Timer_init();
    			ACSR &= !_BV(ACD);
    			KOMPARATOR_ON;
    
    			 sei(); 
    			 
    }
    
    
    int main(void)
    {
    
    
      DDRD &= !_BV(6);
      PORTD &= !_BV(6);
      DDRB &= !_BV(0);
      PORTB |= _BV(0);
      DDRB |= _BV(4);
      PORTB |=_BV(4);
      DDRB |=_BV(5);
    
      
    
      DDR_GEN |= _BV(PORT_GEN_PIN);
    
    
      lcd_init(LCD_DISP_ON);
      lcd_clrscr();
      lcd_puts("Dalmierz    BETA\n");
      
      
    
    ADMUX |= _BV(REFS0)|_BV(ADLAR)|_BV(MUX1)|_BV(MUX0);
    
    ADCSRA |= _BV(ADEN)| _BV(ADPS0)| _BV(ADPS1);
    	
                
      for(;;){
     
    	  if(!(PINB & _BV(0))){
    				flag=0;
    
                    ADCSRA |= _BV(ADSC);
    				while( ADCSRA & _BV(ADSC)) {};
    
    
    				pomiar=ADCH;
    		
    				pomiar=pomiar*500/256-273.15;
               
    			opoznienie=ZASIEG_MIN;
    			PORTB |= _BV(5);
    			Pomiar();
    			
    			 
    			 while(!(PINB & _BV(0))) {}
    			_delay_ms(80);
    
    		}
    	}
    	
    }
    
  • REKLAMA
  • #2 7492253
    michalko12
    Specjalista - Mikrokontrolery
    Coś ci sie pomyliło, zamiast tyldy dajesz wykrzykniki. Popraw cały kod i wtedy sprawdź.
    DDRD &= !_BV(6);
    PORTD &= !_BV(6); 
    
    DDRD &= ~_BV(6);
    PORTD &= ~_BV(6);
  • #3 7492682
    gulgul
    Poziom 10  
    faktycznie! a mie się zdawało, że to jest równoważne . Wielkie dzięki!
REKLAMA