PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C Motorsteuern klappt!?!?!pwm nicht!!!



patti16
21.01.2006, 16:17
hallo leute,

kann einer von sagen was ich falsch mach. Er soll eine Pwm geschwindigkeit haben also ich meine das so:

ocr1a = 12

nur er dreht immer 255 an statt 12 oder andere zahlen bis 255 warm??

hier der code noch:



#include <avr/io.h>


/* Timer1 initialisieren */
void timer1_init(void);


int main(void)
{
/* Timer1 initialisieren */
timer1_init();
OCR1AL = 5;

DDRD = 0xff;
PORTD = (1<<PD1)|(1<<PD4)|(1<<PD3);
while (1)

;
}

/* Timer1 initialisieren */
void timer1_init(void)
{
/* normale 8-bit PWM aktivieren ( nicht invertiert ),
Das Bit WGM10 wird im Datenblatt auch als PWM10 bezeichnet */
TCCR1A = (1<<COM1A1)|(1<<WGM10);

/* Einstellen der PWM-Frequenz auf 14 kHz ( Prescaler = 1 ) */

/* Interrupts für Timer1 deaktivieren
Achtung : Auch die Interrupts für die anderen Timer stehen in diesem Register */
TIMSK &= ~0x3c;
}



danke im voraus

gruß
patrick

linux_80
21.01.2006, 17:16
Hallo,
so auf den ersten Blick hätte ich zwei Anmerkungen,
Wie schauts mit einem Prescaler aus, wenn kein Wert gesetzt wird ist er 0, und somit der Timer aus.
Du schreibts nur nach OCR1AL, das ist aber ein 16-Bit Register, da sollte man trotzdem OCR1A angeben, dann macht der Compiler den Rest mit High und Low-Register.

patti16
21.01.2006, 22:30
ups wo ich das da gerade sehe wollte eigentlich auch ocr1a schreiben

aber gut das du mich aufmerksam darauf gemacht hast.

gruß
patrick

patti16
22.01.2006, 12:30
klappt immer noch nicht:



#include <avr/io.h>

/* Timer1 initialisieren */
void timer1_init(void);


int main(void)
{
/* Timer1 initialisieren */
timer1_init();



DDRD = 0xff;
PORTD = (1<<PD1)|(1<<PD4)|(1<<PD3);
while (1)

;
}

/* Timer1 initialisieren */
void timer1_init(void)
{
/* normale 8-bit PWM aktivieren ( nicht invertiert ),
Das Bit WGM10 wird im Datenblatt auch als PWM10 bezeichnet */
TCCR1A = (1<<COM1A1)|(1<<CS01);
OCR1A = 255;
/* Einstellen der PWM-Frequenz auf 14 kHz ( Prescaler = 1 ) */

/* Interrupts für Timer1 deaktivieren
Achtung : Auch die Interrupts für die anderen Timer stehen in diesem Register */
TIMSK &= ~0x3c;
}



stimmt das so nicht?


gruß
patrick

linux_80
22.01.2006, 12:41
Hat sich da was geändert ?
Schau Dir mal das Register TCCR1B an !
Thema Clock und Teiler, dazu finde ich nix im Programm.

patti16
22.01.2006, 12:49
ja aber ich möchte doch nur a haben nicht b sonst hätte ich das ja mit darein geschrieben.


gruß
patrick

linux_80
22.01.2006, 12:52
Hast Dir das Register mal angesehen ?
Hat nix mit PWM Ausgang A oder B zu tun !
Ist einfach nur ein weiteres Register von Timer 1.
Und wenn Du da nix reinschreibst läuft der Timer nicht, ganz einfach.

Also guckst du !?

patti16
22.01.2006, 12:55
ok mach ich


gruß
patrick

linux_80
22.01.2006, 13:09
:-)
Bei 8MHz CPU-frequenz wird gerne dieses genommen:

// timer1 on MCU clock/8
TCCR1B = (1 << CS11);

