PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] ATmega32 PORTC



SpeedSebi
05.08.2014, 17:38
Ich habe laut Programm auf PORTC 2 low. Bei mir fließen da aber trotzdem 1,2 Volt

Bräuchte eure Hilfe.
Danke im vorraus!

MfG
Sebi

wkrug
05.08.2014, 18:36
Nutzt Du JTAG?
Wenn nein, dann deaktiviere doch mal die JTAGEN Fuse.
JTAG benutzt Port's von C

SpeedSebi
06.08.2014, 10:07
Vielen Dank für die Antwort. Funktioniert alles!

Jetzt hab ich aber das Problem, dass meine Uhr (die auf dem ATmega32 läuft) bereits nach 21 Sekunden um eine 0,25 Sekunden vor geht.

oberallgeier
06.08.2014, 10:23
... Uhr (die auf dem ATmega32 läuft) bereits nach 21 Sekunden um eine 0,25 Sekunden vor geht.Kenn ich. Weil ich in meiner Anfangszeit (und schlampigerweise immer noch) den Timer bei 125 notwendigen Schritten auf diese "125" setzte - ohne dran zu denken, dass der bei Null zu zählen anfängt.

SpeedSebi
06.08.2014, 10:42
Also sollte ich:
Timer1an:
TIMER1 = 49911
...
TIMER1 = 0
Return

Machen?

wkrug
06.08.2014, 16:00
Teste Deine Routine mit dem Simulator vom AVR Studio 4 bzw. 5.
Wenn die Stoppclock Zeit da stimmt, liegts an deinem Takt.
Wenn da auch fehlerhafte Zeiten gemessen werden liegts an deinem Code.

SpeedSebi
06.08.2014, 19:20
Ich werde es morgen mal testen :)

SpeedSebi
07.08.2014, 13:31
Kenn ich. Weil ich in meiner Anfangszeit (und schlampigerweise immer noch) den Timer bei 125 notwendigen Schritten auf diese "125" setzte - ohne dran zu denken, dass der bei Null zu zählen anfängt.

Wenn du doch das selbe Problem hattest könnte ich mal deinen Code sehen?

oberallgeier
07.08.2014, 14:01
Wenn du doch das selbe Problem hattest könnte ich mal deinen Code sehen?Könnte ich mal raussuchen - ABER das ist C - nicht Bascom. Da glaube ich, dass Dir das nix nutzen wird.

Mal auf die Schnelle gefunden:
/* >>
Sicherung 05Nov08 1800 ...C2..\SRV_tstr168\SRV168_tmr_x00.c ###>>> noch nicht
================================================== =================================
Target MCU : siehe main (ATmega328p)
Target Hardware : siehe main
Target cpu-frequ. : siehe main (In der Quelle wählbar, 20 MHz)
================================================== =================================
Enthaltene Routinen: Timer und Stoppuhr
void TC1TMR_init(void) // Init Timer/Counter 1 für 20 ms/1-2ms Servosignal
void servon(void) // Servosignal einschalten, erlauben
void servoff(void) // Servosignal ausschalten, Verbieten
ISR(TIMER1_COMPA_vect) // VECTOR 11
void TC2TMR_init(void)
ISR(TIMER2_COMPA_vect)
void waitms(uint16_t ms)
void stoppuhr(void) // Stoppuhrfunktion ###>>> übernommen v main-modul
================================================== =================================
*** Versionsgeschichte:
====================
x00 04Nov08 1800 Übernahme des Originals
================================================== =================================
*** Aufgabenstellung : Timer für 16-bit-Servo
==========================================
Original: ...C2..\SRV_tstr168\SRV168_tmr_x00.c 04Nov08 2040
================================================== ============================== */


