Forum: Mikrocontroller und Digitale Elektronik PWM Signal OCR1A auf einen anderen Pin umleiten.


von Eduard E. (megawatt1)


Lesenswert?

Hallo,
ich möchte PWM Signal (µC ATtiny 2313, OCR1A auf PB3) auf PD3 umleiten.
Leider habe ich da ein Problem, die PWM funktioniert am PB3(Pin 15) 
einwandfrei, nur die Weiterleitung funktioniert nicht, die unteren 2 
Zeilen.
Habe schon die (Pin 15, PB3) mit (Pin 14, PB2) verbunden und Pin 14 als 
Eingang konfiguriert, (siehe ganz unten) trotzdem habe ich am Pin7 (PD3) 
kein PWM Signal.
Die Frage, wie kann ich PWM Signal auf einen anderen Pin umleiten ?

Der betreffende Codeausschnitt:
1
int main(void)
2
{ 
3
DDRD |= (1<<PD3);
4
DDRB |= (1<<PB3);
5
DDRB &=~ (1 <<PB2)
6
  
7
    TCCR1A = 0x83;    // non-inverted PWM on OC1A, 10 Bit Fast PWM
8
    TCCR1B = 0x08;
9
    TCCR1B &= ~0x7;         // clear clk setting
10
    TCCR1B |=4; 
11
    OCR1A = 0;
12
  int X=0;
13
  
14
  for  (;;) { 
15
16
  if (OCR1A<1023) {X++;}
17
   if ((OCR1A<1023) && (X>10)) {OCR1A=OCR1A++;} 
18
   if (X==11){X=0;}
19
       
20
21
  if (PINB & (1 << 3)) { PORTD |= (1 << 3);}
22
  if (!PINB & (1 << 3)) { PORTD &=~ (1 << 3);}
23
   
24
    }}

if (PINB & (1 << PB2)) { PORTD |= (1 << 3);}
if (!PINB & (1 << PB2)) { PORTD &=~ (1 << 3);}

von Eduard E. (megawatt1)


Lesenswert?

Mittlerweile bin ich weiter, nachdem ich if durch else ersetzt habe
1
 if (PINB & (1 << 3)) { PORTD |= (1 << 3);}
2
    else { PORTD &=~ (1 << 3);}

funktioniert die Weiterleitung, allerdings sehr ruckelig.
Hat einer Idee wie ich es besser machen kann ?

von Helfer (Gast)


Lesenswert?

> Die Frage, wie kann ich PWM Signal auf einen anderen Pin umleiten ?

Hardware

Mit einer Drahtbrücke? Oder indem man die Weiterleitung vermeidet und 
die per PWM versorgte Hardware an den PWM-Ausgabepin anschliesst.

Wenn man ein PWM Multiplexing oder eine Verteilung des PWM Signals auf 
mehrere Empfänger gleichzeitig machen will, kann man externe 
Hardware-ICs verwenden.

Software

Per Software ist ein Ansatz mit manueller if-Abfrage des PWM Status wie 
oben zu sehen ineffizient. Solltest du noch Luft bei der Taktrate haben, 
erhöhe den Takt des AVR und deine if-Abfragen werden öfter durchgeführt 
und das Ruckeln vermindert sich.

Eine bessere Chance hast du, wenn du dir Interrupts an den 
Umschaltpunkten automatisch geben lässt und in der ISR dann den andere 
I/O-Pin toggelst.

von Eduard E. (megawatt1)


Lesenswert?

Danke für die Tipps, da es sich um eine fertige Platine  handelt, sieht 
die  Drahtbrücke nicht so toll aus. Ist wohl aber die beste Lösung. 
Alles andere wird die Abarbeitung verzögern, was den Rest des Programms 
unbrauchbar macht.
Unten sind noch 3 Periode Counter die ganz Zeitkritisch sind.
Ich habe gehofft es gibt eventuell einen Trick den ich nicht kenne..
Ich werde einfach die Drahtbrücke(10k Widerstand)irgendwie auf die 
andere Seite des µC's legen müssen.

von spess53 (Gast)


Lesenswert?

Hi

Beim ATTiny2313 kann man ein Pin durch einfaches Schreiben einer 1 in 
das Pin-Register togglen.

Toggling the Pin Writing a logic one to PINxn toggles the value of
                 PORTxn,independent on the value of DDRxn.
                 Note that the SBI instruction can be used to toggle
                 one single bit in a port.

MfG Spess

von Eduard (Gast)


Lesenswert?

Kann mir jetzt einer Code schnipsel schreiben wie ich es lösen könnte ?
Ich möchte PWM Signal (µC ATtiny 2313, OCR1A auf PB3) auf PD3 umleiten.

 if (PINB & (1 << 3)) { PORTD ^= (1 << 3);}

von Helfer (Gast)


Lesenswert?

PORTD ^= PINB & (1 << 3);

von Helfer (Gast)


Lesenswert?

Sorry, nee vergiss das letzte.

von Eduard E. (megawatt1)


Lesenswert?

Danke für die sehr schnelle Antwort, welche Pin bei PORTD getoggelt wird 
?  wo gebe ich Pin3 bei PORTD ein ?

von Eduard E. (megawatt1)


Lesenswert?