patti16
22.01.2006, 13:13
so sieht das ganze jetzt aus




void timer1_init(void)
{
OCR1AL = 0xff;

TCCR1A = (1<<WGM10)|(1<<COM1A1)|(1<<COM1A0)|(1<<CS11)| (1<<COM1B1) | (1<<COM1B0);;
TCCR1B = (1<<CS11);

TIMSK &= ~0x3c;

linux_80
22.01.2006, 14:14
sorry, das war ein Schritt in die andere Richtung,
man kann nur Bits setzen, die auch in dem Register vorkommen, bzw. wenn man andere Bezeichnungen verwendet die nicht darin vorkommen, wie zB. CS11 das vom TCCR1B ist, im TCCR1A zu verwenden, kommt was unvorhergesehenes raus.

dies läuft mit 8MHz ganz gut:

// 8Bit PWM OC1A
TCCR1A = (1 << WGM10) | (1 << COM1A1);
// Teiler CPU-clock / 8
TCCR1B = (1 << CS11);

//und dann Werte nur damit setzen:
OCR1A = 120;

patti16
22.01.2006, 14:28
wenns dann noch klappen würde.


gruß
patrick

linux_80
22.01.2006, 14:43
Was hast Du eigentlich für'n µC und wieviel MHz ?
Ist auch das richtige Pin, an dem OCR1A rauskommt, auf Ausgang geschaltet ?

Bei mir haut das hin mit Mega8 mit 8MHz.

patti16
22.01.2006, 16:42
ich habe einen atmega mit 16mhz im moment weil die anderen nicht liefer bar sin aber den rest schaue ich gleich mal nach

ogni42
25.01.2006, 10:10
Hier ist mein Testprogramm für PWM:

#include <avr/io.h>
#include <avr/delay.h>
#include <inttypes.h>
#include "pwmRoutines.h"


// modifier for PWM signal width
// modification is based on pin interrupts
volatile uint8_t pwmWidth = 0x40;


void pwmInit( void )
{
// enable PWM outputs
DDRD = (1<<6) | (1<<5);

pwmWidth = 0x10;
// initialise time and pwm modes
pwmInit0();
// pwmInit1();
// pwmInit2();
}



void pwmInit0( void )
{
// 8 bit phase correct PWM
TCCR0A = (1<<COM0A1)|(1<<COM0B1)|(1<<WGM00);

// set prescaler for PWM frequency
TCCR0B = (1<<CS01);

// for fast initialisation (OCRxA/B values are taken on the first TCNTx = TOP)
TCNT0 = 0xfe;

// set initial PWM Width
OCR0A = pwmWidth = 0x10;
OCR0B = 0x03;
}


void pwmInit1( void )
{
// 16 bit phase correct PWM
TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);

// set prescaler for PWM frequency
TCCR1B = (1<<CS11);

// for fast initialisation (OCRxA/B values are taken on the first TCNTx = TOP)
TCNT1 = 0x00fe;

// set initial PWM Width
OCR1A = (uint16_t)pwmWidth;
OCR1B = (uint16_t)0x03;
}


void pwmInit2( void )
{
// 8 bit phase correct PWM
TCCR2A = (1<<COM2B1)|(1<<WGM20);

// set prescaler for PWM frequency
TCCR2B = (1<<CS21);

// for fast initialisation (OCRxA/B values are taken on the first TCNTx = TOP)
TCNT2 = 0xfe;

// set initial PWM Width
OCR2B = pwmWidth;
}



void pwmRun( void )
{
while (1)
{
;
}
}


pwmInitx() ist jeweils die Initialisierungsroutine für den TimerX. Verwendet wird ein ATMega168. Der pwmWidth Parameter wird in Interruptroutinen modifiziert. Alternativ geht aber das Setzen in pwmRun().

patti16
25.01.2006, 21:36
ok danke werde ich morgen mal ausprobieren.

gruß
patrick