PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : rc5 daten senden mit winavr



pebisoft
15.03.2005, 13:15
hallo , ich möchte jetzt mit winavr daten über die ir-diode
senden zum tsop1736. ich möchte das ganze in einem überschaubaren
programm begreifen und umsetzen. bei den ir-daten sagt man , die müssen
über eine frequenz (36khz beim tsop1736) moduliert werden.
wird das frequensignal beim senden der daten quasi unterbrochen für die datensignale,
oder müssen die datensignale von einem anderen pin mit an dem
übertragungspin angeschlossen werden, so das 2x pins als eingang zur didode gehen,
sozusagen die datensignale plus die frequezsignale. vielleicht hat einer eine gute idee wie man das machen kann. die programme die es gibt machen das nicht so plausibel.
mfg pebisoft

muraad
15.03.2005, 14:09
Also pepisoft wenn ich das richtig verstanden hab dann wird mittels PWM ein 36kHz Signal erzeugt und mit der Pulsweite(also wie lange low und high) kann man ein Signal/Befehl übertragen. Wenn das so richtig ist könnt ich schon mal bisschen Code dafür schreiben.
Und wegen deim anderen Problem mit deim Compass. Geht die I2C-libary jetzt? Sie ist halt eigenltich in Assembler geschrieben, deswegen kann ich dazu nichts sagen. Wenn du willst kann ich hier aber I2C-Funktionen von mir hochladen, und du kannst die versuchen. Meine Funktionen sind hauptsächlich der Code aus dem Datenblatt (über i2c gibts einiges an C Code im Datenblatt) mit ein paar Änderungen.
Gruß Muraad

pebisoft
15.03.2005, 17:47
hallo, das compassmodul cmps03 kann man mit dem programm von Hagen Reddmann
im i2c-format und winavr-c auslesen. ich bekomme bei einer 0 bis 360-grad-drehung immer die zahl 0 bis 3600 als wert, also sehr genau.
"http://www.mikrocontroller.net/forum/read-4-81256.html" dort steht das programm
um ein i2ceeprom bis 24c512 mit winavr-c zu lesen und zu beschreiben oder das obige compassmodul. das ander programm machte schwierigkeiten beim konfigurieren. nimm das von hagen, kann ich nur empfehlen, ist auch gut lesbar mit einem kleinen verständlichen externen asm-anteil. den rc5-code habe ich noch nicht ganz verstanden.
dank deiner informellen hilfe bin ich so gut vorangekommen.
mfg pebisoft

pebisoft
15.03.2005, 18:12
hallo, die signale werden mit dem 36khz ausgegeben (aufmoduliert,
weiss nicht was das heisst). besteht aus 14 bit. die gesamte signalzeit beträgt
114ms, ein bit dauert 1,778ms. sendezeit also 1,778ms*14=25ms sowie
anschliessend 89ms pause. alle bits werden bitphasencodiert gesendet, das
heisst in der mitte der bitzeit wird der logische zustand gewechselt.
ein low auf high bedeutet eine 0, ein wechsel von high auf low eine 1.
ein zustand dauert dann 0,889us ist also dann 1778us für ein komplettes bit.

mfg pebisoft

Arexx-Henk
15.03.2005, 21:33
Hallo pebisoft,

ich hab mahl geguck wie dass bei Asuro Roboter gemacht wird.


PB3 --------R220OHM--------(+)IRDIODE(-)--------PD1

An PB3 steht immer 36KHz und die daten kommen aus PD1.

Wenn PD1 hoch ist wird kein IR-Signal ausgestrahlt.
Denn
- wenn PB3 hoch ist und PD1 hoch, lauft kein Strom.
- wenn PB3 niedrich ist und PD1 hoch, lauft auch kein Strom weil die
IRDIODE dann gesperrt ist.
Wenn PD1 niedrich ist wird ein IR-Signal ausgestrahlt.

Dass 36KHz signal an PB3 wird von einem timer erzeugt.
Und PD1 ist die USART TX ausgang.

gruss

Henk

pebisoft
15.03.2005, 21:51
mich würde mal das zusammenspiel zwischen dem pb3 und pd1 interessieren. warum ist er am usart-anschluss tx, wie werden dort die datenbits erzeugt.
mfg pebisoft

Arexx-Henk
15.03.2005, 22:45
Das 36KHz signal PB3 ist immer anwesend.

Die Asuro communiziert glaube ich nicht mit RC5 oder sonstiges sondern nur mit 'ubliche' serielle schnitstelle signalen. Da kann man z.B. 2400baud, 1 startbit, 8 datenbits, 1 stopbit anwenden. Startbit is 36KHz eingeschaltet (PD1 niedrich), 1-bit ist 36KHz eingeschaltet (PD1 niedrich) , 0-bit ist 36KHz ausgeschaltet (PD1 hoch)

So kann mann einfach die USART benutzen und brauch mann nicht selber die richtige zeitablauf irgendwo zu programmieren.

gruss
Henk

muraad
16.03.2005, 16:02
pepisoft ich weis nicht ob du schon bei www.mc-project.de warst aber da wird es ganz gut erklärt. Sind auch Beispielfunktionen dabei.
Und nochmal zur erklärung:
Es wird mit PWM(Timer0/Timer1) ein 36kHz Signal erzeugt. Ein anderer Timer wird dann in der rc5_send() Funktion so eingestellt das er den PWM Pin des ersten Timers für die gewünschte Zeit auf Ausgang schaltet.
Wobei der zweite Timer so eingestellt werden sollte das er auch wieder 1micro sekunde für einen Tackt braucht, dadurch kann man die Zeit leicht mit unseren srf04 Funktionen messen.
Ich finde es aber umständlich mit 2 Timern. Besser wäre es mit dem Timer IC 555 ein 36kHz Signal zu erzeugen, und vom ATmega aus, mit einem unwichtigen Timer, den Timer IC für die gewünschte Zeit anschalten. Hoffe man konnte es verstehen.
Gruß Muraad

pebisoft
17.03.2005, 18:31
hallo muraad, dieses demo sendet 2 zahlen (10,20), es soll ja gemäss aussage 8 zahlen senden können. wie kann man es ändern, das es ein byte (8bit) sendet die man dann empfnagen kann. er hat dort 2x timecount in einem bereich von-bis abgefragt. wie weit geht eigentlich die von-bis abfrage wenn ich z.b. 8 byte abfragen kann und wie könnte man das nutzen für 8 bit.
mfg pebisoft



