Forum: Mikrocontroller und Digitale Elektronik Attiny 26, invertierter Pin OC1A freischalten


von halama (Gast)


Lesenswert?

Hallo zusammen,

ich habe mit einem Attiny 26 einen Pulscode an PB1 (OC1A)erzeugt, 
allerdings wird das Tastverhältnis rückwärtig (low-high) beim port 
toggle durch TCCR1A abgebildet.

Da ich eine high-low Folge benötige, wäre doch die einfachst Möglichkeit 
den invertierten Pin-Ausgang OC1A an PB0 freizuschalten.

Hat jemand Erfahrung damit, wie ich das Signal invertiert ausgeben kann 
bzw. die "Alternate Functions" ansprechen kann?

Wäre über eine Antwort sehr dankbar

Grüße Martin

P.S:
Der Timer code
void boot_timer1 ()
{
TCNT1 = 0x00;
OCR1C = frequency;
OCR1A = frequency;
TCCR1A |= (1<<COM1A0);
TCCR1B |= (1<<CS10) | (1<<CTC1);
TIMSK  |= (1<<OCIE1A);
}

von Stefan G. (steg13)


Lesenswert?

DDRB |=(1<<0)|(1<<1);
TCCR1A |= (1<<COM1A0)|(1<<PWM1A)|(1<<PWM1B);

von halama (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Stefan,

ich habe Deinen Eintrag ausprobiert und trotz nachlesen des Attiny 
Datenblatt, keine Wirkung damit erzielt.

Was genau macht "(1<<0)|(1<<1)" bei DDRB?

Da ich im CTC Mode laufe und bis zu meinem Wert "frequency" zähle und 
danach den Timer nulle und wieder von neuem zählen lasse ist mir der 
Eintrag bei TCCR1A "(1<<PWM1A)|(1<<PWM1B)" noch nicht ganz klar.

Ist ja nur der Einsatz beider PWMs. Könntest Du das noch ein bischen 
ausführen, was genau damit beabsichtig werden soll...?!

Anbei habe ich ein Oszi-Bild. Der gelb dargestellte Kanal sollte 
komplett invertiert werden.

Über Software und Hilfsvariable toggeln möchte ich vermeiden, da dann 
die Auflösung für die Frequenz durch die Programschritte in die Knie 
geht.

Grüße Martin

von Stefan G. (steg13)


Lesenswert?

ich häng mal ein PWM-Programm für Tiny26 dran.
Das war mein erstes Projekt in C . Wahrscheinlich ist es nicht optimal 
programmiert, aber es läuft.  Kannst ja mal damit experimentieren.
Wenn du was nicht verstehst schreib wieder.
-------------
/*
;PWM Signalerzeugung
;4 verschiedene Frequenzen über Schalter wählbar
;
; ================================================
;                   TINY26
; ================================================
;                __   __
;  CLOCK--- PB0 |1  |_| 28| PA0 --o o- SW1-1 1 kHz
;  CLOCK--- PB1 |2   A  27| PA1 --o o- SW1-2 5 kHz
;           PB2 |3   T  26| PA2 --o o- SW1-3 10kHz
;           PB3 |4   M  25| PA3 --o o- SW1-4 20kHz
;           VCC |5   E  24| GND
;           GND |6   L  23| AVCC
;           PB4 |7      22| PA4
;           PB5 |8   A  21| PA5
;  LED----- PB6 |9   T  20| PA6
;           PB7 |10  m  19| PA7
;               |_________|
;
VorteilerA
CS13 CS12 CS11 CS10
 0    0    0    1   CK/1
 0    0    1    0   CK/2
 0    0    1    1   CK/4
 0    1    0    1   CK/16
 0    1    1    1   CK/64
*/

#define F_CPU    4172000 //FUSE-BIT CKSEL2 und CKSEL3 gesetzt

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#define TCCR1A  _SFR_IO8(0x30)
#define PWM1B   0
#define PWM1A   1
#define FOC1B   2
#define FOC1A   3
#define COM1B0  4
#define COM1B1  5
#define COM1A0  6
#define COM1A1  7

#define TCCR1B  _SFR_IO8(0x2F)
#define CS10    0
#define CS11    1
#define CS12    2
#define CS13    3
#define PSR1    6
#define CTC1    7

void portInit(void){
  DDRB  = 0xFF; // PORTB alle Ausgang
  DDRA  = 0x00; // PORTA alle Eingang
  PORTA = 0xFF; // PULL-UP
}

void timerInit(void){
  // enable TimerA
  TCCR1A|=(0<<COM1A1)|(1<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|(0<<FOC1A)|(0<<F 
OC1B)|(1<<PWM1A)|(1<<PWM1B);
}

void Pause(void){ //etwa 0,17s bei 4MHz-Takt
  uint8_t i;
  uint8_t j;
  for(i=0;i<255;i++)
  {
    for(j=0;j<255;j++) {}
}}

void set20khz(void){
  TCCR1B = 1;     // VorteilerA /1
  OCR1C  = 208;   // Max Zählwert CK/Vorteiler/f (interner Oscill. 
4.000.000Hz)
  OCR1A  = 104;   // Vergleichswert a(%) * OCR1C (z.B. 50% 
Puls-Pausenverhältnis)
}

void set10khz(void){
  TCCR1B = 2;     // VorteilerA /2
  OCR1C  = 208;   // Max Zählwert CK/Vorteiler/f (interner Oscill. 
4.000.000Hz)
  OCR1A  = 104;   // Vergleichswert a(%) * OCR1C (z.B. 50% 
Puls-Pausenverhältnis)
}

void set5khz(void){
  TCCR1B = 3;     // VorteilerA /4
  OCR1C  = 208;   // Max Zählwert CK/Vorteiler/f (interner Oscill. 
4.000.000Hz)
  OCR1A  = 104;   // Vergleichswert a(%) * OCR1C (z.B. 50% 
Puls-Pausenverhältnis)
}

void set1khz(void){
  TCCR1B = 6;     // VorteilerA /32
  OCR1C  = 130;   // Max Zählwert CK/Vorteiler/f (interner Oscill. 
4.000.000Hz)
  OCR1A  =  65;   // Vergleichswert a(%) * OCR1C (z.B. 50% 
Puls-Pausenverhältnis)
}

//*****************Hauptprogramm**************
int main()
{

portInit();
timerInit();
set1khz();

for(;;){ //Endlosschleife

  //Schalterabfrage und Frequenz umschalten

  if(bit_is_clear (PINA,3))  set20khz();
  if(bit_is_clear (PINA,2))  set10khz();
  if(bit_is_clear (PINA,1))  set5khz();
  if(bit_is_clear (PINA,0))  set1khz();

  //LED an PORTB5 blinkt (3Hz)

  PORTB |= (1 << 6);  // Bit 6 setzen
  Pause();
  PORTB &= ~(1 << 6); // Bit 6 löschen
  Pause();
}}


von halama (Gast)


Lesenswert?

Super, dank Dir ganz herzlich hab's jetzt Verstanden und hinbekommen.

Grüße Martin

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.