PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Fast PWM an Timer2



Feratu
06.03.2009, 20:20
Hi
Ich benötige eine PWM mit mehr als 25kHz, deswegen müsste ich die Fast PWM mit Timer2 benutzen.
Der verwendete Chip ist ein Atmega32 mit externen 8Mhz Quarz.
Die entsprechenden Einstellungen des TCCR2 habe ich gefunden aber es funktioniert nicht ?
Zum testen habe ich eine LEd mit einem 1k vorwiederstand am OC2 ausgang.

TCCR2 = 0110 1001
ist: Fast PWM, Prescaler = 1, non-inverting mode
Zufinden auf Seite 125/126 im Datenblatt des Atmega32
Die LED macht nun garnix -_-
Weswegen ist mir ein totales Rätsel.

Mit diesen einstellungen gehts:
TCCR2 = 0110 0001
ist: Phase Correct PWM (sozusagen normal), non-inverting mode, prescaler =1

Was hab ich vergessen zu ändern ?
Im Datenblatt habe ich nichts weiteres finden können was zur behebung des Problems helfen könnte -_-

Mein Testprogramm besteht nur aus den Grundeinstellungen und dem Befehl: Portd = output ;P
Wie gesagt mit den standard einstellungen (das zweite) geht es einwandfrei aber viel zu langsam (ca 15kHz)

mfg

Sauerbruch
07.03.2009, 00:18
Mein Testprogramm besteht nur aus den Grundeinstellungen und dem Befehl: Portd = output

Dann hast Du OCR2 auch nicht auf einen anderen Wert als 0x00 gesetzt?

Im Fast-PWM-Modus (und COM21:0 = &B10) wird der OC-Ausgang gesetzt wenn der Zähler auf 0X00 überläuft, und resettet wenn er OCR2 erreicht.

Ist OCR2 also 0X00, wird OC2 immer auf LOW bleiben.

Setz doch mal OCR2 auf 128 oder so - dann müsstest Du ein schönes Rechtecksignal bekommen!

Gruß & Co

Feratu
07.03.2009, 02:11
Arrrg,.. sorry vergessen hinzuschreiben

OCR2 = 100
Steht auch mit drin ;P

Aber danke für die antwort ^^

Sauerbruch
07.03.2009, 07:13
Dann habe ich so auf Anhieb auch keine Idee... aber Respekt für die Uhrzeit Deines letzten Beitrags - das Problem scheint Dir ja keine Ruhe zu lassen :-k

Wenn mich ein Geisteblitz ereilt, sag´ ich Bescheid...

T.J.
07.03.2009, 10:32
Oha, das kenn ich wenn man bis 4 oder 5 Uhr bastelt und sucht...

Also ich hatte auch Probleme mit einem PWM für ne Displaybeleuchtung neulich. Das war so, dass es in einem bestimmten Modus nicht ging, in anderem Schon. folgendes allerdings geht super:

(achtung, es ist C und ein AT90CAN128) Aber mit was anderem kann ich dir nicht helfen. Ich denke in der Sache ist es egal ;)

Aufruf:


// Init PWM interface
if(initPWM(fast,non_inv,div8));
else return false;


Funktion:


/************************************************** ***************************
*
* Temperature Unit Firmware
* - PWM functions for display-background-LED
*
* Compiler : avr-gcc 4.3.0 / avr-libc 1.6.2 / AVR Studio 4.14
* size : 2,70KB
* by : Thomas Fuchs, Wolfsburg, Germany
* thomas.fuchs@cc-robotics.de
*
* License : Copyright (c) 2009 Thomas Fuchs
*
* Tested with AT90CAN128
************************************************** **************************/
#include <stdbool.h>
#include "utils.h"
#include "pwm.h"

uint8_t PWM_Timer_temp = 0; // save the operation during hard on/off

// Init PWM

/* defines
#define normal 0
#define phase_correct 1
#define fast 2

#define non_inv 0
#define inv 1
#define off 2

#define no_div 0
#define div8 1
#define div64 2
#define div256 3
#define div1024 4
*/
bool initPWM(uint8_t mode, uint8_t operation, uint8_t clk_div)
{
PWM_Value = 0;
PWM_Timer = 0;
PWM_DDR |= _BV(PWM_Pin);

switch (mode)
{
case 0:
break;

case 1:
PWM_Timer |= (1<<WGM00);
break;

case 2:
PWM_Timer |= (1<<WGM00);
PWM_Timer |= (1<<WGM01);
break;

default:
return false;
}

switch (operation)
{
case 0:
PWM_Timer |= (1<<COM0A1);
break;

case 1:
PWM_Timer |= (1<<COM0A0);
PWM_Timer |= (1<<COM0A1);
break;

case 2:
break;

default:
return false;
}

switch (clk_div)
{
case 0:
PWM_Timer |= (1<<CS00);
break;

case 1:
PWM_Timer |= (1<<CS01);
break;

case 2:
PWM_Timer |= (1<<CS00);
PWM_Timer |= (1<<CS01);
break;

case 3:
PWM_Timer |= (1<<CS02);
break;

case 4:
PWM_Timer |= (1<<CS00);
PWM_Timer |= (1<<CS02);
break;

default:
return false;
}
return true;
}