/* IR-Routine:
Es werden unterschiedlich lange Impulse gesendet und vom Empfänger ausgewertet.
Exemplarisch werden 10 verschiedene Längen implementiert, wovon jeder dann als
Befehl betrachtet werden kann. Dies ist zunächst die trivialste Variante, reicht
aber für einfach Fernsteuerungen aus.
Variation von pulse: 10 ... 20 ... 30 ...... 100*/

#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <lcd.c>

//#define send
#define receive

#ifdef send
volatile unsigned char empty = 0;
volatile unsigned char pulse = 0;

SIGNAL (SIG_OVERFLOW0) {
if (pulse) {
DDRB |= (1<<PB1);
empty = 1;
pulse--;
}
if (!pulse) {
empty = 0;
DDRB &= ~(1<<PB1);
}
}

void ir_init_send (void) {
//36kHz Träger
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS10);
OCR1A = 111;
ICR1 = 222;
//Timer-Interrupt alle 2,048ms zur Signalerzeugung --> 1/(8MHz/256/64)
TCCR0 = (1<<CS01) | (1<<CS00); //Prescaler von 64
TIMSK |= (1<<TOIE0); //Timer0 Overflow Interrupt aktivieren
}

void ir_send (unsigned char byte) {
//Senderoutine
if (!empty)
pulse = byte;
}
#endif

#ifdef receive
volatile unsigned short timecount = 0;
volatile unsigned char empty = 0;
volatile unsigned char rec_byte = 0;

SIGNAL (SIG_OVERFLOW0) {
//-----<allgemein>-------
if (!(PINB & (1<<PB0))) { //Low-Pegel = log. 1 am Sender
timecount++;
empty = 1;
}
else {
empty = 0;
}
if ((!empty) && (timecount)) {
//-----<Auswertung>------ //8fache Abtastung
if ((timecount > 70) && (timecount < 90)) { //pulse war 10
rec_byte = 10;
}
if ((timecount > 150) && (timecount < 170)) { //pulse war 20
rec_byte = 20;
}
timecount = 0;
}

}

void ir_init_receive (void) {
//Abtastung realisieren
//Timer-Interrupt alle 0,256ms zum Signalempfang --> 1/(8MHz/256/8)
TCCR0 |= (1<<CS01); //Prescaler von 8
TIMSK |= (1<<TOIE0); //Timer0 Overflow Interrupt aktivieren
lcd_init (LCD_DISP_ON);
}

unsigned char ir_receive (void) {
//Empfangsroutine
return rec_byte;
}
#endif


int main (void) {
#ifdef send
ir_init_send ();
DDRC &= ~(1<<PC5);
#endif
#ifdef receive
ir_init_receive ();
#endif
sei ();
for (;;) {
#ifdef send
if (!(PINC & (1<<PC5))) {
delay (65000); //Entprellung
ir_send (10);
}
if (!(PINC & (1<<PC4))) {
delay (65000); //Entprellung
ir_send (20);
}
#endif
#ifdef receive
if (rec_byte) {
lcd_gotoxy (0,0);
if (rec_byte == 10)
lcd_puts ("10");
if (rec_byte == 20)
lcd_puts ("20");
}
#endif
}
return 0;
}

muraad
18.03.2005, 01:30
Mir ist auch nicht ganz klar wie er das timecount auswertet.
Ich hab grad den Code abgeändert so das man Zahlen zwischen 1 und 255 hätte senden können, aber dann hab ich gelesen das die Frequenz des aufmodulierten Nutzsignals um einiges höher sein muss als 36kHz. Aber was heisst "um einiges höher", reicht 4,7 mal höher?
Wenn ja post ich den Code, wenn nicht dann ist das garnicht so einfach.
Aber muss es den gleich ein ganzen Byte zu versenden sein oder reichen dir nicht vielleicht so 50 Befehle die erkannt werden, das würde es wieder einfacher machen.
Gruß Muraad

pebisoft
18.03.2005, 10:09
kannst du mal schauen , ob man nicht irgendwie von hand die 14 bytes senden kann. evtl als test in einer while-schleife über 36khz über den ocra1. man könnte ja pro halb-bit eine schleife machen von 889us und dann pind5 z.b beim avr16 (ocra1) mit 36khz-pwm versehen und diese dann je nach bit aus oder einschalten und nach dem 14bit kommt ja wieder eine pause von 89ms weil ja die komplette sendezeit immer 114ms beträgt. die 36khz kann man doch mit dem mc-musterprogramm erzeugen, oder?

mfg pebisoft

muraad
18.03.2005, 12:12
Aber wieso denn den ganzen rc5 Code? Willst du Fernsehgeräte ansteuertn? Im rc5 Code sind ja auch nur die letzten 6Bit Befehlsbits d.h. man kann auch nur 64 Befehle senden.
Gruß Muraad

muraad
18.03.2005, 14:18
Pepisoft ich hab jetzt nochmal zwei Funktionen, mit denen man ein Byte, bitweise senden kann. Das 36kHz Signal wird immer noch mit PWM und Timer1 erzeugt. Timer2 wird für das senden und empfangen verwendet.
Beide Funktionen benutzen die Timer so das sie nur währen der Funktion gebraucht werden. Man könnte also auch noch z.B. srf04 Messung auch mit Timer1 machen.
Hier der Code:


// Wieder für 8 Mhz
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

// Eins auswählen

#define send
// #define receive

// Wie lange die verschiedenen Signale dauern in X_SIGNAL*0,128us
#define START_SIGNAL 250 // z.B. 250*0,128us=32ms langes Start Signal
#define HIGH_SIGNAL 200 // 25,6ms
#define LOW_SIGNAL 100 // 12,8ms
// Ein Byte zu senden dauert somit max. 32ms+8*25,6ms=236,8ms, für die Zahl 256

// Pin an dem der TSOP Ausgang angeschlossen ist
#define rc5_pin // z.B. PINA
#define rc5_bit // z.B. PA1

// Für PWM 36kHz Signal
#define PWM_PORT DDRD // PWM Pin1 von Timer1, beim ATmega16 z.B. PD5
#define PWM_BIT PD5

#ifdef send

void rc5_send(unsigned char byte)
{
volatile unsigned char byte_flag,x;

// Timer1 Fast PWM Prescaler 1, 36kHz Träger,
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS10);
OCR1A = 111;
ICR1 = 222;
byte_flag=0;

/* Sendet Start Signal */

// Lädt Timer2 Register mit 5 vor ein 250*128us=32ms langes Startsignal zu senden
TCNT2 = 255 - START_SIGNAL;
// Prescaler 1024 Frequenz 7,8125kHz Tackt von 128us , Timer an
TCCR2= (1<<CS22) | (1<<CS21) | (1<<CS20);
PWM_PORT |= (1<<PWM_BIT); // Der Pin mit dem 36kHz Siganl wird auf Ausgang geschaltet

// Warten bis Overflow2 nach 32ms
while(!(TIFR & (1<<TOV2))) asm volatile ("nop");
PWM_PORT &= ~(1<<PWM_BIT); // 36kHz Signal aus
TCCR2= ~(1<<CS22) & ~(1<<CS21) & ~(1<<CS20); // Timer2 aus

for(x=0;x<=200;x++) asm volatile ("nop"); // Kleine Pause
/* Sendet nun das byte, bitweise */

// high=25,6ms lang, low=12,8ms lang
for(byte_flag;byte_flag<=7;byte_flag++)
{
if(byte & (1<<byte_flag)) // Ist bit(byte_flag) in byte high
TCNT2=255-HIGH_SIGNAL; // Wenn ja TCNT2 vorladen für high senden
else
TCNT2=255-LOW_SIGNAL;
TCCR2= (1<<CS22) | (1<<CS21) | (1<<CS20); // Timer an
PWM_PORT |= (1<<PWM_BIT); // 36kHz Signal an
while(!(TIFR & (1<<TOV2))) asm volatile ("nop"); // Warten bis Overlow2, -> Bit gesendet
PWM_PORT &= ~(1<<PWM_BIT); // 36kHz Signal aus
TCCR2= ~(1<<CS22) & ~(1<<CS21) & ~(1<<CS20); // Timer2 aus
for(x=0;x<=200;x++) asm volatile ("nop"); // Kleine Pause
}
// Timer1 wieder aus, kein PWM mehr
TCCR1A = ~(1<<COM1A1) & ~(1<<COM1A0) & ~(1<<WGM11);
TCCR1B = ~(1<<WGM12) & ~(1<<WGM13) & ~(1<<CS10);
OCR1A = 0;
ICR1 = 0;
}
#endif

#ifdef recieve
unsigned char rc5_recieve(void)
{
volatile unsigned char byte,byte_flag,wert,x;
x=0;
byte_flag=0;

// Solange messen bis Startsignal empfangen, aber max. 9 mal damit nicht in endlosschleife
// galls garkein Signal
do{
TCNT2=0; // Timerregister auf 0
// Warten bis rc5/tsop1736 Pin auf high
while (!(rc5_pin & (1<<rc5_bit))) asm volatile ("nop");
TCCR2= (1<<CS22) | (1<<CS21) | (1<<CS20); // Timer2 starten, Prescaler 1024
// Warten bis rc5/tsop1736 Pin auf low
while (rc5_pin & (1<<rc5_bit)) asm volatile ("nop");
wert=TCNT2; // byte = Timer1
TCCR2= ~(1<<CS22) & ~(1<<CS21) & ~(1<<CS20); // Timer2 aus
x++;
// Wert nicht genau auf STAR_SIGNAL prüfen um eine Fehlertoleranz zu haben
}while((!((wert > STAR_SIGNAL - 10)&&(wert < START_SIGNAL + 5)))|| x!=9);

// Wenn Startsignal empfangen
if((wert > STAR_SIGNAL - 10) && (wert < START_SIGNAL + 5))
{
// Schleife um einzelne Bits zu empfangen
for(byte_flag;byte_flag<=7;byte_flag++)
{
TCNT2=0; // Timerregister auf 0
// Warten bis rc5/tsop1736 Pin auf high
while (!(rc5_pin & (1<<rc5_bit))) asm volatile ("nop");
TCCR2= (1<<CS22) | (1<<CS21) | (1<<CS20); // Timer2 starten, Prescaler 1024
// Warten bis rc5/tsop1736 Pin auf low
while (rc5_pin & (1<<rc5_bit)) asm volatile ("nop");
wert=TCNT2;
TCCR2= ~(1<<CS22) & ~(1<<CS21) & ~(1<<CS20); // Timer2 aus

// Wieder Fehlertoleranz für HIGH_SIGNAL und LOW_SIGNAL, diesmal +/- 20
if((wert > HIGH_SIGNAL - 20) && (wert < HIGH_SIGNAL + 20))
byte|=(1<<byte_flag); // Bit ist high, entsprechendes bit in byte high setzen
else if(wert>80 && wert<120)
byte&= ~(1<<byte_flag); // Bit low setzen
}
return byte;
}
// Wenn kein Startsignal empfangen
else
return 0;
}
#endif

Ist bisschen mehr dieses mal. Werden wahrscheinlich auch noch einige Fehler drin sein. O:)
Vielleicht kannst/musst du auch mal mit den Zeiten für die einzelnen SIGNALE rumspielen, und mit deren Toleranzen in der recieve Funktion.
Und noch was zur rc5_recieve(), sie versucht erst neun mal ein Startsignal zu empfangen. Hat sie ein Startsignal empfangen beginnt sie mit dem empfang der einzelnen Bits. In der rc5_send(byte) ist nach dem Startsignal und nach jedem einzelnen Bit eine kleine Sendepause, mit
for(x=0;x<=200;x++) asm volatile ("nop");
Theoretisch müsste es funktionieren.
Gruß Muraad

EDIT: Hab schon wieder was verbessert O:)

EDIT: Ich hab nochmal was verändert. Vielleicht funktioniert er ja jetzt?!

pebisoft
19.03.2005, 10:58
hallo muradd, man kann auch die addressbit als daten dazunehmen. ich möchte den robby damit daten übersenden. dem tsop interessiert nicht was man mit den 11bit macht(address und comman), es werden 14bit übertragen und beim empfang kann man die bit address und command (11bit)zu einem 10bit-wert (1024) zusammensetzen z.b. und hat 1024 möglichkeiten und man hat noch 1bit über.
senden würde ich gerne ohne timer, nur den pwm-port(oc1a z.b) je nach halb-bit mit 889us einschalten oder auschalten in einer schleife.
mfg pebisoft

