Power-Down-Modus beim Atmega88
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
}