PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RTC / Binär Uhr



AVR-Troll
18.03.2007, 09:44
Hi,

ich bin neu hier. Euer Forum ist echt Klasse ich konnte schon viele Probleme mit euere Hilfe lösen. Doch nun find ich keine Lösung meines Problems.
Ich möchte mir eine Binäre Uhr bauen doch leider funktiont es nicht wie es soll.

Ich habe ein 32,???? Khz Uhren-Quarz an TOSC1 & TOSC2 meines Atmega16 angeschlossen.

Mein CODE .. kommentiert ..:

/* this program uses a external 32.768 khz Quarz on TOSC1 and TOSC2
to archieve a 1 Hz Signal for time measurement.
PORTD will be inverted in the interrupt routine.
*/

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

volatile uint16_t seconds;
volatile uint8_t minutes;
volatile uint8_t hours;
uint8_t i,j;

void display_first_array(uint8_t);
void display_second_array(uint8_t);

// Timer2 (autom. Aufruf 1/s)
INTERRUPT(SIG_OVERFLOW2)
{
seconds++;
if (i==0)
{
PORTB+=16;
i++;
return;
}

if (i==1)
{
PORTB-=16;
i--;
}
}

void initialize(void)
{
seconds=0;
minutes=0;
hours=0;

DDRA = 0;
PORTA = 0;

DDRC = 0;
PORTC = 0;

//first port for the LEDS
DDRB=255;
PORTB=0;

//second Port for the LEDS
DDRD = 255;
PORTD = 0;


// initialise Timer2 for time measurement
// (asynchron driven by a 32.768 kHz quartz)
TIMSK &=~((1<<TOIE2)|(1<<OCIE2)); // disable TC2 interrupt
ASSR |= (1<<AS2); // Timer/Counter2 asynchron with quartz 32,768kHz
TCNT2 = 0x00; // initial value for Timer2
TCCR2 = 0x05; // divide ck/128
while(ASSR & 0x07); // wait until ASSR is written
TIMSK |= (1<<TOIE2); // enable interrupt

sei();
}



int main() {

initialize();


while(1)
{

if (seconds==60)
{
PORTD=++minutes;
seconds=0;
}

if (minutes==60)
{
PORTB=++hours;
minutes=0;
}

if (hours==12)
{
hours=0;
}



}
}

Doch leider klappt es nicht [-( warum ?? weis jemand was??

Gruß

Stephan

SprinterSB
18.03.2007, 10:08
Was auf jeden Fall fehlt ist einige Zugriffe atomar zu machen.

Schau mal in folgendem Artikel, der Artikel ist noch Baustelle, aber es sind ein paar Links drin, die zu dem Thema was sagen.

https://www.roboternetz.de/wissen/index.php/C-Tutorial/Interrupt-Programmierung

In deinem Fall wäre das einfachste so was wie ein yield() in der Hauptschleife:


// yield();
sei();
nop();
cli();

Es gibt also nur einen definierten Punkt im Programm, wo eine IRQ ausgelöst werden kann. Dadurch werden Konflikte vermieden, weil sonst "gleichzeitig" auf PORTB und seconds zugegriffen wird.

Allerdings glaub ich net, daß das der Grund ist, warum es überhaupt nicht funktioniert...

Muss man da nicht Fuses setzen?

Und der Test auf ASSR muss *vor* dem Setzen neuer Werte gemacht werden.

Ausserdem kannst du in der ISR einfach hinschreiben


PORTB ^= 16;