Forum: Mikrocontroller und Digitale Elektronik ATMega16 Fast PWM


von Michael K. (mmike)


Lesenswert?

Hallo Leute,
Ich arbeit mit einem ATMega16 und will den Timer1 im FastPWM betreiben. 
Ich habs auch schon mit simulieren probiert, aber leider ohne Erfolg. 
Die Init Funktion sieht folgendermassen aus:

void EnableServoTestTimer ()
{
  // External crystal 16 MHz, Prescaler 8
  // Enable fast PWM mode 14 (table 47 page 113 ATMega16 Doc):
  TCCR1A    = (1 << COM1A1) |(1 << WGM11);
  // Set prescaler 8
  TCCR1B    = (1 << CS11) | (1 << WGM13) | (1 << WGM12);
  // Set PWM
  ICR1     = (uint16_t)40000;
  OCR1A    = (uint16_t)3000; // min: 1800, neu.: 3000 max: 4200
}

Der Port PD5 ist als Ausgang geschaltet und wenn ich per "Hand" den Pin 
PD5 toggle, dann funzt es auch wunderbar. Nur wenn ich die Funktion zum 
initialisieren verwende, dann tut sich am Scope leider gar nichts.

Vielleicht sieht jemand den Fehler ....

Grüße,
Michael

von Jörg X. (Gast)


Lesenswert?

Der (richtige) Pin ist auf Ausgang geschaltet?
 Probier mal:
> ICR1     = 40000U; // U fuer unsigned weil >32767,
                     // und/oder L fuer Long/32Bit
statt
> ICR1     = (uint16_t)40000;

hth. Jörg

von Michael K. (Gast)


Lesenswert?

Hallo Jörg,
danke für die schnelle Antwort! Der Pin ist definitiv auf Ausgang (wie 
geschrieben) und Pin toggeln funktioniert auch wunderbar. Dein Vorschlag 
mit dem U bzw. L brachte leider auch keine Abhilfe ... gecast'ed wird ja 
eigentlich ....
Vielleicht noch andere Ideen ?
Grüße,
Michael

von Jörg X. (Gast)


Lesenswert?

>> Vielleicht noch andere Ideen ?
Ich sag's mal so: An dem Programm, das du bisher gepostet hast liegt's 
höchstwahrscheinlich nicht ;) (ich kann's nur simulieren, wobei die 
Timer nun mal nicht gehen).

Also: poste mehr Code!
und kürz den Code auf ein Minimum (so ungefähr):
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
void EnableServoTestTimer(void);
5
6
int main(void)
7
{
8
  DDRD |= (1<<DDD5);
9
  EnableServoTestTimer();
10
  
11
  while(1)
12
    ;
13
  return 0;
14
}
15
16
17
void EnableServoTestTimer ()
18
{
19
  // External crystal 16 MHz, Prescaler 8
20
  // Enable fast PWM mode 14 (table 47 page 113 ATMega16 Doc):
21
  TCCR1A    = (1 << COM1A1) |(1 << WGM11);
22
  // Set prescaler 8
23
  TCCR1B    = (1 << CS10) | (1 << WGM13) | (1 << WGM12);
24
  // Set PWM
25
  ICR1     = 100;
26
  OCR1A    = 50; // min: 1800, neu.: 3000 max: 4200
27
}

hth. Jörg

von Michael K. (Gast)


Lesenswert?

Hallo Jörg,

ziemlich genau so sieht mein Code auch aus:

// Standard includes
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>

/*********************************************************************** 
*************************************/
void EnableServoTestTimer ()
{
  // Enable fast PWM mode 14 (table 47 page 113 ATMega16 Doc):
  TCCR1A    = (1 << COM1A1) |(1 << WGM11);
  // Set prescaler 8
  TCCR1B    = (1 << CS11) | (1 << WGM13) |(1 << WGM12);
  // Set PWM
  ICR1     = (uint16_t)40000;
  OCR1A    = (uint16_t)ServoPosition;      // min: 1800, neutral: 3000 
max: 4200
}


/*********************************************************************** 
*************************************/
void DisableServoTestTimer ()
{
  TCCR1A    = 0;
  TCCR1B    = 0;
}


/*********************************************************************** 
*************************************/
// Main loop
/*********************************************************************** 
*************************************/
int main ()
{
  // Port Delta
  DDRD   =     (1 << PD5);      // Output Servo Test

  EnableServoTestTimer ();

  // Init sleep mode
  set_sleep_mode (SLEEP_MODE_IDLE);  //SLEEP_POWER_SAVE

  // Main loop
  for (;;)
  {
    // Set µC to sleep mode
    sleep_mode ();
  }
}

Der einzige Unterschied ist der sleep mode ... kanns daran liegen?

Grüße & Dank,

Michael

von Jörg X. (Gast)


Lesenswert?

Am sleep-mode 'sollte ' es nicht liegen
Da bin ich auch ratlos :(
Geht's vielleicht besser, wenn erst TOP und COMPARE gesetzt werden, 
BEVOR der Timer los läuft ? (sollte sich aber nur kurz auswirken :( )
1
  // Enable fast PWM mode 14 (table 47 page 113 ATMega16 Doc):
2
  TCCR1A    = (1 << COM1A1) |(1 << WGM11);
3
4
  // Set PWM
5
  ICR1     = (uint16_t)40000;
6
  OCR1A    = (uint16_t)ServoPosition;
7
8
  // Set prescaler 8 <-> START TIMER
9
  TCCR1B    = (1 << CS11) | (1 << WGM13) |(1 << WGM12);
Oder funktionieren andere Modi? (gibt ja noch mehr FastPWMs)
bzw. die andere Compare-Einheit?
Mit welcher Frequenz arbeitet der AVR? (bei 1MHz dauert eine Periode 
schließlich 8*40000/1e6Hz = 0.32s = 320ms!).

hth. Jörg

ps.: brauchst du nicht noch "#include<avr/sleep.h>"? oder fehlt das nur 
hier im Code ...

von Michael K. (Gast)


Lesenswert?

Hallo Jörg,
Die anderen Modi hab ich auch schon ausprobiert, aber leider ohne 
Erfolg. Die anderen Compareeinheiten kann ich leider nicht nehmen, da 
das Ganze schon auf Platine ist und die anderen Ports verwendet werden. 
Ich habe vorhin mal die Compare Ints eingeschaltet und eine Test ISR 
angelegt und in dieser dann das toggeln des Ports "per Hand" ausprobiert 
und das klappt wunderbar ....

> Mit welcher Frequenz arbeitet der AVR? (bei 1MHz dauert eine Periode
> schließlich 8*40000/1e6Hz = 0.32s = 320ms!).
16 MHz externer Quarz.

> ps.: brauchst du nicht noch "#include<avr/sleep.h>"? oder fehlt das nur
> hier im Code ...
Du hast Recht! Ich binde normalerweise ne main.h ein in der ist der 
sleep.h include natürlich drin !

Ich werd' morgen abend noch mal nen bißchen rumbasteln! Vielleicht 
klappts ja mit dem tauschen ....

Grüße und besten Dank,
Michael

von Michael K. (Gast)


Lesenswert?

Ich habs ....
Der Mega war hin. Warum ?? Keine Ahnung ... Neuer rein und lief ! Danke 
an alles für die Hilfe !
Grüße,
Michael

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.