Funky
12.10.2006, 10:36
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:
#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
}
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:
#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
}