PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C Bitte um Hilfe bei for-Schleife



oberallgeier
17.08.2016, 11:03
Hallo Alle.

Umgebung:
Win10-pro, AtmelStudio7 (Version: 7.0.1006), Nanoclone 20 MHz.

Ein peinlicher, versteckter? Programmierfehler macht mir zu schaffen. Verschiedene Änderungen bringen keine Hilfe
Folgender Code soll per HardwarePWM am Pin PB3/OC2A bei meinem bereits mehrfach erfolgreich benutzten Nanoclone die LED mit fade-in und fade-out leuchten lassen. Die Schleife zum fade-in bringt das weiche Aufleuchten der LED, die unmittelbar folgende for-Schleife hält das programmierte delay ein, aber die LED leuchtet hier überhaupt nicht. Ich sehe keinen Fehler :-/ und bitte um Hilfe.


/* >>
Stand ...\.._LED-PWM_02-1\main.c
================================================== ============================= =
Target MCU : ATmega 328P TQFP
Target Hardware : arduino nano von paradisetronic
Target cpu-frequ. : 20 MHz Resonator (War 16 MHz Resonator bis 18-07-2016)
================================================== ============================ */
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#define F_CPU 16000000UL

// ATMEL-Standard-Bibliotheken
#include <avr/io.h>
#include <util/delay.h>

//--------------------------------------------------------------
// Globale variable
uint8_t i;

//--------------------------------------------------------------
// Funktionsprototypen
void PWM_Counter2(void); //ohne Rückgabewert

// === HAUPTProgramm ================================================== ======== =
int main ( void )
{ //
DDRB = 0b00101001; // Ausgänge PB0, PB3/OC2A, PB5
PORTB = 0b11010110; // + Port/Pull Ups (1) aktivieren für unbenutzte Eingänge
DDRD = 0b11000000; // Ausgänge PD6 und PD7
PORTD = 0b00111111; // Pull Ups siehe oben

// - - - - - - - - - - - - - - -
PWM_Counter2(); // Timer 2 initialisieren
//
while(1)
{
for( i=0; i<200; i++) // for-Schleife 1. Compare Match Register wird
// mit jedem Schleifendurchlauf inkrementiert
{
OCR2A = i; // OCR2A
_delay_ms( 5);
}

for( i=200; i>0; i--) // for-Schleife 2
{
OCR2A = i;
_delay_ms( 5);
}

} // Ende while (1)

return 0; // Ende des Hauptprogramms
}

//--------------------------------------------------------------------------------
// Funktionsdefinitionen
// ================================================== =========================== =
// == Aufgabe: Timer2A für LED-PWM auf Port OC2A/PB3 initialisieren
// Es wird also die >>Hardware-PWM<< benutzt, hier auf OCR2A/PB3.
// Dokumentation Atmel-8271J-AVR- ATmega-Datasheet_11/2015
// - - - - - - - - - - - - - - - -
void PWM_Counter2 (void) // Initialisiere TimerCounter 2 A
{
TCCR2A |= (1<<COM2A1)|(1<<COM2A0);
// Set OC2A on Compare Match, clear OC2A at BOTTOM
TCCR2A |= (1<<WGM20); // PWM Phase Correct, Mode 5, Teil 1
TCCR2B |= (1<<WGM22); // PWM Phase Correct, Mode 5, Teil 2
//
TCCR2B |= (1<<CS21); // clk/8 (From prescaler)
// 16 MHz / 8 => 2 MHz, 1 tick sind dann 0,5 µs
// 200 tick sind 50 µs, ==> Leuchtdauer der LED
// bei OCR2A "200" und delay 5 mit ED 10 %

OCR2A =200; // Initialisieren OCR2A Anm: nicht nötig


TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled

}

Ceos
17.08.2016, 11:37
was für ein verwendeter Controller exakt? (Ich muss das Datenblatt dazu in der Hand haben)
Warum Phase Correct Mode bzw. welche TOP Wert ist konfiguriert? (Ohne DAtenblatt weis ich das nciht aus dem Kopf)
Meine Vermutung, er zählt mit 16Bit = 65535 und 200/65535 = 0.3%

Aber das ist nur n Schuss ins blaue :D

wait wait wait .... warum schaltest du den interrupt ein? Hast du denn auch eine Interrupt Routine? Sonst schmiert er dabei immer ab!

