Attiny 44a PWM getrennt ausgeben

OP #4998262
Lesenswert?

Hallo zusammen,
Ich habe einen Attiny44a und möchte dass an den Ports Pa5 und Pa6 eine 
Pulsweite ausgegeben wird (gleiche Wellenform Fast PWM 9bit ohne 
Vorteiler Prozessortakt intern 8MhZ). Die Register habe ich soweit 
eingestellt und klappt auch.
Nun das Problem:
Pa5 und Pa6 dürfen nie gleichzeitig an sein. Also entweder ist Pa5 mit 
dem PWM ein für 1min oder Pa6 für 1min. Wenn ich nun in C schreibe
Porta|=(1<<Pina6);
Dann wird auch Pa5 eingeschaltet. Das soll aber nicht.
Woran kann das liegen?
Danke für eure Hilfe
#4998270
Lesenswert?

war er vorher an ?

also das hier Porta|=(1<<Pina6);

bedeutet ja Porta:=Porta OR ( 1 SHL PINa6).

also wir gehen davonn aus, daß am anfang alles null ist.


         Portx:=%0000 0000;

dann setzt du port 5.

         Portx:=%0000 0000 or %0001 0000 = %0001 0000;

So und jetzt willst du port 6 aktiv setzen mit deiner methode.

also
         Portx:=%0001 0000 or %0010 0000 = %0011 0000;

Deshalb hast du immernoch den 5er an.

du mußt also erst den port 5 wider löschen.

Um die 5 zu löschen mußt du also

         Portx:=portx and not (1 shl Pinx5) setzen.
Gast #4998452
Lesenswert?

Schon mal Danke für eure Antworten.
Ich benutze den Hardware PWM Pa5 und Pa6 sind anfangs aus.
Meine Grundidee ist dass ich die Pulsweite für Pa5 und für Pa6 über 
Ocr1a und Ocr1b einstelle und dann mit
Porta&=~(1<<Pina5);
Porta|=(1<<Pina6);

Oder

Porta&=~(1<<Pina6);
Porta|=(1<<Pina5);

den Pa6 als Pwm-Ausgang 1 und Pa5 dauerhaft auf 0 habe. Bzw umgekehrt. 
Aber das klappt nicht.

Den Programmteil schick ich heute abend.
#4998499
Lesenswert?

wenn du die PWM per hardware setzt, dann benötigst du das ein und 
ausschalten ja garnicht.

- Du mußt die besagten ausgänge als ausgang definieren
- Den teilerfaktor und modus für für den timer1
- dann kanst du in dem register beide ausgänge für den timer freigeben 
und den timer starten.

jetzt brauchst du nur noch die werte einstellen, die die beiden timer 
als PWM ausgeben sollen, ( hast du ja auch geschrieben )
also in OCR1A und OCR1B .

Nach einer minute setzt du  das register auf null und das andere dann 
auf dem wert, den du möchtest.

wenn du dann OCR1A:=0; setzt, ist der pinn auf low (0%).
#4998503
Lesenswert?

Michael F. schrieb:
> wenn du dann OCR1A:=0; setzt, ist der pinn auf low (0%).

Nicht bei Fast-PWM, denn der PWM-Wert ist OCR1A + 1.

Mit Phase Correct wird was draus. Oder man schaltet einfach den Pin auf 
Eingang. Aber soweit waren wir ja schon.
Man kann auch den Timer mit Fast-PWM von Clear auf Set umsteuern und 
dann 0x1FF ins OCR schreiben. Mit diesem "Trick" gewinnt man sogar 1 
Step an Auflösung.
(Firma: matzetronics) #4998519
Lesenswert?

Schrammi schrieb:
> Porta&=~(1<<Pina6);
> Porta|=(1<<Pina5);

Wenn du die PWM abschalten willst, ohne irgendwas an der Timer 
Konfiguration zu ändern ist es am einfachsten, den abzuschaltenden Port 
auf Eingang zu stellen, z.B.
1
DDRA &= ~(1 << PINA6);  // schaltet PORTA6 auf Input = PWM inaktiv
2
DDRA |= (1 << PINA6);   // und wieder auf Output = PWM aktiv
Gast #4998554
Lesenswert?

