µC Programm tut nicht, was es soll

OP #2246530
Lesenswert?

Hey ihr lieben!

Ich habe folgendes Problem. Ein Motor drückt mir zwei um pi/2 
verschobene in der Anzahl zur Drehazahl proportionale Rechtecksignale 
durchs Kabel, welche ich mit dem attiny45 auslese.

Die Platine ist denkbar ungünstig geroutet, daher folgende 
Anschlussbelegung:

PB5/Reset <- Rechteck 1 (reset ist per fuse natürlich disabled)
PB4 <- Rechteck 2
PB2 -> CLK
PB1 -> DATA
PB0 -> LOAD

Im Debugger läuft alles perfekt, leider nicht in echt. Die 
Ansteuerroutine des DAC scheint zu laufen, jedenfalls werden die 2047 
aus dem Timer Overflow korrekt aufgebraten. Die gesamte Prozedur ist aus 
er Wiki hier. Allerdings krieg ich nur irgendwelche sprunghaften 
Signale, wenn ich ganz langsam drehe. Vielleicht ist der ClockDevide 
1024 auch zu viel und deshalb zähl ich über das Ziel hinaus? Könnte aber 
eigentlich nicht sein, da die Taktfrequenz bei 20MHz durch einen 
externen Oszillator liegt. Jetzt mal das Programm:

-----------------------------------------------------------------
main.c
-----------------------------------------------------------------

#include <avr/io.h>

#include "ltc1257.h"
#include "avr/interrupt.h"

/* Prototypes: */

static unsigned int counter;

int main(void);
void interruptinit(void);
void ioinit(void);

int main(void)
{

  ioinit();
  counter = 2047;

  while(1)
  {
    ;
  }

  /* NEVEREACHED */
  return 0;
}

void ioinit(void)
{
  /* IO setup: */
  DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (0 << PB4) | (0 << PB5); 
/* LTC1257 pins (output) */
  PORTB = (1 << PB4) | (1 << PB5);
  /* Low-level init of DAC: */
  ltc1257_ll_init();

  /* init interrupts */
  interruptinit();
}

void interruptinit(void)
{
  GTCCR = (1 << TSM) | (1 << PSR0);
  TCCR0B = (1 << CS02) | (0 << CS01) | (1 << CS00); //Clock devide by 
1024 0 0 0 stoppt timer
  TIMSK = (1 << TOIE0); //Overflow Interrupt Counter 0
  GIMSK = (1 << PCIE); //pin change interrupt
  PCMSK = (1 << PCINT4); //interrupt pin 4 changes;

  sei();

  GTCCR = 0 << TSM; //loszählen
}

ISR(PCINT0_vect)
{
  if (bit_is_set(PINB, 4) == bit_is_set(PINB, 5)) counter++;
  else counter--; //zählen Richtungsabhängig
}


ISR (TIMER0_OVF_vect)
{
  cli();
  TCCR0B = (0 << CS02) | (0 << CS01) | (0 << CS00);
  PCMSK = (0 << PCINT4);
  ltc1257_ll_write(counter);
  counter = 2047;
  TCNT0 = 0;
  TCCR0B = (1 << CS02) | (0 << CS01) | (1 << CS00);
  PCMSK = (1 << PCINT4);
  sei();
}

-------------------------------------------------------------
ltc1257.h
-------------------------------------------------------------
/*
 * ltc1257.h
 *
 * Created: 28.06.2011 22:20:50
 *  Author: Berni
 */

#ifndef LTC1257_H_
#define LTC1257_H_

/*
 * Low level access routines to the LTC1257 DAC device.
 */

/*
 * Port, where LTC1257 is connected to:
 * PORTC/PINC
 */

#define DACOUT    PORTB
#define DACIN    PINB

/*
 * Port configuration:
 *
 * Port pin  LTC1257
 * --------------------
 * PB0    LOAD
 * PB1    DATA
 * PB2    CLK
 *
 */

#define DACCLK(LEVEL)  DACOUT = (LEVEL) ? (DACIN | _BV(PB2)):(DACIN & 
~_BV(PB2))
#define DACDATA(LEVEL)  DACOUT = (LEVEL) ? (DACIN | _BV(PB1)):(DACIN & 
~_BV(PB1))
#define DACLOAD(LEVEL)  DACOUT = (LEVEL) ? (DACIN | _BV(PB0)):(DACIN & 
~_BV(PB0))

#define LATCHTIMING  0x01        /* spend some time to the latch  */

#define LEV_LOW    0
#define LEV_HIGH  1

void ltc1257_ll_init(void);
inline void ltc1257_ll_write(unsigned int);

/*
 * Low level initialisation routine for LTC1257.
 */

void ltc1257_ll_init(void)
{
  /* Initial port/pin state */
  DACCLK(LEV_LOW);        /* clock pin low -> idle  */
  DACLOAD(LEV_HIGH);        /* load pin high -> idle  */
}

/*
 * Low level write routine for LTC1257.
 * Awaits data in unsigned integer format
 * 12 bits masked (0x800 masks the data's MSB)
 */

void ltc1257_ll_write(unsigned int data)
{
  volatile unsigned char bitctr = 0;

  for(bitctr = 0; bitctr < 0x0C; bitctr++)
  {
    DACDATA(data & 0x800);      /* output MSB (bits [11..0]!)    */
    data <<= 1;        /* shift next bit to MSB    */
    DACCLK(LEV_HIGH);      /* rising edge -> load bit    */
    DACCLK(LEV_LOW);      /* -> await rising edge      */
  }

  DACCLK(LEV_LOW);        /* clock pin low -> idle    */

  for (bitctr = 0; bitctr < LATCHTIMING; bitctr++)
    ;

  DACLOAD(LEV_LOW);        /* load pulled low -> output    */
  DACLOAD(LEV_HIGH);        /* load pulled high -> idle    */
}

#endif /* LTC1257_H_ */

------------------------------------------------------

Falls ihr eine Idee habt, woran das liegen könnte, nur her damit. Danke 
für die Mühen und liebe Grüße
Bernd
Moderator (Firma: Titel) Persönliche Seite #2246654
Lesenswert?

Vorab:
Funktionen haben in Header-Dateien nichts zu suchen.

Vorab, die zweite:
In einer Interruptroutine sind alle weiteren Interrupts sowieso 
geblockt. Deshalb ist das unnötig:
ISR (TIMER0_OVF_vect)
{
  cli();
  :
  sei();
}

Bernd P. schrieb:
> Ein Motor drückt mir zwei um pi/2 verschobene in der Anzahl
> zur Drehazahl proportionale Rechtecksignale durchs Kabel,
> welche ich mit dem attiny45 auslese.
> ISR(PCINT0_vect)
> {
>   if (bit_is_set(PINB, 4) == bit_is_set(PINB, 5)) counter++;
>   else counter--; //zählen Richtungsabhängig
> }
Eine Encoderauswertung sieht normalerweise anders aus...

Was soll denn der Code machen?
Den Drehgeber auswerten und dann auf den DAC schreiben?
OP #2246883
Lesenswert?

Hey!

Das Problem lag scheinbar in der

ISR(PCINT0_vect)
{
  if (bit_is_set(PINB, 4) == bit_is_set(PINB, 5)) counter++;
  else counter--; //zählen Richtungsabhängig
}

Einfach nur hochzählen klappt. Die bit_is_set() hat nich funktioniert. 
Jemand ne Idee, warum? Ansonsten kann das Problem als gelöst angesehen 
werden.

Viele Grüße
Bernd
#2246952
Lesenswert?

Bernd P. schrieb:
> ISR(PCINT0_vect)
> {
>   if (bit_is_set(PINB, 4) == bit_is_set(PINB, 5)) counter++;
>   else counter--; //zählen Richtungsabhängig
> }
>
> Einfach nur hochzählen klappt. Die bit_is_set() hat nich funktioniert.
> Jemand ne Idee, warum? Ansonsten kann das Problem als gelöst angesehen
> werden.

Ich habe eine Vermutung:

bit_ist_set sieht wahrscheinlich so aus:

#define bit_is_set(a,b) ((a) & (1 << (b))

Dieses Makro gibt ungleich 0 zurück wenn das bit gesetzt ist, aber 
trotzdem keinen festen Wert.

Das sollte funktionieren:
1
if(bit_is_set(PINB, 4) && bit_is_set(PINB, 5))
#2246994
Lesenswert?

Samuel K. schrieb:
> Dieses Makro gibt ungleich 0 zurück wenn das bit gesetzt ist, aber
> trotzdem keinen festen Wert.

Nicht fest, aber definiert. Zitat avr-gcc-tutorial:
1
bit_is_set (<Register>,<Bitnummer>)
>Die Funktion bit_is_set prüft, ob ein Bit gesetzt ist. Wenn das Bit gesetzt
>ist, wird ein Wert ungleich 0 zurückgegeben. Genau genommen ist der
>Rückgabewert die Wertigkeit des abgefragten Bits, also 1 für Bit0, 2 für
>Bit1, 4 für Bit2 etc.

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