// PWM dimm

/* defines
#define soft_off 0
#define soft_on 1
#define hard_off 2
#define hard_on 3
*/

void dimmPWM(uint8_t function)
{
uint8_t i;

switch (function)
{
case 0:
for (i=255; i>0; i--) // 255 must be configurated value from EEPROM
{
PWM_Value = i;
delay_ms(8); // delay 10 ms
}
break;

case 1:
for (i=0; i<255; i++) // 255 must be configurated value from EEPROM
{
PWM_Value = i;
delay_ms(8); // delay 10 ms
}
break;

case 2:
PWM_Timer_temp = (PWM_Timer&0x30);
PWM_Timer &= 0xCF;
break;

case 3:
PWM_Timer |= PWM_Timer_temp;
break;

default:
return;
}
}


header zu pwm.c:


/************************************************** ***************************
*
* Temperature Unit Firmware
* - header file of pwm.c
*
* Compiler : avr-gcc 4.3.0 / avr-libc 1.6.2 / AVR Studio 4.14
* size : 953Bytes
* by : Thomas Fuchs, Wolfsburg, Germany
* thomas.fuchs@cc-robotics.de
*
* License : Copyright (c) 2009 Thomas Fuchs
*
* Tested with AT90CAN128
************************************************** **************************/
#define PWM_DDR DDRB
#define PWM_Pin 7
#define PWM_Timer TCCR0A
#define PWM_Value OCR0A

// Init PWM
#define normal 0
#define phase_correct 1
#define fast 2

#define non_inv 0
#define inv 1
#define off 2

#define no_div 0
#define div8 1
#define div64 2
#define div256 3
#define div1024 4

// PWM dimm
#define soft_off 0
#define soft_on 1
#define hard_off 2
#define hard_on 3

extern void delay_ms(uint16_t period); //delay routine (milliseconds)


Ich hoffe das hilft dir!

Gock
07.03.2009, 12:50
So wie da steht, müsste es eigentlich richtig sein. Ich schätze, es leigt am restlichen Code.
Ohne den kann man wohl kaum weiterhelfen.
Gruß

Feratu
07.03.2009, 12:52
Boar das letzte mal wo ich was mit C gemacht habe ist etwa 6 Jahre her und das war C++ im 3D Gamestudio xD
Eherlich gesagt habe ich nicht ganz kapiert was du da macht, zum Teil habe ich mir mal das Toturial im Wissen bereich durchgelesen. Also im Endeffekt machst du ja nicht viel anders als ich ;P
Danke für die Antwort ;P


Das Problem habe ich nicht gefunden aber ich habe es zum laufen gebracht (31kHz).
Vorher: TCCR2 = 01101001
Jetzt: TCCR2 = 105
Das ist genau das gleiche nur eben in Dezimal
HEX wollte Bascom irgendwie nicht,.. neija was solls nun funktioniert es ^^

Danke leute ;P

Gock
07.03.2009, 13:20
Deswegen wollte ich ja den Code sehen.
Ich weiß nicht, wie es in BASCOM ist, aber in C hieße es richtigerweise:

TCCR2 = 0b01101001;
Das ist übrigens binär und nicht hex. Die Kennzeichnung ist natürlich wichtig. Wie sollte der Compiler auch wissen, ob das jetzt binär ist oder decimal oder was auch immer??? Ohne "0b" würde die Zahl dahinter als oktal interpretiert...
Daher sollte man immer den relevanten und korrekten Code posten, so, wie er im Programm steht.
Gruß

Feratu
07.03.2009, 14:00
Verdammt jetzt ist mir einiges klar xD
Das es kein Hex ist sondern Binär ist mir schon bewusst ;P Aber warum hat es dann mit dem Modus 2 funktioniert ?
Hab ja den original Code gepostet ^^

Jetzt ist mir immerhin der Fehler klar, danke ;P
Das passiert mir garantiert nicht mehr xD
mfg
](*,)


In Bascom:
TCCR2 = &B01101001

T.J.
07.03.2009, 23:12
hex: 0xF3
bin: 0b01110101010
dez: 231

immer dran denken ;)