Oh Leute ihr seid super. Ist ne gute alternative Idee den port als 
Eingang zu schalten.
Aber noch mal für mich zum Verständnis. So wie ich mir das gedacht habe 
funktioniert das grundsätzlich nicht?
#4998565
Lesenswert?

Schrammi schrieb:
> Ist ne gute alternative Idee den port als
> Eingang zu schalten.

Ist ne äußerst schlechte Idee.
Einen floatenden Ausgang möchte man in der Regel nicht.
Z.B. wenn dahinter ein FET ne Leistungs-LED treiben soll, wird der bei 
floatendem Gate schön überlastet.

Was stört Dich daran, einfach ins TCCR1A zu schreiben?
PORTA und DDRA schreibt man einmalig nach dem Reset und gut.
#4998580
Lesenswert?

@ Schrammi poste mal , ich gehe davonn aus, daß der wurm am TCCR1A 
liegen wird , oder du ihn einfach vergessen hast.

Wie gesagt, solange die PWM aktiv ist, lässt er sich nicht auf Grund 
ziehen ( außer auf 1/255 PWM )  :-).

Mit dem eingang binn auch der meineung von Peter, mit seiner erklärung 
und der aufwand ist ja nicht geringer.

hier nochmal ein link  : 
http://modelleisenbahn-steuern.de/controller/atmega8/12-13-1-tccr1a-atmega8.htm

https://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM
Gast #4998904
Lesenswert?

So jetzt mal das Programm. Pa5 und Pa6 müssen gegen GND ziehen.


#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>


  int ea1()    //Eingäng/Ausgäng 1
  {

  }
  int ea2()    //Eingäng/Ausgäng 2
  {

  }
  int ea3()    //Eingäng/Ausgäng 3
  {

  }
  int ea4()    //Eingäng/Ausgäng 4
  {

  }
  int ea5()    //Eingäng/Ausgäng 5
  {

  }
  int ea6()    //Eingäng/Ausgäng 6
  {

  }

  void motor_aus()  //1=1 2=1 3=0 4=0
  {
    PORTA&=~((1<<PINA5)|(1<<PINA6));
    _delay_ms(1);  //damit der Mosfet auch wirklich aus ist
    PORTA|=(1<<PINA0)|(1<<PINA1);
  }
  void motor_stopp()  //1=0 2=0 3=0 4=0
  {
    PORTA&=~((1<<PINA5)|(1<<PINA6));
    _delay_ms(1);  //damit der Mosfet auch wirklich aus ist
    PORTA&=~((1<<PINA0)|(1<<PINA1));
  }
  void motor_rechts()  //1=0 2=1 3=0 4=1
  {
    PORTA&=~((1<<PINA5)|(1<<PINA6));
    _delay_ms(1);  //damit der Mosfet auch wirklich aus ist
    PORTA=(PORTA|(1<<PINA1)|(1<<PINA5))&(~(1<<PINA0));

  }
  void motor_links()  //1=1 2=0 3=1 4=0
  {
    PORTA&=~((1<<PINA5)|(1<<PINA6));
    _delay_ms(1);  //damit der Mosfet auch wirklich aus ist
    PORTA=(PORTA|(1<<PINA0)|(1<<PINA6))&(~((1<<PINA1)));

  }
int main(void)
{  // Takt
  CLKPR=0b10000000;  //Prozessortakt intern 8MHz
  CLKPR=0b00000000;  // Teiler 0
  // Ports
  DDRA =0b01100011;  //Ein/Ausgänge an A
  PORTA=0b00011100;  //Pullup an A
  DDRB =0b00000000;  //Ein/Ausgänge an B
  PORTB=0b00001111;  //Pullup an B
  // ADC
  ADMUX=0b00000111; // VCC als Ref.spannung Einlesen PA7
  ADCSRA|=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);  //adc eingeschaltet 
vorteiler 64
  ADCSRB|=(1<<ADLAR);    //Werte linksbündig

  // PWM / Timer
  TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<COM1A0)|(1<<COM1B0)|(1<<WGM11); 
