PWM Signal OCR1A auf einen anderen Pin umleiten.

OP #2081361
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);}
Gast #2081468
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.
OP #2081555
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.
Gast #2081564
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
OP #2087406
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
}
OP #2087586
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
}}
Gast #2088492
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.

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