muraad
19.03.2005, 12:23
Mein Code könnte man theoretisch auch auf 100 zu sendende Bits erweitern sogar ziemlich leicht.
Nur mit nur einem Timer wird es schwer, mir fällt auch grad nichts konkretes ein wie ich das anstellen könnte.
Ein genaues Timing, mit for() Schleifen, wird ohne zweiten Timer auch ziemlich schwer glaub ich. Wie wird das bei Bascom gemacht, auch mit nur einem Timer?

Gruß Muraad

pebisoft
19.03.2005, 21:28
hallo muraad, bei bascom ist es timer 1, da gibt es den befehl "rc5send togbit, adress, command".
dies ist der anschluss " +5V <---[A Led K]---[220 Ohm]---> PD5 "
bei bascom. pd5 ist beim avr16 oc1a.


ich habe mal ein beispiel mit us_889 und ms_89. oc1a ist bei mir am avr16 pd5. der pd5 (oca1) wird je nach bit auf high oder low geschaltet. lieg ich hier verkehrt mit meiner ganzen theorie.




#include <stdio.h>
#include <inttypes.h>
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <string.h>
#include <stdint.h>


uint16_t zaehler;
uint32_t zaehler1;

void us_889(void)
{

for (zaehler=0; zaehler<1185; zaehler++)
asm volatile("nop");

}

void ms_89(void)
{
for (zaehler1=0; zaehler1<117105; zaehler1++)
asm volatile("nop");
}

void ir_init_send(void) {
//36kHz Träger
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS10);
OCR1A = 111;
ICR1 = 222;
//Timer-Interrupt alle 2,048ms zur Signalerzeugung --> 1/(8MHz/256/64)
TCCR0 = (1<<CS01) | (1<<CS00); //Prescaler von 64
TIMSK |= (1<<TOIE0); //Timer0 Overflow Interrupt aktivieren
}


int main(void)
{

ir_init_send();
DDRD=255;
PORTD=32; // bit pd5

while (1)
{
PORTD=32;
us_889();
PORTD=0;
us_889();

PORTD=32;
us_889();
PORTD=0;
us_889();

PORTD=32;
us_889();
PORTD=0;
us_889();

PORTD=32;
us_889();
PORTD=0;
us_889();

PORTD=0;
us_889();
PORTD=32;
us_889();

PORTD=0;
us_889();
PORTD=32;
us_889();

PORTD=32;
us_889();
PORTD=0;
us_889();

PORTD=0;
us_889();
PORTD=32;
us_889();

PORTD=0;
us_889();
PORTD=32;
us_889();

PORTD=0;
us_889();
PORTD=32;
us_889();

PORTD=32;
us_889();
PORTD=0;
us_889();

PORTD=32;
us_889();
PORTD=0;
us_889();

PORTD=0;
us_889();
PORTD=32;
us_889();

PORTD=0;
us_889();
PORTD=32;
us_889();

PORTD=32;
ms_89();
}
}


mfg pebisoft

muraad
20.03.2005, 00:02
Also kann man mit Bascom richtige rc5 Befehle sende, und nicht einfach nur ein Byte?! Ich verstehe immer noch nicht was du mit dem rc5 Protokoll willst. Es ist vielleicht für Fernbedienungen gut aber für nen Roboter. Ich hab halt so zusagen ein eigenes Protokoll gemacht.
Und zu deinem Code. Würde prinzipiell schon gehen, du musst das nur in ne Funktion packen und ihr eine unsigned int Variable übergeben. In der Funktion werden dann die ersten 14Bits der Variable überprüft ob sie low oder high sind und dementsprechend gesendet.
Dann brauchst du noch nen Funktion die das Empfäng und auswertet.

Gruß Muraad

pebisoft
20.03.2005, 09:48
hallo, muurad, guten tag.
empfänger in winavr-c gibt es schon. ich kann von der fernbedienung alle signale mit dem winavr-c anzeigen lassen auf dem lcd-display oder pc-schirm (vom avr über rs232). mich interessiert einfach , wie ich jetzt daten selber erzeugen kann in den 14bytes. dein programm läuft noch nicht, vielleicht liegt es am timer. die ausgabe habe ich schon in "ddrd" umgeschrieben. ich habe einen video-audio-sender auf dem robby, der vom robby zum arbeitstisch senden kann. der empfänger auf dem arbeitstisch kann über funk aber auch ein ir-signal zum sender schicken, damit man quasi den fernsehsender umschalten kann. ich möchte das jetzt dazu nutzen den robby steuerungsdaten für das verhalten per ir zu schicken. diese daten möchte ich aber selber erzeugen und nicht die fernbedienung. ich habe überall im internet schon geschaut, es gibt kein programm in winavr-c für das senden von rc5-code. das es unmöglich ist, glaube ich nicht. ist vielleicht eine schwierige aufgabe. obwohl der rc5-code und die erklärungen bestens sind, schaff ich es nicht umzusetzen.
kein sende-empfangscode für den rc5 ist eigentlich so gut erklärt.
mfg pebisoft

Dino Dieter
20.03.2005, 10:07
Hallo pebisoft

RC5 Sender zu programmieren, ist eigentlich kein größeres Problem.

Schau mal auf dieser Seite nach.

http://home.t-online.de/home/holger.klabunde/rc5send.htm

Ist zwar für PIC, aber in C und somit mit nur wenigen Änderungen zu übernehmen. Ich habe das mal für einen Tiny12 übernommen
und es läuft ohne Probleme. Da der Tiny12 jedoch mit interem Takt von 1.2 MHz lief, ist das Programm für deine Taktfrequenz nicht
ohne weiteres zu übernehmen. Auch lief auf dem Tiny12 nichts anderes.

MFG
Dieter

pebisoft
20.03.2005, 10:40
ich habe obern mal was geschrieben, ganz einfach, funktioniert aber nicht.
kannst du einmal schauen gestern 21:28 . was mache ich da verkehrt.
mfg pebisoft

muraad
20.03.2005, 13:11
Also so wie dein Code ist kann er nicht richtig funktionieren.
Hab ihn mal bisschen umgeändert, aber so wie du wolltest.
Hier:


#include <stdio.h>
#include <inttypes.h>
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <string.h>
#include <stdint.h>


uint16_t zaehler;
uint32_t zaehler1;

void us_889(void)
{

for (zaehler=0; zaehler<1185; zaehler++)
asm volatile("nop");

}

