ATMega16 Fast PWM

OP #687173
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
Gast #687317
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
Gast #687330
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
Gast #687362
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
Gast #687386
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 ...
Gast #687581
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren