duplicate case value

OP #1588885
Lesenswert?

Hallo ich bekomme folgenden Fehler bei diesem Code:

error: duplicate case value
für die Fälle mit PB3, PB4 und PB5.

ISR(INT0_vect) {
  uint8_t buttons = ((~PIND) & (_BV(PD0) | _BV(PD1) | _BV(PD3) | 
_BV(PD4) | _BV(PD5))) | ((~PINB) & (_BV(PB7) | _BV(PB6) |_BV(PB5) 
|_BV(PB4) |_BV(PB3))) ;
  uint8_t cmd = 0;

  switch(buttons) {
  case _BV(PD0):
    cmd = RC5_CMD_VOLUME_INC;
    break;
  case _BV(PD1):
    cmd = RC5_CMD_VOLUME_DEC;
    break;
  case _BV(PD3):
    cmd = RC5_CMD_MUTE;
    break;
  case _BV(PD4):
    cmd = RC5_CMD_INPUT_01 ;
    break;
  case _BV(PD5):
    cmd = RC5_CMD_INPUT_02;
    break;
   case _BV(PB3):
    cmd = RC5_CMD_INPUT_03;
    break;
  case _BV(PB4):
    cmd = RC5_CMD_INPUT_04;
    break;
  case _BV(PB5):
    cmd = RC5_CMD_INPUT_05;
    break;
  case _BV(PB6):
    cmd = RC5_CMD_INPUT_06;
    break;
  case _BV(PB7):
    cmd = RC5_CMD_INPUT_07;
    break;

  }

Kann mir jemand sagen warum ich da eine Fehler bekomme?

Vielen Dank im Voraus.

Viele Grüße
Jonanova
Gast #1588903
Lesenswert?

Hallo,

da musst du dir anschauen, welchen Wert _BV(PB3) und alle anderen 
enthalten, ich sehe das an deinem Programmstück nicht (Listing?). Es ist 
aber ziemlich sicher, dass der Compiler recht hat und gleiche Werte 
dabei sind. Er hat nämlich fast immer recht.

Gruss Reinhard
OP #1588906
Lesenswert?

DAs ist der Komplette Code:

/*
 * $Id: rc.c,v 1.2 2006-10-19 15:28:04 andreas Exp $
 */

/*
 * Copyright (c) 2006 Andreas Schroeder <andreas@a-netz.de>
 *
 * Implement functions of an infrared remote control and RC5 protocol 
with an
 * Atmel ATTiny 2313.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
USA
 *
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "rc5codes.h"

/**
 * Device code to send
 */
#define RC5_DEVICE_CODE       RC5_DEV_PREAMP1

/**
 * Maximum bit count before transmission is finished. Minimum (as
 * protocol standard says) is 64. Higher values yield a lower repetition 
rate.
 */
#define MAX_BITCOUNT 64

#define RC5_TEMPLATE (0x3000 | (RC5_DEVICE_CODE << 6))

volatile uint16_t rc5data = 0;

volatile uint8_t bitcounter = MAX_BITCOUNT;
volatile uint8_t halfbitcounter;

// modulation square wave generation
// compare output mode: toggle OC0A on compare match
// if COM0Ax are all unset, the waveform generation is disabled and
// the normal PORTx value is seen on the OC0A pin.
#define ENABLE_MODULATION (TCCR0A |= _BV(COM0A0))
#define DISABLE_MODULATION (TCCR0A &= ~_BV(COM0A0))

// activate half bit timer
#define ENABLE_BIT_TIMER (TCCR1B |= _BV(CS10))
#define DISABLE_BIT_TIMER (TCCR1B &= ~_BV(CS10))

// button control
// MCUCR is setup by default to trigger INT0 on low level, so only 
external
// interrupt needs to be turned on or off
#define ENABLE_BUTTONS (GIMSK |= _BV(INT0))
#define DISABLE_BUTTONS (GIMSK &= ~_BV(INT0))


ISR(INT0_vect) {
  uint8_t buttons = ((~PIND) & (_BV(PD0) | _BV(PD1) | _BV(PD3) | 
_BV(PD4) | _BV(PD5))) | ((~PINB) & (_BV(PB7) | _BV(PB6) |_BV(PB5) 
|_BV(PB4) |_BV(PB3))) ;
  uint8_t cmd = 0;

  switch(buttons) {
  case _BV(PD0):
    cmd = RC5_CMD_VOLUME_INC;
    break;
  case _BV(PD1):
    cmd = RC5_CMD_VOLUME_DEC;
    break;
  case _BV(PD3):
    cmd = RC5_CMD_MUTE;
    break;
  case _BV(PD4):
    cmd = RC5_CMD_INPUT_01 ;
    break;
  case _BV(PD5):
    cmd = RC5_CMD_INPUT_02;
    break;
   case _BV(PB3):
    cmd = RC5_CMD_INPUT_03;
    break;
  case _BV(PB4):
    cmd = RC5_CMD_INPUT_04;
    break;
  case _BV(PB5):
    cmd = RC5_CMD_INPUT_05;
    break;
  case _BV(PB6):
    cmd = RC5_CMD_INPUT_06;
    break;
  case _BV(PB7):
    cmd = RC5_CMD_INPUT_07;
    break;

  }

  // assemble rc5 packet from TEMPLATE (2 start bits and device 
identifier)
  // and 6 command bits
  rc5data = RC5_TEMPLATE | (cmd & 0x3f);

  // activate timer 1 (half bit timer) to write out bitstream
  bitcounter = 0;
  halfbitcounter = 0;
  sleep_disable();
  DISABLE_BUTTONS;
  ENABLE_BIT_TIMER;
}

ISR(TIMER1_COMPA_vect) {
  uint8_t bit = ((rc5data & 0x2000) >> 13);
  uint8_t half = (bit ^ ((halfbitcounter == 0) ? 1 : 0));

  // transmit 14 bit rc5 packet
  if(half && bitcounter < 14) {
    ENABLE_MODULATION;
  } else {
    DISABLE_MODULATION;
  }

  if(bitcounter >= MAX_BITCOUNT) {
    // we can now prepare for the next key press
    ENABLE_BUTTONS;
    DISABLE_BIT_TIMER;
    sleep_enable();
  } else if(bitcounter == 14) {
    // rc5 packet has been transmitted
    DISABLE_MODULATION;
  }

  if(halfbitcounter == 0) {
    halfbitcounter++;
  } else {
    halfbitcounter = 0;
    bitcounter++;
    rc5data <<= 1; // shift left rc5 data
  }
}

int main(void) {
  // setup rc oscillator clock divider to div 1
  // (=> 8MHz with internal RC oscollator)
  CLKPR = _BV(CLKPCE); // enable clock prescale change
  CLKPR = 0; // div1 => 8 MHz

  // setup waveform generation to 36kHz on timer 0
  TCCR0A |= _BV(WGM01); // Clear timer on compare match
  TCCR0B |= _BV(CS00); // timer source is system clock
  //OCR0A = 107; // 36kHz @ 8 (7,77) MHz
  // verify correct frequency! The internal oscillator is not really 
accurate
  OCR0A = 113;

  //OCR0A = 27; // 36kHz @ 1 MHz

  DDRB |= _BV(PB2); // port b.2 as output
  PORTB &= ~_BV(PB2); // pb2 is lo

  // setup half-bit clock (555Hz) on timer1
  TCCR1A = 0;
  TCCR1B = _BV(WGM12); // Clear timer on compare match
  // verify correct frequency! The internal oscillator is not really 
accurate
  OCR1A = 7350; // ~ 889us @ 8MHz

  TIMSK |= _BV(OCIE1A); // output compare interrupt enable 1a

  // button port is input, pullup enabled
  // buttons on PD0,1,3,4,5, int0 on pd2
  PORTD = _BV(PD0) | _BV(PD1) | _BV(PD2) | _BV(PD3) | _BV(PD4) | 
_BV(PD5);
  PORTB = _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6) | _BV(PB7);

  // save energy, disable analog comaprator
  ACSR |= _BV(ACD);

  // setup external interrupt
  ENABLE_BUTTONS;

  sei();
  // set sleep mode to power down mode (i.e. all functions except 
external
  // level (!) interrupts are disabled. Tiny2313 needs ~ 0.5uA then.
  set_sleep_mode( _BV(SM0) | _BV(SM1) );

//   enable sleep mode
  sleep_enable();

  for(;;) {
    // sleep and wait for external interrupt (from button press)
    sleep_cpu();
  }

}

Vielen Dank.

Gruß
jonanova
#1588914
Lesenswert?

PD3 ist ein Makro
#define PD3   3

PB3 ist ein Makro
#define PB3   3


und damit haben PD3 und PB3 denselben Wert.
Du kannst anhand PD3 bzw. PB3 nicht mehr unterscheiden, von welchem Port
der Wert gekommen ist.
Besser wäre es gewesen, da nicht PD3 bzw. PB3 einzuführen, sondern sowas
wie BIT_3. Dann wäre das klarer.
#1588917
Lesenswert?

1
  uint8_t buttons = ((~PIND) & (_BV(PD0) | _BV(PD1) | _BV(PD3) | _BV(PD4) | _BV(PD5))) |
2
                    ((~PINB) & (_BV(PB7) | _BV(PB6) |_BV(PB5) |_BV(PB4) |_BV(PB3))) ;

Du musst Zauberkünstler sein:
10 Bits in nur 8 Bit Speicherfläche unterbringen. Das macht dir so 
schnell keiner nach. Tatsächlich ist in buttons aber das Bit 3, Bit 4 
und Bit 5 gesetzt, wenn das jeweilige Bit in mindetsens entweder PIND 
oder PINB gelöscht ist.
Gast #1588932
Lesenswert?

Hallo,

_BV ist ein Bit-Value, aber für verschiedene Ports kommt das gleiche 
raus, also ist _BV(PD3) = _BV(PB3). Das ist was anderes als bei 
8051-Prozessoren, wo jedes Bit in den SFRs einen eigenen Wert hat, der 
geht dann aber von 0..255 und ist nur mit Bit-Befehlen benutzbar. _BV 
bildet eine Bitmaske: 1,2,4,8,16 usw.

Könnte mich auch täuschen, aber am schnellsten siehst du was läuft, wenn 
du prüfst, welchen Wert PB3 und PD3 haben. Das müsste in io.h stehen.

Gruss Reinhard
Gast #1588945
Lesenswert?

Hallo,

es sollte inzwischen klar sein, warum der Fehler kommt, aber dein Ansatz 
hat noch ein anderes Problem (ausser dem, dass du einen grösseren Vektor 
als nur 8 bit definieren müsstest): was passiert, wenn jemand 2 Buttons 
drückt? Ist das so beabsichtigt?

Gruss Reinhard
OP #1591367
Lesenswert?

Hallo,

vielen Dank erstmal an alle.
Ich wusste leider nicht wofür _BV stand, aber Dank eurer Hilfe bin ich 
jetzt klüger.
Ich habe es jetzt über die If Schleife nach dem Vorschlag von Peter 
gelöst.

@Reinhard: Der Code ist für eine Ir Fernbedienung. Wenn dort jemand auch 
zwei Tasten gleichzeitig drücken würde, dann könnte der Attiny eh nur 
einen Code generieren. Das heißt es wäre aber auch nicht so schlimm, 
wenn er gar nichts machen würde.

Vielen Dank für eure Hilfe.

Viele Grüße
jonanova

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