oberallgeier
17.08.2016, 12:40
was für ein verwendeter Controller exakt? ..Au weh, tut mir leid. Es ist ein nano328p/TQFP AU 1511 (ATmega328-P_Atmel-42735A_Datasheet_Complete-06-2016 (http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf)) verbaut, den originalen 16MHz-Resonator hatte ich durch einen baugleichen 20 MHz-Typ ersetzt.


.. Warum Phase Correct Mode bzw. welche TOP Wert ist konfiguriert? ..Das ist ein selbsterstelltes Programm (Studentenübung), das mir zur Fehlersuche vorgelegt wurde. TOP ist OCRA, siehe Datenblatt, Seite 205, waveform Mode 5.


.. Meine Vermutung, er zählt mit 16Bit = 65535 und 200/65535 = 0.3% ..Es ist Timer2, bei den megas immer? 8bittig; der 16bittige Timer ist immer? Timer1.


.. wait wait wait .... warum schaltest du den interrupt ein? Hast du denn auch eine Interrupt Routine? Sonst schmiert er dabei immer ab!Das wait soll die isochrone Phase der PWM dimensionieren - ohne zweiten Timer. Wie erwähnt, ein Anfängerversuch.


.. Hast du denn auch eine Interrupt Routine? Sonst schmiert er dabei immer ab!Nein, der Interrupt wurde im vorgelegten Programm nicht mal in der Timerinitialisierung erlaubt/freigegeben. Ich bin selbst überrascht, dass weder die Interruptlibrary #include <avr/interrupt.h> benutzt werden muss, noch muss der Interrupt global freigegeben werden, nur lokal in der Timerinitialisierung. Bei global freigegebenem Interrupt muss notwendigerweise zusätzlich noch die ISR ISR (TIMER2_COMPA_vect) erstellt sein, wenn auch nur als leere Funktion. (Ja ja, das klingt auch bei mir nach experimentellem Software-Engineering, aber mein C ist ja noch sehr rudimentär).

Ceos
17.08.2016, 13:10
"wait wait wait" war nur ein ausruf, keine Frage XD

das Flag für den Interrupt ist Teil eines Registers, beschrieben in der IO.h du musst interrupt.h nicht zwingend laden für das Flag ... Wenn du keine ISR angelegt hast, springt er an die Vektroadresse, bekommt eine schöne 0xf slide serviert und landet irgendwo, nur nicht da wo er hingehört!

Daher als Grundregel, niemals einen Interrupt zu aktiviern bevor man nicht doppel/dreifach gecheckt hat dass man den (RICHTIGEN) Vektor auch implementiert hat ... udn wenn nur ein gammeliges NOP() drin steht :)

Was die Timer angeht .. ich hab zu viele Controllerdatenblätter gelesen als dass ich 100% sicher sein könnte welcher Timer wie tickt ohne gezielt nachzuschlagen XD

Zum Thema: dein programmierter Modus ist Phase Correct mit OCRA2 als TOP Register (WGM22|20) und compare up active (COM1|0) bei Output A ... das wiederspricht sich ... wenn du dein OCR2A in der Schleife updatest, veränderst du die Frequenz, denn dein TOP WErt entspricht immer OCR2A! Du müsstest schon OCR2B und den entsprechenden Pin benutzen damit das klappen kann XD

ist mir aber auch erst klar geworden als ich die WGM Tabelle vor mir hatte

und dennoch wäre ich dafür ein normales Fast PWM mit festem TOP von 0xFF zu benutzen, weil man dann eben nicht diese Problem hat :D

oberallgeier
17.08.2016, 16:08
.. Du müsstest schon OCR2B und den entsprechenden Pin benutzen damit das klappen kann XD
ist mir aber auch erst klar geworden als ich die WGM Tabelle vor mir hatte
und dennoch wäre ich dafür ein normales Fast PWM mit festem TOP von 0xFF zu benutzen, weil man dann eben nicht diese Problem hat :DJaaa, danke. Das war mir nicht klar/bewusst geworden. Aber es stimmt. Prima.
Ja, ich nehme eigentlich nur CTC oder fast PWM. Die phase correct PWM war mir irgendwie zu meiner Atmel-Anfangszeit undurchsichtig vorgekommen, hatte ich nie benutzt/benötigt. Das ursprüngliche Programm ist, wie gesagt, das Oevre eines (andern) Anfängers.

Danke, jetzt läufts wirklich und vorstellungsgemäß.