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
Dann schau dir mal die Definitionen für PB3, PB4 und PB5 an. Du wirst mit staunen feststellen daß diese identisch mit PD3, PD4 und PD5 sind.
Sorry, aber ich kann dir nicht folgen. Ich möchte eigentlich PD0 bis PD5 und PB3 bis PB7 als eingänge definieren. was genau mache ich falsch? Vielen Dank jonanova
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
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
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.
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.
Das Switch ist hier eh der falsche Ansatz. Jede Taste ist doch ein Pin, also mußt Du nur jeweils einen Pin prüfen. Dadurch wird dann auch der Code schneller, da der AVR Pintestbefehle hat.
1 | if( PINu & 1<<Puv ) ... |
2 | if( PINx & 1<<Pxy ) ... |
3 | ...
|
Peter
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.