//Erst aus und bei compare an da die H-Brücke im Ruhezustand 
durchgeschaltet ist  ,  Top bei 9 bit  , Modus6 Fast PWM
  TCCR1B|=(1<<CS10)|(1<<WGM12);    // ohne Teiler
    /* Replace with your application code */
    while (1)
    {
    OCR1A=220;
    OCR1B=220;
    motor_rechts();
    _delay_ms(5000);
    motor_links();
    _delay_ms(5000);
    }
}
#4999008
Lesenswert?

du hast ja zur zeit

TCCR1A|=

(1<<COM1A1)|(1<<COM1B1)|
(1<<COM1A0)|(1<<COM1B0)|
(1<<WGM11);  also beide pinns werden geändert, sobald der registerinhalt 
erreicht ist.


ich würde es mal umsortieren, so wie es im datenblatt steht.

TCCR1A = (1<<COM1A1)| (1<<COM1A0)|(1<<WGM11);  // nur Pin 6 geht auf die 
PWM

odert anders geschrieben

 TCCR1A =(1<<COM1A1)|(0<<COM1B1)|(1<<COM1A0)|(0 <<COM1B0)|(1<<WGM11);



oder dasselbe für

TCCR1A = (1<<COM1B1)| (1<<COM1B0)|(1<<WGM11);  // nur Pin 5

TCCR1A = (0<<COM1A1)|(1<<COM1B1)|(0<<COM1A0)|(1<<COM1B0)|(1<<WGM11);

Die  TCCR1A|= benötigst du hier garnicht ... du kannst also direkt beide 
werte setzen.


hindert dich eigentlich etwas darann, den phasecorrectmodus zu benutzen 
?

dann ginge das in etwa so

TCCR0A:=(1 shl COM0B1) or (1 shl WGM00);      // phase correct PWM mode

dann kann man auch bis auf null runtergehen ...
Gast #4999021
Lesenswert?

Ja Danke Danke Danke!!!!
 hab`s nun so gelöst:

  void motor_rechts()  //1=0 2=1 3=0 4=1
  {
    TCCR1A&=~((1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0));
    PORTA&=~((1<<PINA5)|(1<<PINA6));
    _delay_ms(1);  //damit der Mosfet auch wirklich aus ist
    TCCR1A|=(1<<COM1B1)|(1<<COM1B0);
    PORTA=(PORTA|(1<<PINA1)|(1<<PINA5))&(~(1<<PINA0));

  }

funktioniert!

Super besten Dank euch :-)
Gast #4999404
Lesenswert?

>    TCCR1A&=~((1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0));
hier würde ich TCCR1A einfach auf NUll setzen und dann komplett neu 
laden.
Deine PWM-PINs PORTA5 und PORTA6 kannst Du am Anfang direkt auf Low 
setzen.
Die sind dann auch LOW, wenn Du die PINs von der PWM "abkoppelst".
Das einzige, worum du dich noch kümmern musst, sind PA0 und PA1, welche 
wohl die anderen beiden Steuerpins deiner Brücke zu sein scheinen. (Bei 
Dir mit 3=0|1 bzw. 4=0|1 bezeichnet).
Den Timer kannst Du durchlaufen lassen, gibt dann nur beim "anknüppern" 
des PA5 oder PA6 an die PWM-Unit einmalig einen falschen Wert.

Mir sind da auch schon die Fets um die Ohren geflogen, kann ich gut 
nachvollziehen. Ich hatte einen mega48mu und FDC64?? für ein 
mikromodellbautruck programmiert. der blieb dann hin und wieder mit 
rauchendem Führerhaus auf der Tisch-Truck-Trail-Strecke stehen. Ein 
OCRx=0 reicht da tatsächlich nicht aus.
1
TCCR1A = 0;

und neu setzen des TCCR1A, je nach Motorlaufrichtung half bei mir.
Ich hab sogar den Timer noch auf null gesetzt, damit der OCR Wert auch 
wirklich "stimmt", ist aber Krümelkackerei.
Viel Spaß noch, LG


StromTuner

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