Kann mir jemand noch zeigen wie ich die 300Hz Impulse am Eingang PB1, am 
Ausgang PD2 halbieren kann.  Ich habe mir jetzt so gedacht:

  if (PINB & (1 << 1)) { PORTD ^= (1 << 2);}

oder so:
1
int main(void)
2
{ 
3
DDRD |= (1<<PD2);
4
DDRB &=~ (1 <<PB1)
5
6
int i=0;
7
8
for  (;;) { 
9
10
  if (((PINB & (1 << 1)) && (i<=1)) { i++; }
11
  if (((PINB & (1 << 1)) && (i==2)) { PORTD |= (1 << 2); i=0; }
12
  else if ((!(PINB & (1<<1)) && (PINB & (1 << 1))) { PORTD & =~ (1 << 2);} 
13
}
14
}

von Daniel (Gast)


Lesenswert?

Hi Eduard.
Hier der Link zur meiner Lösung.
http://www.mikrocontroller.net/attachment/103029/test.c
Es gibt bestimmt bessere Beispiele aber es läuft.
Nur achte nicht auf ADC es geht nicht hier im Test-Program.
Du kannst beliebige Ports und Pins in der switch(Port) Anweisung des 
Timers 0 ansprechen.
Sowie eine variable Pulsbreite über den Register OCR0A einstellen.

von Eduard E. (megawatt1)


Lesenswert?

Hallo Daniel, meinst Du so kann es funktionieren ?
1
// Port 
2
void Port_Init()
3
{
4
  DDRD|=(1<<PD3);
5
}
6
7
#define    Port_Hi    PORTD|=(1<<PD3)
8
#define    Port_Lo    PORTD&=~(1<<PD3)
9
10
void Timer_0 (uint16_t Port)
11
12
{  
13
   OCR1A=OCR1A;        
14
   if((TCNT1>=0)&&(TCNT1<=OCR1A))
15
{  
16
    switch(Port)
17
    {
18
      case 0:  Port_Hi; break;
19
    }
20
  }else {Port_Lo;}
21
}
22
  
23
int main(void)
24
{ 
25
Port_Init();
26
Timer_0_Init();
27
uint16_t Res;
28
29
//DDRD |= (1<<PD3);
30
//DDRB |= (1<<PB3);
31
//DDRB &=~ (1 <<PB2);
32
  
33
    TCCR1A = 0x83;    // non-inverted PWM on OC1A, 10 Bit Fast PWM
34
    TCCR1B = 0x08;
35
    TCCR1B &= ~0x7;         // clear clk setting
36
    TCCR1B |=4; 
37
    OCR1A = 0;
38
    int X=0;
39
  
40
  for  (;;) { 
41
42
   if (OCR1A<1023) {X++;}
43
   if ((OCR1A<1023) && (X>10)) {OCR1A=OCR1A++;} 
44
   if (X==11){X=0;}
45
             
46
Timer_0(Res,0);
47
}}

von Daniel (Gast)


Lesenswert?

Hi Eduard.
Ich habe die einzelnen EInstellungen von dir in TCCR1A und TCCR1B nicht 
nachgeschaut, sollten stimmen.
Du kannst nicht OCR1A=OCR1A; schreiben, denn es ist dasselbe Register.
Du musst eine Veriable verwenden z.B. OCR1A=Wert; wobei Wert einen 
unsigned int Variable sein muss. Der TCNT1 zählt immer von 0 bis zum 
Vorgabewert im OCR1A.
1
// Port 
2
void Port_Init()
3
{
4
  DDRD|=(1<<PD3);
5
}
6
7
#define    Port_Hi    PORTD|=(1<<PD3)
8
#define    Port_Lo    PORTD&=~(1<<PD3)
9
10
void Timer_0 (uint16_t Wert, uint8_t Port)
11
12
{  
13
   OCR1A=Wert;        
14
   if((TCNT1>=0)&&(TCNT1<=OCR1A))
15
{  
16
    switch(Port)
17
    {
18
      case 0:  Port_Hi; break;
19
    }
20
  }else {Port_Lo;}
21
}
22
  
23
int main(void)
24
{ 
25
Port_Init();
26
Timer_0_Init();
27
uint16_t Res=200;  // Variabler Wert
28
29
//DDRD |= (1<<PD3);
30
//DDRB |= (1<<PB3);
31
//DDRB &=~ (1 <<PB2);
32
 
33
//    Die Angaben müssen mit deinem Controller passen 
34
    TCCR1A = 0x83;    // non-inverted PWM on OC1A, 10 Bit Fast PWM
35
    TCCR1B = 0x08;
36
    TCCR1B &= ~0x7;         // clear clk setting
37
    TCCR1B |=4; 
38
//    OCR1A = 0; // weg lassen denn du löschst den Vergleichswert
39
    
40
  uint16_t X=0;
41
  
42
  for(;;) 
43
  { 
44
45
    for(x; x<1000; x++)  // Nur ein Beispiel
46
    {
47
       Timer_0(Res,0);
48
    }
49
  }
50
}
Kompiliert habe ich den oberen Code nicht.
Muss weg.
Du musst schon um genaue Hilfe zu erhalten deinen Controller und 
CPU-Frequenz nennen.
Viel Erfolg.

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.