Forum: Mikrocontroller und Digitale Elektronik drehgeber mit mega32


von TK (Gast)


Lesenswert?

Hallo,
ich habe mir einen drehgeber bei reichelt bestellt. Nachdem ich ja noch 
immer recht wenig plan von dem Ganzen habe habe ich bissl geschaut und 
folgenden quelltext gefunden
/*********************************************************************** 
*/
/* 
*/
/*                      Reading rotary encoder                     */
/*                      one, two and four step encoders supported  */
/* 
*/
/*              Author: Peter Dannegger 
*/
/* 
*/
/*********************************************************************** 
*/
#include <avr/io.h>
#include <avr/interrupt.h>

        // target: ATmega16
//---------------------------------------------------------------------- 
--

#define  XTAL    8e6      // 8MHz

#define PHASE_A    (PINA & 1<<PA1)
#define PHASE_B    (PINA & 1<<PA3)

#define LEDS_DDR  DDRC
#define  LEDS    PORTC      // LEDs against VCC


volatile int8_t enc_delta;      // -128 ... 127
static int8_t last;


void encode_init( void )
{
  int8_t new;

  new = 0;
  if( PHASE_A )
    new = 3;
  if( PHASE_B )
    new ^= 1;          // convert gray to binary
  last = new;          // power on state
  enc_delta = 0;
  TCCR0 = 1<<WGM01^1<<CS01^1<<CS00;    // CTC, XTAL / 64
  OCR0 = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);  // 1ms
  TIMSK |= 1<<OCIE0;
}


ISR( TIMER0_COMP_vect )        // 1ms for manual move-ment
{
  int8_t new, diff;

  new = 0;
  if( PHASE_A )
    new = 3;
  if( PHASE_B )
    new ^= 1;          // convert gray to binary
  diff = last - new;        // difference last - new
  if( diff & 1 ){        // bit 0 = value (1)
    last = new;          // store new as next last
    enc_delta += (diff & 2) - 1;    // bit 1 = direction (+/-)
  }
}


int8_t encode_read1( void )      // read single step encoders
{
  int8_t val;

  cli();
  val = enc_delta;
  enc_delta = 0;
  sei();
  return val;          // counts since last call
}


int8_t encode_read2( void )      // read two step encoders
{
  int8_t val;

  cli();
  val = enc_delta;
  enc_delta = val & 1;
  sei();
  return val >> 1;
}


int8_t encode_read4( void )      // read four step encoders
{
  int8_t val;

  cli();
  val = enc_delta;
  enc_delta = val & 3;
  sei();
  return val >> 2;
}


int main( void )
{
  int32_t val = 0;

  LEDS_DDR = 0xFF;
  encode_init();
  sei();

  for(;;){
    val += encode_read1();      // read a single step encoder
    LEDS = val;
  }
}

Dieser code ist für den mega16. Ich habe aber nur nen mega 8515 und nen 
mega32 zur hand, aber das dürfte doch auch nicht anders sein, oder? Ich 
müsste dann doch einfach im AVR stu-dio beim gcc als target eben den 
mega32 auswählen, oder?
Mein Ziel wäre echt einfach nur n Drehgeber, bei dem die LED einfach 
immer einen schritt wei-tergeht (damit ich diesen code dann für eine 
displayansteuerung/menüauswahl verwenden kann).
Danke schon mal
Grüße

: Verschoben durch User
von glitschiger lurch (Gast)


Lesenswert?

> stu-dio / wei-tergeht

womit has Du diese Wortschöpfungen erzeugt ?

von gast (Gast)


Lesenswert?

Bevor du stupide nur das "Target" änderst, solltest du versuchen den 
gefundenen code zu verstehen. Weil dann fällt dir auf, dass der 
eigendliche Encoder-Code prozessorunabhängig ist (ich benutze ihn sogar 
auf einem Renesas M16C26A). Mit dem Verstehen des Codes wird dir dann 
auch klar, welche Ports/Register du für deinen Prozessor ggf. anpassen 
musst. Einfach auf gut Glück das Target ändern ist zwar ´ne Maßnahme, 
bringt aber u.U. neue Probleme mit sich, welche einem "Anfänger" das 
Leben unnötig schwer machen.

von TK (Gast)


Lesenswert?

habs das in word geschrieben - kann sein dass der das getrennt hat...

die ports PINA & 1<<PA1 habe ich auf
PINB & 1<<PA0
PINB & 1<<PA2
PINB & 1<<PA4
geändert
LED Port habe ich auch angepasst.
Habe eben sogar nen Quellcode gefunden der die Ports genauso ansteuert 
wie es bei mir der fall ist - aber selbst das funkte nicht mit dem 
8515er.

von aha (Gast)


Lesenswert?

Weshalb die Interrupts abschalten ? Um ein Byte zu lesen ? Was soll da 
unterbrochen werden ?

von Klaus (Gast)


Lesenswert?

@aha
> Weshalb die Interrupts abschalten ? Um ein Byte zu lesen ? Was soll da
> unterbrochen werden ?

 cli();
 val = enc_delta;
 enc_delta = val & 1;
 sei();

da liegt ja mehr als ein opcode dazwischen, da kann schon was verloren 
gehen.

@TK
schau Dri mal diese Zeilen:
  TCCR0 = 1<<WGM01^1<<CS01^1<<CS00;    // CTC, XTAL / 64
  OCR0 = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);  // 1ms
an und vergleiche die Timer0 Einstellung von Mega16 und Deinem 
Zielcontroller. Bei Mega32 sollte das aber auch passen.

Außerdem noch den Takt und den Vorteiler von Timer0 anschauen und mal 
ausrechnen nach wie vielen ms Timer0 überläuft. (Beispielcode und 
Zielcontroller)

HTH,
Klaus

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.