/* ================================================== ============================ */
// == Routine wurde übernommen aus m168d_dme_10x80.c.
// Aufgabe: Servo mit Soft-PWM ansteuern auf wählbarem Port
void TC1TMR_init(void) // Init Timer/Counter 1 für 20 ms/1-2ms Servosignal
{
TCCR1B |= (1<<CS11); // CS11 <=> clk/8 => Frequenz 2,5 MHz doc S134
TCCR1B |= (1<<WGM12); // WGM12 => CTC, TOP = OCR1A doc S133
TIMSK1 &= ~(1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt disab
}
// ================================================== ===============================
// ================================================== ===============================

/* ================================================== ============================ */
/* === Nicht unterbrechbare ISR für TIMER1_COMPA_vect VECTOR(11) ============ */
// ISRoutine beendet den Interrupt <<< das läuft nicht 05Nov08 - spät nachts, daher
// ==>> ISR schaltet den Servopin aus.
ISR(TIMER1_COMPA_vect) // VECTOR 11
{
// SrvPORT ^= (1<<SrvPIN); // LED auf SrvPORT (SrvPIN) toggeln
// TIMSK1 &= ~(1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt disab
SrvPORT &= ~(1<<SrvPIN); // SrvPIN ausschalten
}
/* ================================================== ============================ */
/* ================================================== ============================ */


/* ================================================== ============================ */
/* === Initialisierung fuer Timer2 mega168 =================================== */
void TC2TMR_init(void) // Init Tmr/Cntr2, 8-Bit auf 20 kHz = 50 µs
{
TCCR2A |= (1<<WGM21); // Timer im CTC-Mode, Top=OCR2A doc S 157
TCCR2B |= (1<<CS21); // Prescaler 1/8 / Clock <- CPU doc S 158
OCR2A = 124; // Preset 124 für 50µs bei 20Mhz
TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled
}
/* ================================================== ============================ */


/* ================================================== ============================ */
/* === Nicht unterbrechbare ISR für timer2 ===================================== */
/* Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR für
EXT_INT0 und -INT1 ausgelesen und den Werten Iz_yseci zugewiesen ...... */
// In der LCD-Fassung wird (erstmal) nach 20 ms das Servosignal gesetzt WENN
// Servo enabled ist - - - - so ungefähr
ISR(TIMER2_COMPA_vect) // Vektor 7
{
if (Izeit_1 < Izthrznt) //Interrupt-Timer = 20 000 ... (1 sec blink)
{
Izeit_1 ++; // war: alle Izthrznt Sekunden wird Ende erreicht
} // und Izeit_1 bleibt in der uint16-Grenze
else
{
PORTC ^= (1<<PC5); // LED auf Port PC5 toggeln
Izeit_1 = 0; // ansonsten: Rückstellen auf Null
icntsec = icntsec + 1; // Countdown-Sekundenzähler hoch(!!)zählen
if (icntsec == 43201) // Countdownzähler geht maximal 12 Std. + 1 sec
icntsec = 0;
}

// Es folgt die Servoroutine. Der Servo wird mit der Variablen Isvs1 gesteuert:
// Servocounter läuft hoch von 1 .. 400.
// Wenn 400 erreicht ist, wird wieder 1 gesetzt.
//
if (Srv_flg == 8) // Servo läuft nur, wenn flag == 8
{
// ############ Test Anfang:
PORTC ^= (1<<PC4); // LED auf PC4 toggeln als Nachweis für Servolauf
// .. das ist nur zu Testzwecken
// ############ Test Ende

if (Srv_cnt < 400) //Servo-Counter läuft von 1 .. 400
{ // 400 * 0,050 ms => 20 ms.
Srv_cnt ++;
}
else // Servo-Timer hat Ende=400 erreicht, daher
{
OCR1A = Srv_rmp;
TIMSK1 |= (1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt enabled
Srv_cnt = 1; // Servocounter zurückstellen auf Null und
SrvPORT |= (1<<SrvPIN); // SrvPIN einschalten
}

if (Srv_cnt == 100) //Servo-Counter = 100 <=> schalte TC1 OCM disabl
{ //
TIMSK1 &= ~(1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt disab
}

}
else
{
TIMSK1 &= ~(1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt disab
SrvPORT &= ~(1<<SrvPIN); // SrvPIN ausschalten
}
}
/* ================================================== ============================ */


/* ================================================== ============================ */
/* ================================================== ============================ */
/*### Programm pausieren lassen !! Der Pausenwert ist nur experimentell !*/

void waitms(uint16_t ms)
{
for(; ms>0; ms--)
{
uint16_t __c = 4000;
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__c)
: "0" (__c)
);
}
}
/* ================================================== ============================ */


// ================================================== ===============================
void stoppuhr(void) // Stoppuhrfunktion #####>>>>> steht IMMER im main-modul
{
// PORTC |= (1<<PC4); // LED auf PC4/I2C/SCA einschalten
// PORTC &= ~(1<<PC4); // LED auf Port PC4/I2C/SCA ausschalten
// PORTC ^= (1<<PC4); // LED auf Port PC4/I2C/SCA toggeln

uart_puts ("\r\tBeginn Routine Stoppuhr\r\n");
waitms(3000);
PORTC |= (1<<PC4); // LED auf PC4/I2C/SCA einschalten
PORTC &= ~(1<<PC4); // LED auf Port PC4/I2C/SCA ausschalten
waitms(2000);
////////////// Wartezeit bis zum Start = Vorstartphase
cli();
// Setzen der Variablen für die Stoppuhrfunktion
icntsec = 0; // Starte den Countdown-Sekundenzähler mit 0
// ###>>> damit die Zählung genau stimmt.
Izeit_1 = 0; // Beginne mit einer GANZEN Sekunde
icdwvor = 2; // Vorwarnung mit x sec vor Ablauf
icdwmax = 5; // icdwmax = Laufzeit des Countdowns in sec
// icdwmax = 36000; // icdwmax = Laufzeit des Countdowns in sec
// bei "1200" sind das 20 min
// 3600 sind 1 Std
// 28800 sind 8 Std
// 32400 sind 9 Std

// Jetzt wird weiter geblinkt so lange, bis der Eingang PB4 auf GND ist
while (1)
{
if (!( PINB & (1<<PINB5))) // mache was, wenn Pin SCK low ist
break; // "Durchschalten" wenn PinB5 auf GND
else
{
setportcon(5); // Hellphase NUR waitms >> 1 <<
waitms(1); // ... damit erkennt man diese Wartephase
setportcoff(5); // Dunkelphase. Loop endet mit Dunkelphase
waitms(99);
} // Ende if
} // Ende while (1)

// Es wurde ein Tastendruck auf PinB4 erkannt ==> Tastenabfrage beenden und
// so schnell wie möglich mit der Timerroutine beginnen
// Bis hierher sind KEINE Interrupts erlaubt

PORTC |= (1<<PC5); // Hellphase auf PC5 als Kennzeichen, dass die
// Vorstartphase abgelaufen ist
PORTC |= (1<<PC4); // LED auf PC4/I2C/SCA einschalten
PORTC |= (1<<PC3); // LED auf PC3 einschalten
sei();

while (1) //
{
// if (icntsec >= icdwmax) // Countdown läuft bis icdwmax sec
if (icntsec == icdwmax) // Countdown läuft bis icdwmax sec
{
PORTC &= ~(1<<PC4); // LED auf Port PC4/I2C/SCA ausschalten
break; // .. dann brich die Schleife ab
}

// if (icntsec >= (icdwmax-icdwvor)) // Vorwarnung !
if (icntsec == (icdwmax-icdwvor)) // Vorwarnung !
PORTC &= ~(1<<PC3); // LED auf Port PC3 ausschalten
} // Ende while (1)

waitms (5);
uart_puts ("\r\tStoppuhr abgelaufen\r\n");
lcd_i_02 ();
waitms (5000);

}
/* ================================================== ============================ */


/* ================================================== ============================ */
/* ===== ENDE Subroutinen ================================================== */
/* ================================================== ============================ */

SpeedSebi
07.08.2014, 16:01
Ich hab jetzt eine externe Frequenz von 4,194304 MHz (2^22 Hz), 16 bit Zähler und einem Vorteiler von 64 (2^6). Zack ... einfach und genau (naja ± 2 Sek.) ;)

oberallgeier
07.08.2014, 16:12
Ich hab jetzt eine externe Frequenz von 4,194304 MHz ... einfach und genau Klasse! Gut gemacht. UND Du weißt, warum es Quarze mit so seltsam krummen Frequenzen gibt ;.-.)

SpeedSebi
08.08.2014, 06:01
Eigentlich sollte man aus den "krummen" Zahlen die Baud-Raten rausteilen oder?

oberallgeier
08.08.2014, 07:38
Eigentlich sollte man aus den "krummen" Zahlen die Baud-Raten rausteilen oder?Genau, das gibt die Baudratenquarze. Ist hier gut erläutert (http://www.mikrocontroller.net/articles/Baudratenquarz) , siehe vor allem die "Mathematische Betrachtung" und ne hübsche Tabelle dieser "krummen", in Wahrheit aber immer geraden, Werte der Baudratenquarze ist hier. (http://www.hanneslux.de/avr/tipps/baudratenquarz.html)