Erstmal scheint der Code nciht für einen ATmega32 geschrieben zu sein. (Wenn ich den Artikel richtig gelesen hab)
Und bis du Sicher das der Emüfänger an PD2 am µC geht?
Hallo Leute,
ich habe mal wieder ein ATMEL AVR Problem. Ich nutze einen ATmega32 @16MHz. Ich habe versucht den RC5 C-Code zum laufen zu
bringen. Ich habe den Code von diesem Artikel http://www.rn-wissen.de/index.php/RC...%C3%BCr_ATMega. Leider bekomme
ich ihn nicht zum laufen. Es wird zwar ein Interrupt erkannt, aber die Bits der addr und code Variable sind immer Null egal
welche Taste ich auf meiner Fernbedienung drücke. Ich habe auch schon mehrere Fernbedienungen versucht, doch leider ohne
Ergbenis. Ich weiß das mit den Bits, weil ich die Variable über den UART und RS232 an den PC übertragen lasse. An dem RC5
Code habe ich nichts geändert.
Ich verwende das Pollin Evalution Board und das Addon Board. Auf dem Addon Board ist der TSOP 1136. Ich denke es könnten zwei
Fehlerquellen sein. Erstens in dem Artikel steht nichts von meinem IR Empfänger drin und zweitens meine verwendeten
Fernbedienungen verwenden nicht den RC5 Standart. Ich habe auch schon eine Phillips Fernbedienung verwenden, aber da kommt
dann gar kein Interrupt an.
An was kann das liegen? Sollte ich mal den Empfänger tauschen und einen von dem Artikel verwenden?
Vielen dank schon mal fürs lesen. Vielleicht hat jemand schon den Code zum laufen gebracht und könnte mir vielleicht ein
bisschen helfen. Oder sieht hier noch eine Fehlerquelle.
So und hier mein verwendeter Code:
WislerCode:#include "rc5.h" #include "uart.h" #include <avr/io.h> #include <avr/interrupt.h> int main() { //uint8_t code = 0; //uint8_t addr = 0; /*UART INIT*/ uart_init(); /* der ensprechende INT-Port muss INPUT sein */ /* RC5 initialisieren, alle Adressen zulassen */ rc5_init (RC5_ALL); /* Interrupts zulassen */ sei(); while(1) { /* Gibt's was Neues? */ if (-1 == rc5.flip) { /* Nein, dann mach irgendwas (oder nix) */ } else { /* Ja, dann rc5.code merken und evtl. rc5.addr */ /* falls man die braucht und nicht sowieso schon kennt */ /*code = rc5.code; addr = rc5.addr;*/ uint8_t code = rc5.code; uint8_t addr = rc5.addr; //FB Code senden! uart_putc(code); uart_putc(' '); uart_putc(addr); /* und auf naechstes Zeichen warten */ rc5.flip = -1; /* code (evtl. addr) auswerten */ } } return 0; }
Erstmal scheint der Code nciht für einen ATmega32 geschrieben zu sein. (Wenn ich den Artikel richtig gelesen hab)
Und bis du Sicher das der Emüfänger an PD2 am µC geht?
Wichtig ist nicht die Pin NR, sonder der Pin an dem der INTO oder INT1 ist. // damit es allgemein gehen soll.
du rufst mit der rc5_init (RC5_all) eine funktion aus rc5.c auf.
Wie und wo ist der Datenausgang des TSOP dran, an INTO oder INT1 ?
Beim Mega16 ist INTO an PD2, so wie TobiKa sagt. Am Mega 32 wohl auch, ( im Datenblatt nachschauen)
in dieser Zeile definierst du das :
#ifndef RC5_INT
#define RC5_INT RC5_INT0 // hier ist int0 der pin für den data_out des TSOP oder halt RC5_INT1 für den anderen
#endif /* RC5_INT */
Desweitern, wo definierst du den Tsop-Pin als Eingang ? z.b.
// Into pin auf Eingang stellen, hier PD2
DDRD &= ~(1<<PD2); // eingang
denn: Pin nicht als Eingang => auch kein Empfang am µC
falls du eine RC5 Fernbedienung hast , würde ich folgende Zeilen mal einfügen( und zwar da woe bei dir "FB Code senden! " steht:
// ach ps. wenn wir schon dabei sind, meide sonderzeichen auch im kommentar, gewöhn dir gar nicht erst an Sonderzeichen zu nutzen, also kein -> ! mehr
if(code == 32)
{
PORTB ^= (1<<PB0);
}
und an PB0 eine LED , denn drückst du nun die Program+ taste, so müßte die LED toggeln.
FCPU definiert im rc5.c und auch im makefile ? z.b.:
#define F_CPU 16000000UL
und im Makefile ( mit editor öffnen)
# MCU name
MCU = atmega16
#oder halt atmega32 für den mega 32
# Main Oscillator Frequency
# This is only used to define F_OSC in all assembler and c-sources.
F_OSC = 16000000
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Target file name (without extension).
TARGET = mega16
# oder wie deine .c-datei heißt wo die main-Schleife liegt, nur ohne .c drann
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c rc5.c
# hier werden alle .c-datein aufgelistet, ohne Komma dazwischen, nur eine Leertaste
so was in der Art,
das sind die wichtigsten Einstellungen die vorgenommen werden müßen damit es klappt, bei mir tut es
Geändert von steveLB (19.03.2011 um 23:08 Uhr)
[X] <-- Nail here for new Monitor
weiter unten steht das:
Portierung ATmegaXX: sollte ohne Anpassung laufen
ATtiny, Classic: Anpassungen erforderlich
Ausserdem sind der Atmega16 und Atmega32 sehr ähnlich in den Sachen, die der Code erfordert. Ja der Empfänger geht wird ja auch ein Interrupt ausgelöst. Nur kommen die Bits net richtig an. Ich denke ich muss mir das Signal mal mit einem Oszi anschauen. Nur leider habe ich keins:
@steveLB
Also des mit dem Pin habe ich überprüft. Leider tut es auch nicht. Auch das mit DDRD habe ich getestet tut leider nicht.
Danke schonmal für eure Tipps. Kann es vielleicht doch am Empfänger liegen, weil ich im Internet noch niemanden gefunden habe, der meinen Empfänger verwendet?
ich hab bis jetzt auch immer Tsop 17xx verwendet, kanns versuchen so einen her zu bekommen, wenn du alles aus meinem Post gemacht hast und es immernoch nicht tut, weiß ich auch nimmer weiter
[X] <-- Nail here for new Monitor
Brauchst auch keins. Ich hatte mir diese Schaltung aufgebaut und damit meinen Empfänger getestet, einen (nein, mehrere) SFH5110-36, siehe Link unten bei MiniD0. Dazu gibt es dieses compilierte Basic-Programm, mit dem kannst Du die Funktion des Empfängers messen - WIRKLICH messen. Du kannst auch damit analysieren, ob die Steuerung RC-5-Code versendet oder etwas anderes. Ich habe mehrere Fernsteuerungen bzw. ihre Codes getestet, die JVC fand ich viel praktischer als dieses RC-5-Gegurke. Trotzdem läuft derzeit als Steuerung für und in meinem MiniD0 eine alte RC-5, die nicht mit der zugehörigen Glotze verschrottet wurde. Ach ja, die Software fürs RC-5 im MiniD0 hatte ich selbst gebaut.Zitat von wisler
Und, wie Du oben lesen kannst, dürfte es nicht wirklich auf den Empfängerchip ankommen, da auch der SFH RC-5-fähig ist *ggg*.
Viel Erfolg!
Ciao sagt der JoeamBerg
Hallo, ich habe ebenso Probleme mit dem RC5 Code vom RoboterNetz -> http://www.rn-wissen.de/index.php/RC...%C3%BCr_ATMega . Ich habe ihn erfolgreich compilieren können und übertragen auf einen Atmega8 mit einem TSOP31236 (36 Khz) IR empänger und einer Loewe Fernbediehnung ( Control 150 TV (RC5 Standart)).
Jeddoch reagiert der Kontroller auf keinen einizgen Tastendruck! Das Signal am TSOP ausgang habe ich mit einem D-Oscillsoscope nachgemessen, da sollte eigendltich alles stimmig sein.
Ich lasse in der Mainschleife ein paar Flanken erzeugen, um überhaupt zu gucken ob der uC reagiert, doch leider tut sich an den Ausgängen nichts.
FCPU habe ich auch in der RC5 schon definiert!
SeveLB hat oben geschrieben das ich den Pin PD2 noch als eingang setzten muss, doch im Original Thread steht " der INT port wird nicht als IN gesetzt" jetzt bin ich verwirrt.
Hier mal meine Datei:
/*
* GccApplication2.c
*
* Created: 29.08.2013 19:25:02
* Author: Hendrik
*/
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include "rc5.h" //NEU
void rechtsdrehen(int schritte) {
int s;
for(s=schritte; s>0; s--){
PORTD=0b00000111;
_delay_ms(0.1);
PORTD=0b00000101;
_delay_ms(0.1);
}
PORTD=0b00000000;
return;
}
void linksdrehen(int schritte) {
int s;
for(s=schritte; s>0; s--) {
PORTD=0b00000110;
_delay_ms(0.1);
PORTD=0b00000100;
_delay_ms(0.1);
}
PORTD=0b00000000;
return;
}
int main(void)
{ //Eingangsport Init
//DDRD &= ~(1<<PD2); // eingang fuer TSOP-DATA
//PORTD |= (1<<PD2); // Pull Up
DDRB = 0b00000001;
DDRC = 0b00100000;
//uint8_t code = 0;
//uint8_t addr = 0;
/* der ensprechende INT-Port muss INPUT sein */
/* RC5 initialisieren, alle Adressen zulassen */
rc5_init (RC5_ALL);
/* Interrupts zulassen */
sei();
while(1)
{
/* Gibt's was Neues? */
if (-1 == rc5.flip)
{
/* Nein, dann mach irgendwas (oder nix) */
PORTB = 0b00010000;
_delay_ms(10);
PORTB = 0b00000000;
_delay_ms(10);
PORTB = 0b00010000;
_delay_ms(10);
}
else
{
/* Ja, dann rc5.code merken und evtl. rc5.addr */
/* falls man die braucht und nicht sowieso schon kennt */
/*code = rc5.code;
addr = rc5.addr;*/
uint8_t code = rc5.code;
uint8_t addr = rc5.addr;
//Reaktion auf Tastendruck
PORTB = 0b00000001;
_delay_ms(10);
PORTB = 0b00000000;
_delay_ms(10);
PORTB = 0b00000001;
_delay_ms(10);
/* und auf naechstes Zeichen warten */
rc5.flip = -1;
/* code (evtl. addr) auswerten */
}
}
return 0;
}
Hast du mal gelesen was der Code macht? Hast ihn grob versteanden ?
wegen : " SeveLB hat oben geschrieben das ich den Pin PD2 noch als eingang setzten muss, doch im Original Thread steht " der INT port wird nicht als IN gesetzt" jetzt bin ich verwirrt."
Es steht doch :" /* der ensprechende INT-Port muss INPUT sein */ " wenn du mal den ersten Link, zum Artikel nimmst.
Also setzte den auch auf Input. Und wenn du wieder mal verwirrt bist, dann probiere beide Möglichkeiten aus .
in der Klammer von :
if (-1 == rc5.flip)
{ .. }
kommt nichts rein, es bleibt nur der eine Kommentar (" // Nein, dann mach irgendwas (oder nix)") drinnen.
danach kommt die Klammer der
else {.. } ,
hier wird der Tastendruck ausgewertet. Aber wie ? Ganz einfach es wird in der Variablen "addr" die Adresse und in der Variablen " code" der RC5 Code reingeschrieben, mehr nicht, alles andere passiert von alleine im Interrupt. Also in code ist jetzt der code der Taste gespeichert die du gedrückt hast.
Somit musst du hier so was machen:
if(code == 33)
{ ... // was getan werden soll beim druck der Taste mit dem Code 33 }
33 und 32 sind entweder Volume up/ down oder Channel up/down auf einer Fernbedienung mit RC5.
[X] <-- Nail here for new Monitor
Ich habe jedenfall den code der Main funktion verstanden. Mir ist auch klar das in die If klammer eigentlich nichts reinkommt und man in else den code auswerten kann.
Das Problem ist nur es Funktioniert nicht. Und ich habe alles erdenkliche ausprobiert, schon bevor ich hier gepostet habe
Also ich habe jetzt mal versucht das so schier wie möglich zu gestalten, würde mich sehr freuen wenn jemand die zeit finden könnte mal drüber zu gucken ob ich einen fehler drinn habe, denn ich weiß beim besten willen nicht mehr was es sein könnte (sitze schon seit 2 Tagen daran)
Ich musste in der RC5.c noch SIGNAL (SIG_OVERFLOW0) in ISR(TIMER0_OVF_vect) außerdem
SIGNAL (SIG_INTERRUPT0) in ISR(INT0_vect) und SIGNAL (SIG_INTERRUPT1) in ISR(INT0_vect) umwandeln- damit der compiler nicht mehr meckert ( habe nachgelesen das die befehle veraltet waren)
application.c :
rc5.h:Code:#define F_CPU 16000000UL #include <util/delay.h> #include <avr/io.h> #include <avr/interrupt.h> #include <stdint.h> #include "rc5.h" int main(void) { //Eingangsport Init DDRB = 0b11111111; DDRD &= ~(1<<PD2); // eingang fuer TSOP-DATA //PORTD |= (1<<PD2); // Pull Up /* der ensprechende INT-Port muss INPUT sein */ /* RC5 initialisieren, alle Adressen zulassen */ rc5_init (RC5_ALL); /* Interrupts zulassen */ sei(); while(1) { /* Gibt's was Neues? */ if (-1 == rc5.flip) { /* Nein, dann mach irgendwas (oder nix) */ } else { /* Ja, dann rc5.code merken und evtl. rc5.addr */ /* falls man die braucht und nicht sowieso schon kennt */ /*code = rc5.code; addr = rc5.addr;*/ uint8_t code = rc5.code; uint8_t addr = rc5.addr; //Reaktion auf Tastendruck PORTB = 0b11111111; _delay_ms(10); PORTB = 0b00000000; _delay_ms(10); PORTB = 0b11111111; _delay_ms(10); /* und auf naechstes Zeichen warten */ rc5.flip = -1; /* code (evtl. addr) auswerten */ } } return 0; }
rc5.c:Code:#ifndef _RC5_H_ #define _RC5_H_ #include <inttypes.h> #define RC5_INT0 0 #define RC5_INT1 1 #define RC5_ALL 0xff typedef struct { uint8_t code; uint8_t addr; volatile signed char flip; } rc5_t; extern rc5_t rc5; extern void rc5_init (uint8_t addr); #endif /* _RC5_H_ */ [/c]
Ich habe auch via If anweisung versucht den code 12 (PWR Taste) abzufragen.. klappt auch nicht.Code:#include <avr/io.h> #include <avr/interrupt.h> #include "rc5.h" #define F_CPU 16000000UL #ifndef RC5_INT #define RC5_INT RC5_INT0 #endif /* RC5_INT */ #ifndef RC5_PRESCALE #define RC5_PRESCALE 1024 #endif /* RC5_PRESCALE */ /* ******************************************************************************** */ rc5_t rc5; /* ******************************************************************************** */ #ifndef F_CPU #error Please define F_CPU #endif /* !F_CPU */ /* µs for a whole bit of RC5 (first & second part) */ #define RC5_BIT_US (64*27) #define RC5_TICKS \ ((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 1000 / RC5_PRESCALE))) #define RC5_DELTA \ (RC5_TICKS / 6) typedef union { uint16_t w; uint8_t b[2]; } code_t; static code_t code; static uint8_t rc5_addr; /* Number of Bits received so far */ /* Number of Interrupts occured so far */ static uint8_t nbits; static uint8_t nint; /* ******************************************************************************** */ void rc5_init (uint8_t addr) { nint = 0; nbits = 0; rc5.flip = -1; rc5_addr = addr; #if (RC5_PRESCALE==1024) TCCR0 = (1 << CS02) | (1 << CS00); #elif (RC5_PRESCALE==256) TCCR0 = (1 << CS02); #elif (RC5_PRESCALE==64) TCCR0 = (1 << CS01) | (1 << CS00); #else #error This RC5_PRESCALE is not supported #endif /* RC5_PRESCALE */ /* INTx on falling edge */ /* clear pending INTx */ /* enable INTx interrupt */ #if (RC5_INT == RC5_INT0) MCUCR = (MCUCR | (1 << ISC01)) & ~ (1 << ISC00); GIFR = (1 << INTF0); GICR |= (1 << INT0); #elif (RC5_INT == RC5_INT1) MCUCR = (MCUCR | (1 << ISC11)) & ~ (1 << ISC10); GIFR = (1 << INTF1); GICR |= (1 << INT1); #else #error please define RC5_INT #endif /* RC5_INT */ } /* ******************************************************************************** */ ISR(TIMER0_OVF_vect) { TIMSK &= ~(1 << TOIE0); uint8_t _nbits = nbits; code_t _code = code; if (26 == _nbits) { _nbits++; _code.w <<= 1; } if (27 == _nbits && _code.b[1] >= 0x30 /* AGC == 3 */ && 0 > rc5.flip) { uint8_t _rc5_code; uint8_t _rc5_addr; /* we do the bit manipulation stuff by hand, because of code size */ _rc5_code = _code.b[0] & 0x3f; /* 0b00111111 : #0..#5 */ _code.w <<= 2; _rc5_addr = _code.b[1] & 0x1f; /* 0b00011111 : #6..#10 */ if (rc5_addr & 0x80 || rc5_addr == _rc5_addr) { rc5.code = _rc5_code; rc5.addr = _rc5_addr; signed char flip = 0; if (_code.b[1] & 0x20) /* 0b00100000 : #11 */ flip = 1; rc5.flip = flip; } } nint = 0; nbits = 0; /* INTx on falling edge */ /* clear pending INTx */ /* enable INTx interrupt */ #if (RC5_INT == RC5_INT0) MCUCR = (MCUCR | (1 << ISC01)) & ~ (1 << ISC00); GIFR = (1 << INTF0); GICR |= (1 << INT0); #elif (RC5_INT == RC5_INT1) MCUCR = (MCUCR | (1 << ISC11)) & ~ (1 << ISC10); GIFR = (1 << INTF1); GICR |= (1 << INT1); #endif } /* ******************************************************************************** */ #if (RC5_INT == RC5_INT0) ISR(INT0_vect) #elif (RC5_INT == RC5_INT1) ISR(INT1_vect) #endif /* RC5_INT */ { code_t _code = code; uint8_t _nint = nint; uint8_t tcnt0 = TCNT0; TCNT0 = 0; if (0 == _nint) { /* INTx on both edges */ #if (RC5_INT == RC5_INT0) MCUCR = (MCUCR | (1 << ISC00)) & ~ (1 << ISC01); #elif (RC5_INT == RC5_INT1) MCUCR = (MCUCR | (1 << ISC10)) & ~ (1 << ISC11); #endif /* RC5_INT */ TIFR = (1 << TOV0); TIMSK |= (1 << TOIE0); _code.w = 0; } else { /* Number of bits of the just elapsed period */ uint8_t n = 1; /* Bits received so far */ uint8_t _nbits = nbits; /* is TCNT0 close to RC5_TICKS or RC5_TICKS/2 ? */ if (tcnt0 > RC5_TICKS + RC5_DELTA) goto invalid; else if (tcnt0 < RC5_TICKS/2 - RC5_DELTA) goto invalid; else if (tcnt0 > RC5_TICKS - RC5_DELTA) n = 2; else if (tcnt0 > RC5_TICKS/2 + RC5_DELTA) goto invalid; /* store the just received 1 or 2 bits */ do { _nbits++; if (_nbits & 1) { _code.w <<= 1; _code.b[0] |= _nint & 1; } } while (--n); if (0) { invalid: /* disable INTx, run into Overflow0 */ #if (RC5_INT == RC5_INT0) GICR &= ~(1 << INT0); #elif (RC5_INT == RC5_INT1) GICR &= ~(1 << INT1); #endif /* RC5_INT */ _nbits = 0; } nbits = _nbits; } code = _code; nint = 1+_nint; }
Was allerding funktioniert ist wenn ich den Port INT0 (PD2) einfach auf LOW abfrage, dann bekomme ich Flanken angezeigt auf dem Oscilloscope beim Tastendruck.
Geändert von wolf7272 (31.08.2013 um 13:27 Uhr)
Der Code scheint ok zu sein. ich benutzte aber SIGNAL und include
// Für alte avr-gcc Versionen
#ifndef SIGNAL
#include <avr/signal.h>
#endif // SIGNAL
Die Schaltung selber könnte es noch sein, oder falls du ein makefile z.B. bei Programmer Notepad [Win avr] benutzt, das du hier dein rc5.c nicht eingefügt hast
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c lcd.c rc5.c
was ich noch gesehen habe in deiner obigen rc5.h steht
#endif /* _RC5_H_ */ [/c]
was soll das [/c] ?
Geändert von steveLB (31.08.2013 um 15:29 Uhr)
[X] <-- Nail here for new Monitor
Lesezeichen