-         

Ergebnis 1 bis 3 von 3

Thema: Power-Down-Modus beim Atmega88

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    18.07.2006
    Beiträge
    15

    Power-Down-Modus beim Atmega88

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Tag,

    ich versuche gerade mal ein wenig mit dem Power Pown Modus zu experimentieren.

    Dabei soll der Controller nach dem Start und der Initialisierung sofort in den Power-Down-Mode gehen. Durch einen gedrückten Taster ensteht dann ein Low-Pegel am INT1, welcher als Level Interrupt programmiert ist und den Controller aus dem Power-Down-Mode aufweckt. Das Programmm läuft..... Bis dahin läuft auch alles einwandfrei.

    Nun mein Problem:

    Durch erneutes drücken des Tasters, also erneuter Low-Pegel am INT1 soll der Controller wieder in den Power-Down-Mode gehen. Das funktioniert nur leider nicht. Vielleicht hat einer ne Idee woran das liegen kann?

    Hier ist der Code:

    Code:
    #include<avr/io.h>
    #include<avr/sleep.h>
    #include<avr/interrupt.h>
    #include <stdio.h>
    #include <inttypes.h>
     
    typedef unsigned char	u8;
    typedef signed short	s16;
    
    #define FOSC 14745600 //Clock Speed
    #define BAUD 9600
    #define UBRR ((FOSC / (BAUD * 16L)) - 1)
     
    #define	XTAL		1e6		// 1MHz
     
    #define KEY_PIN		PIND
    #define KEY0		0
    #define KEY1		1
    #define KEY2		2
    #define KEY3		3
    #define KEY4		4
     
    #define LED_DDR		DDRB
    #define LED_PORT	PORTB
    #define LED0		0
    #define LED1		1
    #define LED2		2
    #define LED3		3
    #define LED4		4
     
    //#define REPEAT_MASK	(1<<KEY1^1<<KEY2)	// repeat: key1, key2
    #define REPEAT_START	50		// after 500ms
    #define REPEAT_NEXT	20		// every 200ms
    
    //Initialisierung AD-Wandler
    void ADC_wandlung();
    
    //Initialisierung UART
    void uart_init();
     
     
    u8 key_state;				// debounced and inverted key state:
    					// bit = 1: key pressed
    u8 key_press;				// key press detect
     
    u8 key_rpt;				// key long press and repeat
    
    unsigned int pause;
    
    unsigned char taster = 0xFF;
    unsigned char a;
    
    
    void uart_init()
    {
    
    /* Port als Ausgang */
    //DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3);
    
    //PORTB |= (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3);
    
    /* Aktivieren des Empfängers, des Senders und des "Daten empfangen+Daten leer"-Interrupts */
    UCSR0B = (1<<RXCIE0)|(1<<RXEN0) |(1<<TXEN0) | (1 << UDRIE0);
    
    /* baud rate*/
    UBRR0H = (unsigned char) (UBRR>>8);
    UBRR0L = (unsigned char) UBRR;
    
    /* frame format: 8data, 2stop bit*/
    UCSR0C = (1 << USBS0) | (3 << UCSZ00);
    }
     
     
    ISR(TIMER0_OVF_vect )			// every 10ms
    {
      static u8 ct0, ct1;
      u8 i;
     
      TCNT0 = (u8)(s16)-(XTAL / 1024 * 10e-3 + 0.5);	// preload for 10ms
     
      i = key_state ^ ~taster;		// key changed ?
      ct0 = ~( ct0 & i );			// reset or count ct0
      ct1 = ct0 ^ (ct1 & i);		// reset or count ct1
      i &= ct0 & ct1;			// count until roll over ?
      key_state ^= i;			// then toggle debounced state
      key_press |= key_state & i;		// 0->1: key press detect
    }
     
     
    u8 get_key_press( u8 key_mask )
    {
      cli();					// read and clear atomic !
      key_mask &= key_press;                        // read key(s)
      key_press ^= key_mask;                        // clear key(s)
      sei();
      return key_mask;
    }
     
     
    u8 get_key_rpt( u8 key_mask )
    {
      cli();					// read and clear atomic !
      key_mask &= key_rpt;                        	// read key(s)
      key_rpt ^= key_mask;                        	// clear key(s)
      sei();
      return key_mask;
    }
     
     
    u8 get_key_short( u8 key_mask )
    {
      cli();			// read key state and key press atomic !
      return get_key_press( ~key_state & key_mask );
    }
     
     
    u8 get_key_long( u8 key_mask )
    {
      return get_key_press( get_key_rpt( key_mask ));
    }
     
     
    int main( void )
    {
    
     	 //UART Initialisieren
      	uart_init();
    
      	TCCR0B = 1<<CS02^1<<CS00;			// divide by 1024
      	TIMSK0 = 1<<TOIE0;				// enable timer interrupt
    
      	DDRD &= ~( 1<< PD3) | (1 << PD0) | (1 << PD2);    
      	
    	SMCR &= ~(1 << SM0) | (1 << SM2);  				//Power Down Modus
    	SMCR |=  (1 << SM1) | (1 << SE);				//Power Down & Sleep Enable
    
    	EICRA &= ~(1 << ISC11) | (1 << ISC10);  		//Low Level of INT1 generates Interrupt Request
    	EIMSK |= (1 << INT1);							//External Interrupt Request Enable
    	sei();
    
    	set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_mode();
    	EIMSK &= ~(1 << INT1);							//External Interrupt Request Diable
     	
      	LED_PORT = 0xFF;
      	LED_DDR = 0xFF;
      
     
      for(;;){	
    
        ADC_wandlung();
    
    	if(!(PIND & (1 << PIND3)))
    	taster &= ~(1 << 4);
    	
    	else
    	taster |= (1 << 4); 
    
        if( get_key_press( 1<<KEY4 ))					//Interrupt at INT1
    	{
    	EIFR |= (1 << INTF1);							//INT1 Interrupt Flag löschen
    	EIMSK |= (1 << INT1);							//External Interrupt Request Enable
    	sleep_mode();
    	EIMSK &= ~(1 << INT1);							//External Interrupt Request Diable
    
    	}
    	
        //erste LED
     	if((ADCH <=35) && (ADCH >= 30))
    	taster &= ~(1 << 0);
    	
    	else
    	taster |= (1 << 0); 
    
        if( get_key_press( 1<<KEY0 ))
        LED_PORT ^= 1<<LED0;
    
    	
        //zweite LED
    	if((ADCH <=110) && (ADCH >= 105))
    	taster &= ~(1 << 1);
    	
    	else
    	taster |= (1 << 1); 
     
    
        if( get_key_press( 1<<KEY1 ))
          LED_PORT ^= 1<<LED1;
    
    
        //dritte LED
     	if((ADCH <=207) && (ADCH >= 202))
    	taster &= ~(1 << 2);
    	
    	else
    	taster |= (1 << 2); 
    
        if( get_key_press( 1<<KEY2 ))
        LED_PORT ^= 1<<LED2;
    
        //vierte LED
    	if((ADCH <=253) && (ADCH >= 248))
    	taster &= ~(1 << 3);
    	
    	else
    	taster |= (1 << 3); 
     
    
        if( get_key_press( 1<<KEY3 ))
          LED_PORT ^= 1<<LED3;
    
      }
    }
    
    void ADC_wandlung()		//ADC0/PCINT - PORTC, Bit0
    {
      DDRC = 0x00;		// Alle Pins von Port C als Eingang definiert
      ADMUX &= ~((1<<MUX0)|(1<<MUX1)|(1<<MUX2)|(1<<MUX3));	//ADC0 eingestellt.
      ADCSRA = (1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);
      ADMUX |= (1<<REFS0) | (1 << ADLAR); //|(1<<REFS0);
    
      ADCSRA |= (1<<ADSC);		//AD Wandlung
      while (ADCSRA & (1<<ADSC))
      {
      ;
      }
      
    }
    
    ISR(USART_UDRE_vect)
    {
      if(pause == 50000)
      {
      UDR0 = ADCH;
      pause = 0;
      }
      pause++;
      a = ADCH;
    
    }
    
    
    ISR(INT1_vect )
    {
    //EIMSK &= ~(1 << INT1);							//External Interrupt Request Diable
    }

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Der levelgetriggerte INTx ist nur sinnvoll, um ihn aufzuwecken. Sobald er wach ist, solltest du INTx auf Flanke stellen und vor dem Schalfengehen dann wieder auf Level-Trigger. Evtl die INTxFlags resetten.
    Disclaimer: none. Sue me.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    18.07.2006
    Beiträge
    15
    Hey, jetzt klappt alles!

    Die Abfrage war falsch. Muss nicht nur abfragen ob der Taster gedrückt ist, sondern auch ob er wieder losgelasssen wurde. Erst dann darf was passieren.

    Ansonsten macht er ja schon zig Durchläufe in der ISR.

    Gruß

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •