Forum: Mikrocontroller und Digitale Elektronik PWM mit atmega88


von Ramon C. (pnesius)


Lesenswert?

salü ihr,

ich hab hier ein problem und ich bastle da schon seit stunden rum und 
ich kapier das einfach nicht ;(

ich benutze den atmega88 ( 
http://www.atmel.com/dyn/products/product_card.asp?part_id=3302 ) auf 
dem stk500 board

nun muss ich pwm signale generieren und das tut soweit eigentlich auch 
wie ichs will, habs ans oszilloskop angehängt und sieht alles wunderbar 
aus. mein problem ist aber die veränderung der pulslängen.

der code unten produziert mir also ein pwm signal wie gewünscht, jetzt 
möchte ich aber die pulsbreite verlängern bzw verkürzern und hab dazu 
die zwei schalter eingebaut die mir das comparematchregister neu 
beschreiben (inkrementieren und dekrementieren). der komische effekt den 
ich nicht verstehe ist dass das signal genau so lange verändert bleibt 
wie ich auf dem knopf drücke. lasse ich den knopf los, dann geht die 
pulsbreite wieder auf die ursprüngliche breite zurück (die breite die 
bei der initialisierung gesetzt wurde). ich möchte aber dass der puls um 
die erhöhte breite verlängert bleibt.

wenn ich also den knopf loslasse, dann springe ich von einer while 
schlaufe ( while(!(PIND & (0x01 << PD0))) {} ) die nichts macht, in eine 
andere ( while(1) ) die auch genau nichts macht und trotzdem wird das 
signal auf den initialwert zurückgesetzt. sieht da irgendjemand was ich 
falsch mache?

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/signal.h>
4
5
void timer_init(void) {
6
  TIMSK1 = (1<<TOIE1); // Timer Interup Mask 1 -> Timer Overflow Interrupt Enable
7
  TCNT1 = 0; // Timer Counter -> timerreset
8
  
9
  // non inverting Fast PWM Mode with prescaler 64
10
  TCCR1B = (1<<CS11) | (1<<CS10) | (1<<WGM13) | (1<<WGM12);
11
  TCCR1A = (1<<COM1A1) | (1<<WGM11);
12
13
  ICR1 = 0x00FA; // 2 ms period
14
  
15
  OCR1A = 0x007D; // 1 ms pulslength compare value
16
  
17
  sei();
18
  
19
}
20
21
int main(void) {
22
  DDRB = 0x02; // Port B -> PB1 (OL1A) for PWM set as output, others inports
23
  DDRD = 0x00; // Port D -> all bits set as inports
24
  timer_init();
25
  
26
  while(1)
27
  {
28
    if( !(PIND & (0x01 << PD0)) )
29
    {
30
      OCR1A = OCR1A + 0x0F;
31
32
      while(!(PIND & (0x01 << PD0))) {}
33
    }    
34
    else if( !(PIND & (0x01 << PD1)) )
35
    {
36
      OCR1A = OCR1A - 0x0F;
37
38
      while(!(PIND & (0x01 << PD1))) {}
39
    }
40
    
41
  }
42
}

von Johannes M. (johnny-m)


Lesenswert?


von Ramon C. (pnesius)


Lesenswert?

na, die tasten sind glaub ich schon hardwaremässig entprellt. der fehler 
wäre dann auch nicht so systematisch ausgefallen.

ich habs jetzt rein zufällig rausgefunden... aber ich kapier dennoch 
nicht warum das einen einfluss hat.

füge ich folgende funktion hinzu um den overflow abzufangen (kleiner 
test mit blinkender led), funktioniert es wie ich es will. kommentier 
ich sie raus entsteht der oben beschriebene effekt.

1
volatile long int count;
2
// timer 1 overflow
3
SIGNAL(SIG_OVERFLOW1) {
4
  count++;
5
  if(count % 0xFF == 0) {
6
    PORTB = (1 << PB0);
7
    count = 0;
8
  }
9
  else if(count % 0x7F == 0)
10
  {
11
    PORTB = (0 << PB0);
12
  }
13
}

von Johannes M. (johnny-m)


Lesenswert?

Ramon Clematide wrote:
> füge ich folgende funktion hinzu um den overflow abzufangen (kleiner
> test mit blinkender led), funktioniert es wie ich es will. kommentier
> ich sie raus entsteht der oben beschriebene effekt.
Tja, wenn Du einen Interrupt freigibst, für den kein Handler existiert, 
und der Interrupt tritt auf, dann gibts halt nen Reset. Ist doch klar, 
dass dann alles Mögliche passieren kann, oder?

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.