Razer
29.08.2006, 11:53
Hallo an alle
Bei meinem Gesichtsbräunertimer hab ich noch ein paar Probleme.
Doch leider funktioniert noch nicht alles ganz zuverlässig. Am Auslesen
des EEproms happerts noch ein bisschen. Woran kann das liegen??
Und was mir noch aufgefallen ist, wenn ich KEY0 gedrückt halte, dann
zählt er viel langsamer die Variable time herunter als wenn ich KEY1
gedrückt halte und er nach oben zählt.
Hier mal der Source Code:
/*******************************************
Title: Belichtungstimer
Author: Robert Schilling
Date: 9.8.2006
Hardware: Atiny26 + Board
********************************************/
#include <avr/io.h>
#include <stdlib.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#define LEDPORT PORTA
#define LED_A PA0
#define LED_B PA1
#define LED_C PA2
#define LED_D PA3
#define LED_E PA4
#define LED_F PA5
#define LED_G PA6
#define RELAISPORT PORTA
#define RELAISPIN PA7
#define TASTER_TRANSPORT PORTB
#define KEY_PIN PINB
#define KEY0 4
#define KEY1 5
#define KEY2 6
#define REPEAT_MASK (1<<KEY0^1<<KEY1^1<<KEY2) // repeat: key1, key2
#define REPEAT_START 50 // after 500ms
#define REPEAT_NEXT 20 // every 200ms
#define EEP_ADRESS_MIN 0x01
#define EEP_ADRESS_SEC 0x02
#define DONE 0x01
#define UNDONE 0x00
#define TIMER_1SEC_ENABLED 0x01
#define TIMER_1SEC_DISABLED 0x00
#define _D 0x0B
#define _O 0x0C
#define _N 0x0D
#define _E 0x0E
const uint8_t symbol[]={0x3F, //0
0x05, //1
0x5B, //2
0x4F, //3
0x65, //4
0x6E, //4
0x7E, //5
0x07, //6
0xFF, //7
0x6F, //8
0x08, //9
0x5D, //d
0x5C, //o
0x54, //n
0x7A}; //E
const uint8_t active_position[] = {0x78,
0x74,
0x72,
0x71};
uint8_t segment[4];
uint8_t position;
volatile uint16_t time = 0;
volatile uint8_t done = UNDONE;
volatile uint8_t counter;
volatile uint8_t timer_1sec = TIMER_1SEC_DISABLED;
volatile uint8_t counter_1sec = 0;
uint8_t key_state; // debounced and inverted key state:
// bit = 1: key pressed
uint8_t key_press; // key press detect
uint8_t key_rpt; // key long press and repeat
void time2dispay(void);
void eeprom_read(void);
void eeprom_write(void);
void init(void);
void update_display(void);
void timer_init(void);
uint8_t get_key_press(uint8_t key_mask);
uint8_t get_key_rpt(uint8_t key_mask);
uint8_t get_key_short(uint8_t key_mask);
uint8_t get_key_long(uint8_t key_mask);
void timer_init(void)
{
TCCR1B = ((1 << CS12) | (1 << CS11) | (1 << CTC1)); //Prescaler = 32; Enabale CTC Mode
OCR1C = 0xFA; //Compare Interrupt at 250
TIMSK |= (1 << OCIE1A);
}
void time2display(void) //ZEit wird zerlegt in die einzelnen Ziffern
{
uint16_t rest;
segment[0] = time / 600;
rest = time % 600;
segment[1] = rest / 60;
rest %= 60;
segment[2] = rest / 10;
rest %= 10;
segment[3] = rest;
}
void eeprom_read(void) //EEProm wird ausgelesen und Zeit wird berechnet
{
time = (eeprom_read_byte((uint8_t *)EEP_ADRESS_MIN) * 60) + eeprom_read_byte((uint8_t *)EEP_ADRESS_SEC);
time2display();
}
void eeprom_write(void)
{
uint8_t minuten, sekunden;
minuten = time / 60; //Zeit wird in Minuten und Sekunden Zerlegt
sekunden = time % 60;
if(minuten != eeprom_read_byte((uint8_t *)EEP_ADRESS_MIN)) //Zuerst wird der EEPROM ausgelesen
eeprom_write_byte((uint8_t *)EEP_ADRESS_MIN, minuten); //Falls die Werte nicht übereinstimmen,
//wird der EEPROM neu beschrieben
if(sekunden != eeprom_read_byte((uint8_t *)EEP_ADRESS_SEC))
eeprom_write_byte((uint8_t *)EEP_ADRESS_SEC, sekunden);
}
void init(void)
{
DDRA = 0xFF; //PORTA als Ausgang
DDRB = 0x0F; //PORTB 0 - 3 als Ausgang, 4 - 6 als Eingang
PORTB = 0x70; //Aktiver die Pullups an PB4, PB5, PB6
position = 0;
eeprom_read();
timer_init();
counter = 0;
counter_1sec = 0;
timer_1sec = TIMER_1SEC_DISABLED; //Deaktiviere die 1sec ISR
counter_1sec = 0;
}
void update_display(void)
{
position++;
if(position > 3)
position = 0;
TASTER_TRANSPORT = active_position[position] | 0x70;
LEDPORT = symbol[segment[position]];
}
ISR(TIMER1_CMPA_vect)
{
static uint8_t ct0, ct1, rpt;
uint8_t i;
counter++;
if(counter == 5) //5ms
{
//Debounceroutine von Peter Danegger
i = key_state ^ ~KEY_PIN; // 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
if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
rpt = REPEAT_START; // start delay
if( --rpt == 0 )
{
rpt = REPEAT_NEXT; // repeat delay
key_rpt |= key_state & REPEAT_MASK;
}
counter = 0;
counter_1sec++;
if(time > 0)
time2display();
update_display();
if((counter_1sec == 200) && (timer_1sec == TIMER_1SEC_ENABLED)) //1sec ISR
{
counter_1sec = 0;
time--;
time2display();
if(time == 0)
{
RELAISPORT &= ~(1 << RELAISPIN); //Switsch OFF Relais
done = DONE;
segment[0] = _D; //"DONE"
segment[1] = _O;
segment[2] = _N;
segment[3] = _E;
timer_1sec = TIMER_1SEC_DISABLED; //Disable 1sec interrupt
}
}
}
}
uint8_t get_key_press(uint8_t 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;
}
uint8_t get_key_rpt(uint8_t 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;
}
uint8_t get_key_short(uint8_t key_mask)
{
cli(); // read key state and key press atomic !
return get_key_press( ~key_state & key_mask );
}
uint8_t get_key_long(uint8_t key_mask)
{
return get_key_press( get_key_rpt( key_mask ));
}
void tastenauswertung(void)
{
if(done == DONE && (get_key_press(1 << KEY0) || get_key_press(1 << KEY1) || get_key_press(1 << KEY2)))
{
done = UNDONE;
init();
}
if(get_key_press(1 << KEY2)) //START
{
RELAISPORT |= (1 << RELAISPIN); //Switsch On Relais
eeprom_write();
timer_1sec = TIMER_1SEC_ENABLED;
}
if(get_key_rpt(1 << KEY0) && get_key_rpt(1 << KEY1) && timer_1sec == TIMER_1SEC_ENABLED)
init();
if(get_key_rpt(1 << KEY0) && time > 0 && timer_1sec != TIMER_1SEC_ENABLED)
time--;
if(get_key_press(1 << KEY0) && time > 0 && timer_1sec != TIMER_1SEC_ENABLED)
time--;
if(get_key_rpt(1 << KEY1) && time < 3600 && timer_1sec != TIMER_1SEC_ENABLED) //1 Stunde
time++;
if(get_key_press(1 << KEY1) && time < 3600 && timer_1sec != TIMER_1SEC_ENABLED) //1 STunde
time++;
}
int main(void)
{
init();
sei();
time2display();
while(1)
{
tastenauswertung();
}
}
Warum ist denn das so??
Ich hoffe es kann mir helfen
Gruß Robert
Bei meinem Gesichtsbräunertimer hab ich noch ein paar Probleme.
Doch leider funktioniert noch nicht alles ganz zuverlässig. Am Auslesen
des EEproms happerts noch ein bisschen. Woran kann das liegen??
Und was mir noch aufgefallen ist, wenn ich KEY0 gedrückt halte, dann
zählt er viel langsamer die Variable time herunter als wenn ich KEY1
gedrückt halte und er nach oben zählt.
Hier mal der Source Code:
/*******************************************
Title: Belichtungstimer
Author: Robert Schilling
Date: 9.8.2006
Hardware: Atiny26 + Board
********************************************/
#include <avr/io.h>
#include <stdlib.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#define LEDPORT PORTA
#define LED_A PA0
#define LED_B PA1
#define LED_C PA2
#define LED_D PA3
#define LED_E PA4
#define LED_F PA5
#define LED_G PA6
#define RELAISPORT PORTA
#define RELAISPIN PA7
#define TASTER_TRANSPORT PORTB
#define KEY_PIN PINB
#define KEY0 4
#define KEY1 5
#define KEY2 6
#define REPEAT_MASK (1<<KEY0^1<<KEY1^1<<KEY2) // repeat: key1, key2
#define REPEAT_START 50 // after 500ms
#define REPEAT_NEXT 20 // every 200ms
#define EEP_ADRESS_MIN 0x01
#define EEP_ADRESS_SEC 0x02
#define DONE 0x01
#define UNDONE 0x00
#define TIMER_1SEC_ENABLED 0x01
#define TIMER_1SEC_DISABLED 0x00
#define _D 0x0B
#define _O 0x0C
#define _N 0x0D
#define _E 0x0E
const uint8_t symbol[]={0x3F, //0
0x05, //1
0x5B, //2
0x4F, //3
0x65, //4
0x6E, //4
0x7E, //5
0x07, //6
0xFF, //7
0x6F, //8
0x08, //9
0x5D, //d
0x5C, //o
0x54, //n
0x7A}; //E
const uint8_t active_position[] = {0x78,
0x74,
0x72,
0x71};
uint8_t segment[4];
uint8_t position;
volatile uint16_t time = 0;
volatile uint8_t done = UNDONE;
volatile uint8_t counter;
volatile uint8_t timer_1sec = TIMER_1SEC_DISABLED;
volatile uint8_t counter_1sec = 0;
uint8_t key_state; // debounced and inverted key state:
// bit = 1: key pressed
uint8_t key_press; // key press detect
uint8_t key_rpt; // key long press and repeat
void time2dispay(void);
void eeprom_read(void);
void eeprom_write(void);
void init(void);
void update_display(void);
void timer_init(void);
uint8_t get_key_press(uint8_t key_mask);
uint8_t get_key_rpt(uint8_t key_mask);
uint8_t get_key_short(uint8_t key_mask);
uint8_t get_key_long(uint8_t key_mask);
void timer_init(void)
{
TCCR1B = ((1 << CS12) | (1 << CS11) | (1 << CTC1)); //Prescaler = 32; Enabale CTC Mode
OCR1C = 0xFA; //Compare Interrupt at 250
TIMSK |= (1 << OCIE1A);
}
void time2display(void) //ZEit wird zerlegt in die einzelnen Ziffern
{
uint16_t rest;
segment[0] = time / 600;
rest = time % 600;
segment[1] = rest / 60;
rest %= 60;
segment[2] = rest / 10;
rest %= 10;
segment[3] = rest;
}
void eeprom_read(void) //EEProm wird ausgelesen und Zeit wird berechnet
{
time = (eeprom_read_byte((uint8_t *)EEP_ADRESS_MIN) * 60) + eeprom_read_byte((uint8_t *)EEP_ADRESS_SEC);
time2display();
}
void eeprom_write(void)
{
uint8_t minuten, sekunden;
minuten = time / 60; //Zeit wird in Minuten und Sekunden Zerlegt
sekunden = time % 60;
if(minuten != eeprom_read_byte((uint8_t *)EEP_ADRESS_MIN)) //Zuerst wird der EEPROM ausgelesen
eeprom_write_byte((uint8_t *)EEP_ADRESS_MIN, minuten); //Falls die Werte nicht übereinstimmen,
//wird der EEPROM neu beschrieben
if(sekunden != eeprom_read_byte((uint8_t *)EEP_ADRESS_SEC))
eeprom_write_byte((uint8_t *)EEP_ADRESS_SEC, sekunden);
}
void init(void)
{
DDRA = 0xFF; //PORTA als Ausgang
DDRB = 0x0F; //PORTB 0 - 3 als Ausgang, 4 - 6 als Eingang
PORTB = 0x70; //Aktiver die Pullups an PB4, PB5, PB6
position = 0;
eeprom_read();
timer_init();
counter = 0;
counter_1sec = 0;
timer_1sec = TIMER_1SEC_DISABLED; //Deaktiviere die 1sec ISR
counter_1sec = 0;
}
void update_display(void)
{
position++;
if(position > 3)
position = 0;
TASTER_TRANSPORT = active_position[position] | 0x70;
LEDPORT = symbol[segment[position]];
}
ISR(TIMER1_CMPA_vect)
{
static uint8_t ct0, ct1, rpt;
uint8_t i;
counter++;
if(counter == 5) //5ms
{
//Debounceroutine von Peter Danegger
i = key_state ^ ~KEY_PIN; // 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
if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
rpt = REPEAT_START; // start delay
if( --rpt == 0 )
{
rpt = REPEAT_NEXT; // repeat delay
key_rpt |= key_state & REPEAT_MASK;
}
counter = 0;
counter_1sec++;
if(time > 0)
time2display();
update_display();
if((counter_1sec == 200) && (timer_1sec == TIMER_1SEC_ENABLED)) //1sec ISR
{
counter_1sec = 0;
time--;
time2display();
if(time == 0)
{
RELAISPORT &= ~(1 << RELAISPIN); //Switsch OFF Relais
done = DONE;
segment[0] = _D; //"DONE"
segment[1] = _O;
segment[2] = _N;
segment[3] = _E;
timer_1sec = TIMER_1SEC_DISABLED; //Disable 1sec interrupt
}
}
}
}
uint8_t get_key_press(uint8_t 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;
}
uint8_t get_key_rpt(uint8_t 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;
}
uint8_t get_key_short(uint8_t key_mask)
{
cli(); // read key state and key press atomic !
return get_key_press( ~key_state & key_mask );
}
uint8_t get_key_long(uint8_t key_mask)
{
return get_key_press( get_key_rpt( key_mask ));
}
void tastenauswertung(void)
{
if(done == DONE && (get_key_press(1 << KEY0) || get_key_press(1 << KEY1) || get_key_press(1 << KEY2)))
{
done = UNDONE;
init();
}
if(get_key_press(1 << KEY2)) //START
{
RELAISPORT |= (1 << RELAISPIN); //Switsch On Relais
eeprom_write();
timer_1sec = TIMER_1SEC_ENABLED;
}
if(get_key_rpt(1 << KEY0) && get_key_rpt(1 << KEY1) && timer_1sec == TIMER_1SEC_ENABLED)
init();
if(get_key_rpt(1 << KEY0) && time > 0 && timer_1sec != TIMER_1SEC_ENABLED)
time--;
if(get_key_press(1 << KEY0) && time > 0 && timer_1sec != TIMER_1SEC_ENABLED)
time--;
if(get_key_rpt(1 << KEY1) && time < 3600 && timer_1sec != TIMER_1SEC_ENABLED) //1 Stunde
time++;
if(get_key_press(1 << KEY1) && time < 3600 && timer_1sec != TIMER_1SEC_ENABLED) //1 STunde
time++;
}
int main(void)
{
init();
sei();
time2display();
while(1)
{
tastenauswertung();
}
}
Warum ist denn das so??
Ich hoffe es kann mir helfen
Gruß Robert