void ms_89(void)
{
for (zaehler1=0; zaehler1<117105; zaehler1++)
asm volatile("nop");
}

void ir_init_send(void) {
//36kHz Träger
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS10);
OCR1A = 111;
ICR1 = 222;
//Timer-Interrupt alle 2,048ms zur Signalerzeugung --> 1/(8MHz/256/64)
TCCR0 = (1<<CS01) | (1<<CS00); //Prescaler von 64
TIMSK |= (1<<TOIE0); //Timer0 Overflow Interrupt aktivieren
}

void rc5_send(uint16_t code) // Nur die ersten 14Bits zählen die obersten 2 werden ignoriert
{
uint8_t i;
for(i=0;i<=14;i++)
{
DDRD&= ~(1<<PD5); // PWM 36kHz Signal auf low
us_889(); // halbe Bitzeit warten
if (code & (1<<i)) // aktuelles Bit in code prüfen ob high
DDRD|= (1<<PD5); //wenn ja, PWM 36kHz Signal auf high
us_889(); // zweite halbe Bitzeit
}
ms_89(); // Pause

int main(void)
{

ir_init_send();
rc5_send(0b0000110001001111); // Nur untersten 14Bits sind wichtig
}

Jetzt werden nur deine for() Schleifen benutzt. Ich weiß allerdings nicht genau ob man einer Funktion den Wert einer Variable als Binärzahl übergeben darf, ich denke aber schon.
Gruß Muraad

pebisoft
20.03.2005, 18:12
hallo arexx-henk schreibt folgendes:

ich hab mahl geguck wie dass bei Asuro Roboter gemacht wird.
PB3 --------R220OHM--------(+)IRDIODE(-)--------PD1
An PB3 steht immer 36KHz und die daten kommen aus PD1.
Wenn PD1 hoch ist wird kein IR-Signal ausgestrahlt.
Denn
- wenn PB3 hoch ist und PD1 hoch, lauft kein Strom.
- wenn PB3 niedrich ist und PD1 hoch, lauft auch kein Strom weil die
IRDIODE dann gesperrt ist.
Wenn PD1 niedrich ist wird ein IR-Signal ausgestrahlt.

Dass 36KHz signal an PB3 wird von einem timer erzeugt.
Und PD1 ist die USART TX ausgang.

vielleicht baucht ocr1a nicht geschaltet werden sondern nur ein anderes signal und ocr1a liefert nur das 36khz-signal.

allmählich komme ich mit der signalgebung ins schleudern.
versucht ihr es noch einmal zu überdenken.
vielen dank.
mfg pebisoft

muraad
20.03.2005, 19:32
Ich hab den Code jetzt nochmal grundlegend geändert.
Was mir nie aufgefallen ist. Bei rc5 dauert ein Bit zu senden 1778us, in der Mitte entscheidet sich ob 1 oder 0. Bei 1 muss in der Mitte der Zeit ein wechsel von high auf low sein, bei 0 ein wechsel von low auf high.
D.h. man muss auch mit einbeziehen was das letzte Bit war(0 oder 1) und damit der aktuelle Signalpegel.
Ich hab jetzt ne neue Funktion, mit deinen for() Schleifen, die das alles macht.


#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <string.h>
#include <stdint.h>


uint16_t zaehler;
uint32_t zaehler1;
#define PWM_PORT DDRD
#define PWM_BIT PD5
void us_889(void)
{

for (zaehler=0; zaehler<1185; zaehler++)
asm volatile("nop");

}

void ms_89(void)
{
for (zaehler1=0; zaehler1<117105; zaehler1++)
asm volatile("nop");
}

void rc5_init(void) {
//36kHz Träger
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS10);
OCR1A = 111;
ICR1 = 222;
}

void rc5_send(uint16_t code) // Nur die ersten 14Bits zählen die obersten 2 werden ignoriert
{
uint8_t i,X;

// Prüfen ob das erste Bit low oder high ist um zu wissen wie man anfängt
if(code&(1<<0)); // Ist erstes Bit high
{
i=1; // letztes Bits war high
PWM_PORT|= (1<<PWM_BIT); //wenn ja, PWM 36kHz Signal auf high
us_889(); // halbe Bitzeit warten
PWM_PORT&= ~(1<<PWM_BIT); // PWM 36kHz Signal auf low
us_889(); // zweite halbe Bitzeit
}
else
{
i=0;
us_889(); // halbe Bitzeit warten
PWM_PORT|= (1<<PWM_BIT);
us_889(); // zweite halbe Bitzeit
}

// Sendet die letzten 13Bits und prüft wie das letzte Bit war
for(X=1;X<=13;X++)
{
if((i=1)&&(code&(1<<X)) // letztes Bit war high und nächstes ist high
{
PWM_PORT|= (1<<PWM_BIT); // high
us_889();
PWM_PORT&= ~(1<<PWM_BIT);
us_889();
}
else if((i=1)&&(!(code&(1<<X)))) // letztes high und nächstes low
{
i=0;
us_889();
PWM_PORT|= (1<<PWM_BIT);
us_889();
}
else if((i=0)&&(code&(1<<X))) // letzes low, nächstes high
{
i=1;
us_889();
PWM_PORT&= ~(1<<PWM_BIT);
us_889();
}
else if((i=0)&&(code&(1<<X))) // letzes low, nächstes low
{
PWM_PORT&= ~(1<<PWM_BIT);
us_889();
PWM_PORT|= (1<<PWM_BIT);
us_889();
}
else
asm volatile ("nop"); // zu else sollte es nie kommen
}
ms_89(); // Pause falls gleich noch etwas gesendet wird
}
int main(void)
{

ir_init_send();
rc5_send(0b0000110001001111); // Sendet das was du in deinem Code senden wolltest
}

Ach und was das beim Asuro mit dem USART Pins zu tun hat weis ich auch nicht. Auf jedenfall wird das nicht das rc5 Protokoll sein denk ich.

Viele grüße Muraad

pebisoft
20.03.2005, 21:50
hallo, muraad vielen dank. dein programm lässt sich compilieren. es kommt aber kein signal an. ist egal wo ich die ir-diode mit 100ohm anschliesse (+ oder minus und pd5 ocra1), mit bascom läuft die diode. ich gebe aber nicht auf. es muss doch möglich sein, eine addresse und ein command zu senden plus toggle und startsbits.
ich kann auch nicht prüfen , ob die daten vom trägersignal stimmen.
mfg pebisoft

muraad
21.03.2005, 12:33
Es könnten noch zwei Fehler sein. Erstens könnte irgendwas falsch sein an der ir_init(), die Frequenz stimmt schon, ich weiß nur nicht ob FastPWM stimmt. Vielleicht sollte man hier mal auf PhaseCorrect PWM umstellen.
Und zweitens könnte es sein dass das hier:
for(X=1;X<=13;X++)
{
if((i=1)&&(code&(1<<X)) // letztes Bit war high und nächstes ist high
{
PWM_PORT|= (1<<PWM_BIT); // high
us_889();
PWM_PORT&= ~(1<<PWM_BIT);
us_889();
}
else if((i=1)&&(!(code&(1<<X)))) // letztes high und nächstes low
{
i=0;
us_889();
PWM_PORT|= (1<<PWM_BIT);
us_889();
}
else if((i=0)&&(code&(1<<X))) // letzes low, nächstes high
{
i=1;
us_889();
PWM_PORT&= ~(1<<PWM_BIT);
us_889();
}
else if((i=0)&&(code&(1<<X))) // letzes low, nächstes low
{
PWM_PORT&= ~(1<<PWM_BIT);
us_889();
PWM_PORT|= (1<<PWM_BIT);
us_889();
}
else
asm volatile ("nop"); // zu else sollte es nie kommen
}
zu lange dauert, und ein Bit dadurch nicht 1,778ms sondern vielleicht 2ms braucht. Deswegen könnte es sein das deine rc5_recieve() Funktion, die du verwendest, es nicht als rc5 Code erkennt.
Man müsste in einem Simulator mal genau schauen wie lange mein for() Schleife (13Bits) mit den if Anweisungen braucht. Ist da dann wirklich ein größere Zeitfehler muss/kann man vielleicht noch deinen us_889() Wartefunktionen verändern.
In der ir_init_send() war auch noch was von Timer0 drinnen, das hatte ich nur vergessen zu löschen. Habs jetzt verbessert, und die Funktion rc5_init() gennant.
Gruß Muraad

pebisoft
21.03.2005, 22:45
hallo muraad, hallo dino dieter, könnt ihr eure erfahrungen einmal zusammenlegen. es funktioniert bis jetzt noch nicht, auch wenn die timerabstimmung stimmt. ich finde den fehler nicht. dino dieter, du hast doch einmal einen pic als sender genommen und das in c geschrieben.
dieses hier hat dino dieter vorgeschlagen, aus einem pic-rc5-sender:


//Eine 0 senden
void SendBit0()
{
unsigned char i;

//890us Impuls mit 36kHz senden
//Bei 28us Periodendauer ergibt das 32 Impulse
//Die Befehle unten ergeben nur 20us*32 = 640us
//Der Rest wird mit dem Schleifenoverhead verbraten
//Deshalb sieht die Nullphase auch kürzer aus als sie
//tatsächlich ist !
//Beim 12C508 ist der Overhead kleiner !!
//Liegt am Compiler
//Deshalb sind hier mehr NOPs als im Programm für 16F84
for(i=0; i<32; i++)
{
LED_ON();
NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
NOP; NOP;
LED_OFF();
NOP; NOP; NOP; NOP; NOP; NOP;
}

//890us Pause
for(i=0; i<32; i++)
{
NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
}

}

//Eine 1 senden
void SendBit1()
{
unsigned char i;

//890us Pause
for(i=0; i<32; i++)
{
NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
}

//890us Impuls mit 36kHz senden
for(i=0; i<32; i++)
{
LED_ON();
NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
NOP; NOP;
LED_OFF();
NOP; NOP; NOP; NOP; NOP; NOP;
}
}

void PhaseMod()
{
unsigned char mask;
unsigned char i;

SendBit1(); //Erstes Startbit=1
SendBit1(); //Zweites Startbit=1

//Togglebit
if(toggle==0)
{
SendBit0();
}
else
{
SendBit1();
}
//Ende Togglebit

//5 Bit Gerätecode
mask=0x10; //Beginn bei MSB

for(i=0; i<5; i++)
{
if(SUBCODE&mask) //Send 1
{
SendBit1();
}
else //Send 0
{
SendBit0();
}

mask>>=1; //Nächstes Bit
}
//Ende Gerätecode

//6 Bit Kommandocode
mask=0x20; //Beginn bei MSB

for(i=0; i<6; i++)
{
if(comcode&mask) //Send 1
{
SendBit1();
}
else //Send 0
{
SendBit0();
}
mask>>=1; //Nächstes Bit
}
//Ende Kommandocode

//Übertragung komplett
LED_OFF(); //IR-LED abschalten
}

könnte man beim avr nicht auch ein 36khz-signal erzeugen an einem beliebigen port. der dann erst erzeugt wird, wenn die 14bit gesendet werden (36khz brauchen ja erst beim senden einer "1" oder "0" erzeugt werden, oder sehe ich das verkehrt). diese massnahme hält den roboter nicht zeitlich gross auf und ist im steuerungsprogramm nicht spürbar.

mfg pebisoft

pebisoft
22.03.2005, 09:37
hallo muraad, vielleicht kannst du mir sagen, wie ich ein 36khz signal erzeuge ohne interrupt. nur wenn ich das halbbit sende von 889us soll der frei wählbare pin pulsieren mit 36khz.
mfg pebisoft

muraad
22.03.2005, 13:06
Ganz erlich gesagt hab ich keine Idee. Außer den Pin 36000mal in der Sekunde an und auszuschalten.
Ach und das der Code von DinoDieter sich kompilieren lässt ist schon klar, ist ja standart C. Aber ich bezweifle das er auf einem AVR genauso lange braucht wie auf einem PIC. In dem Code steht das er schon für einen anderen Pic angepasst werden muss.
Du musst dir halt selber for() Schleifen machen, wie in dem PIC Code, und rumtesten solange bis du ein 36kHz Signal hast.
Gruß Muraad

Dino Dieter
22.03.2005, 19:43
Hallo Pebisoft

In dem Code oben, stehen doch alle Lösungen.


for(i=0; i<32; i++)
{
PORTA &= ~(1<< LED_PIN); //oder welcher port auch immer (LED an)
//Hier eine Zeitschleife rein, die ca 13 µs verbrät

PORTA |= (1<< LED_PIN); //oder welcher port auch immer (LED aus)


//Hier eine Zeitschleife rein, die ca 13 µs verbrät
}

//890us Pause
for(i=0; i<32; i++)
{
//Hier eine Zeitschleife rein, die ca 27 µs verbrät

}

}

Der Code läßt doch eine LED mit ungefähr 36 KHz leuchten für ca 889 µs. Danach 889µ aus.


Hier mal ein Teil von meinem Code damals. Wie gesagt für einen Tiny mit 1,2 MHz. Mußte halt die Variablen in Register halten.



#include <avr/io.h>

#define uchar unsigned char
#define uint unsigned int

void licht_aus (void);
void licht_an (void);
void send_0 (void);
void send_1 (void);
void daten (void);


#define led 1

//Funktion zum senden einer 0 +++++++++++++++++++++++++++++++++++++++
void send_0 ()
{
licht_an();
licht_aus();
}


//Funktion zum senden einer 1 +++++++++++++++++++++++++++++++++++++++
void send_1 ()
{
licht_aus();
licht_an();
}

//Funktion Licht aus+++++++++++++++++++++++++++++++++++++++++++++++ ++
void licht_aus (void)
{
register uchar n asm("r2");

for(n=0;n< 146;n++) // 889µs Pause
{ asm volatile (" nop");
asm volatile (" nop");
}
}

//Funktion Licht an++++++++++++++++++++++++++++++++++++++++++++++++ ++
void licht_an ()
{
register uchar n asm("r2");

for(n=0;n<33;n++)
{
// 13 us Licht an ca 15 Takte
PORTB = 0x01; // LED an
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
// 13 us Licht aus ca 15 Takte
PORTB = 0x00; //LED aus
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");
asm volatile (" nop");



}

}

//Funktion Daten senden++++++++++++++++++++++++++++++++++++++++++++ ++
void daten()
{
//Sendet immer nur zum Test diesen Code
//Adresse = 0
//Command = 1
// 2 Startbits senden
send_1();
send_1();
// Togglebit senden
send_0();
//Adresse senden
send_0();
send_0();
send_0();
send_0();
send_0();
//Comand senden
send_0();
send_0();
send_0();
send_0();
send_0();
send_1();
}


//Einstellen der Hardware des AVR++++++++++++++++++++++++++++++++++++
void init(void)
{

//Ports einstellen
DDRB = 0xff;
TCCR0 = (1<<CS02)| (1<< CS00);
//OSCCAL setzen sonst läuft er nicht sauber mit 1,2 MHZ
//nur bei TINY 12 mit internen Takt notwendig
asm volatile (" ldi 0x18, 0x3e");
asm volatile (" out 0x31, 0x18");

}

//Hauptprogramm+++++++++++++++++++++++++++++++++++++ +++++++++++++++++
void main (void)
{
init();

DDRB = 0xff;

register uchar d asm("r4");

for(;;)
{
daten();
TCNT0 = 0;
while ( TCNT0 < 36); //kleine Verzögerung
}
}



Die Funktion daten ist nicht so dolle. Der Sender hat jedoch immer nur eine RC5 Befehl gesendet, von daher.


MFG
Dieter

pebisoft
22.03.2005, 20:35
hallo muraad, dino dieter usw.
es ist vollbracht !
durch ausdauer und nicht aufgeben hat man das ziel erreicht.
ich kann jetzt unter winavr-c ganz sauber rc5-code (14bit) senden ohne interrupt.
es tritt über haupt kein übertragungsfehler auf, klasse.
die 36khz werden nur zur zeit des gesetzten bits erzeugt also nur immer 890us lang.
dank eurer hilfe ist es endlich gelungen.
wie man sieht ist das programm nicht kompliziert. und ist für jeden anfänger nachvollziebar.
hallo muraad, du kannst dieses programm auch wieder bekannt machen.
es läuft bei mir mit dem avr16 und 8mhz.
ir-diode von portb0 über 10kohm nach 5volt.
der port kann beliebig gewählt werden.




#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <string.h>
#include <stdint.h>


//89ms pause
void ms_89(void)
{

uint32_t zaehler;

for (zaehler=0; zaehler<118666; zaehler++)
asm volatile("nop");
}

//Eine 0 senden
void SendBit0(void)
{

uint16_t i,zaehler;

//890us Impuls mit 36kHz senden
//Bei 28us Periodendauer ergibt das 32 Impulse

for(i=0; i<32; i++)
{
PORTB=1;
for (zaehler=0; zaehler<18; zaehler++) // ~14us
asm volatile("nop");
PORTB=0;
for (zaehler=0; zaehler<18; zaehler++) // ~14us
asm volatile("nop");
}

//890us Pause
for (zaehler=0; zaehler<1186; zaehler++)
asm volatile("nop");

}

//Eine 1 senden
void SendBit1(void)
{

uint16_t i,zaehler;

//890us Pause
for (zaehler=0; zaehler<1186; zaehler++)
asm volatile("nop");

//890us Impuls mit 36kHz senden
for(i=0; i<32; i++)
{
PORTB=1;
for (zaehler=0; zaehler<18; zaehler++)
asm volatile("nop");
PORTB=0;
for (zaehler=0; zaehler<18; zaehler++)
asm volatile("nop");
}
}


int main(void)

{

DDRB=1; // Portb1 = ausgang

while (1)
{
SendBit1(); //Erstes Startbit=1
SendBit1(); //Zweites Startbit=1

SendBit0(); //Togglebit

//5 Bit Gerätecode
SendBit0();
SendBit1();
SendBit0();
SendBit1();
SendBit1();

//6 Bit Kommandocode
SendBit1();
SendBit1();
SendBit1();
SendBit1();
SendBit1();
SendBit1();

//Übertragung komplett
PORTB=0; //IR-LED abschalten
ms_89(); // warte 89ms
}

}



mfg pebisoft

Dino Dieter
22.03.2005, 20:53
Hallo

Schön das es jetzt klappt. Da du jetzt einmal dabei bist, wäre es sehr nett, wenn du die Software noch ein wenig "verbessern" könntest.

Ich würde mir eine Funktion wünschen, in der Art etwa

void send_rc5( uint8_t commando, uint8_t befehl)

Auch könnt man die beiden Funktionen void SendBit1(void) & void SendBit0(void) etwas zusammen fassen, da ja doch fast dasselbe passiert, nur in umgekehrter Reihenfolge.

Dann hätte man eine gute RC5 Senden Funktion. Eine automatische Berechnung der Verweilzeiten bei unterschiedlichen Frequenzen wäre
auch eine feine Sache.

MFG
Dieter

pebisoft
22.03.2005, 23:52
hallo dino dieter, hier ist eine änderung,
setzen von bit0 und bit1 wurde zusammengefasst.
halbbit-routinen wurden geschaffen.
es kann der ganze code gesendet werden "send_code(toggle,addresse,commando)".
läuft auf dem avr16 8mhz 100%.




#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <string.h>
#include <stdint.h>


//89ms pause
void ms_89(void)
{
uint32_t zaehler;

for (zaehler=0; zaehler<118666; zaehler++)
asm volatile("nop");
}

void halbbit_high(void)
{
uint16_t i,zaehler;

//890us Impuls mit 36kHz senden
//Bei 28us Periodendauer ergibt das 32 Impulse
for(i=0; i<32; i++)
{
PORTB=1;
for (zaehler=0; zaehler<18; zaehler++)
asm volatile("nop");
PORTB=0;
for (zaehler=0; zaehler<18; zaehler++)
asm volatile("nop");
}
}

void halbbit_low(void)
{
uint16_t zaehler;

//890us Pause
for (zaehler=0; zaehler<1186; zaehler++)
asm volatile("nop");
}

//Eine 0 oder 1 senden
void Send_Bit(uint8_t code)
{
if (code==0)
{
halbbit_high();
halbbit_low();
}
else
{
halbbit_low();
halbbit_high();
}
}


void send_code(uint8_t toggle, uint8_t address, uint8_t command)
{
uint8_t mask,i;

Send_Bit(1); //Erstes Startbit=1
Send_Bit(1); //Zweites Startbit=1

//Togglebit
if(toggle==0)
{
Send_Bit(0);
}
else
{
Send_Bit(1);
}

//5 Bit Addresscode
mask=0x10; //Beginn bei MSB

for(i=0; i<5; i++)
{
if(address&mask) //Send 1
{
Send_Bit(1);
}
else //Send 0
{
Send_Bit(0);
}

mask>>=1; //Nächstes Bit
}


//6 Bit Kommandocode
mask=0x20; //Beginn bei MSB

for(i=0; i<6; i++)
{
if(command&mask) //Send 1
{
Send_Bit(1);
}
else //Send 0
{
Send_Bit(0);
}
mask>>=1; //Nächstes Bit
}

//Übertragung komplett
PORTB=0; //IR-LED abschalten
ms_89(); // warte 89ms
}


int main(void)
{
DDRB=1;
uint8_t command,i;
command=37;

for (i = 14; i < command; i++)
{
send_code(1,27,i); // toggle, addresse, commando
}
}


wer andere programmvorschläge für die erleichterung hat kann diese noch reinbringen.

pebisoft
23.03.2005, 08:36
hallo, habe oben das programm geändert mit halbbit-routinen.
mfg pebisoft

Dino Dieter
23.03.2005, 13:32
Hallo

Das sieht doch schon sehr gut aus. Hier noch ein paar Anregungen.


void halbbit_high(void)
{
uint16_t i,zaehler;

Sollte man ändern in uint8_t.

Was mir noch nicht so richtig gefällt, ist das direkte beschreiben der Port
in den Funktionen.


for(i=0; i<32; i++)
{
PORTB=1; //einaml hier
for (zaehler=0; zaehler<18; zaehler++)
asm volatile("nop");
PORTB=0; //und hier
for (zaehler=0; zaehler<18; zaehler++)
asm volatile("nop");
}

Du beschreibst den ganzen Port neu und nicht nur ein Bit. Zu zweiten
hast du bei einer Änderung der Port die freudige Aufgabe, den ganzen Code zu durchsuchen.

Ich würde oben ein paar #defines einbauen und dort die PIN / Port zuweisen.

In der Art etwa


#define IR_LED_PORT PORTB
#define IR_LED_PIN 0
#define IR_LED_DDR DDRB

#define IR_LED_ON IR_LED_PORT |= (1<<IR_LED_PIN)
#define IR_LED_OFF IR_LED_PORT &= ~(1<<IR_LED_PIN)

Und oben noch eine grobe Beschreibung, was gemacht wird und wie lange
die Funktion benötigt. Dann ist es fast optimal.

MFG
Dieter

pebisoft
23.03.2005, 20:37
hallo, wer diesen artikel von anfang an durchgelesen hat, weiss um was es geht. er will dann auch nur, das die ir-diode senden kann und fummelt das programm auf seine masstsäbe um. darum sollte man die beschreibungen fast weglassen, kostet nur energie. was ich für sehr wichtig fand, ist, das wir es geschafft haben zum ersten mal mit dem avr vernünftigen und fehlerfreien 14-bit-code zu senden ohne einen interrupt zu blockieren.
mfg pebisoft

pebisoft
25.03.2005, 13:41
hallo, zeitkritische routinen kann man auch mit
dem programm "AVRdelayloop.exe" ist freeware, berechenen lassen.
man gibt z.b. die mhz an und die zeit z.b. 0,000014 (14us).
dann wird ein kleines asm programm erstellt. dieses kann man
den mit "mfile" unter "Assembler source file(s)" eintragen
und schon hat man als unterprogramm eine routine.
das programm muss die endung "S" haben z.b. "zeit.S".
kann man dann in winavr mit :
extern void zeit14_us(void);
extern void zeit890_us(void);
extern void zeit89_ms(void);
bekanntmachen und mit "zeit89_ms();" z.b. aufrufen.

ein beispiel für die "rc5-send" mit dem programm "AVRdelay" :




.global zeit14_us
.global zeit890_us
.global zeit89_ms

zeit14_us:

ldi R18, 0x25
WGLOOP0:
dec R18
brne WGLOOP0
nop
ret


zeit890_us:

ldi R18, 0x0A
WGLOOP2:
ldi R19, 0xEC
WGLOOP1:
dec R19
brne WGLOOP1
dec R18
brne WGLOOP2
nop
nop
ret

zeit89_ms:

ldi R18, 0x12
WGLOOP3:
ldi R19, 0x40
WGLOOP4:
ldi R20, 0xCD
WGLOOP5:
dec R20
brne WGLOOP5
dec R19
brne WGLOOP4
dec R18
brne WGLOOP3

ldi R18, 0x03
WGLOOP6:
dec R18
brne WGLOOP6
nop
ret
.end


mfg pebisoft