Ich hab mal an meiner Funktionsbibliothek für den Yeti weiterprogrammiert.

Features:
- senden von Daten per Infrarotschnittstelle (ohne Angabe der Zeichenanzahl, direktes Senden von Zahlen)
- Messen von analogen Spannungen
- Überwachung der Akkuspannung
- Auslesen von zwei Eingabetastern
- Blinken der Frontleds, unabhängig vom Hauptprogramm
- Aktivierung eines Timer-Interrupts im Intervall von 33ms, um regelmäßig auszuführende Vorgänge unabhängig vom Hauptprogramm zu starten

Hier mal die derzeitige Version:

Code:
/*/////////////////////////////////////
// weitere Funktionen für den Yeti 	 //
// (c) Uwe Große-Wortmann (uwegw)    //
// Version 0.1   09.07.06            //
///////////////////////////////////////

Diese Datei enthält weitere Funktionen für den YETI:
- senden von Daten per Infrarotschnittstelle
- Messen von analogen Spannungen
- Überwachung der Akkuspannung
- Auslesen von zwei Eingabetastern
- Blinken der Frontleds, unabhängig vom Hauptprogramm
- Aktivierung eines Timer-Interrupts im Intervall von 33ms, um regelmäßig 
	auszuführende Vorgänge unabhängig vom Hauptprogramm auszuführen  

Integration dieser Datei in eigene Programme (siehe auch test.c): 

In der Haupt-c-Datei am Anfang:
#include "yeti_extended.c"

Im Programm folgende Funktion einfügen:
ISR(TIMER0_OVF_vect) //systick, alle 33ms
{
blinkmodus();
TastenPollen();
//an dieser Stelle können noch weitere Befehle stehen, die regelmäßig erledigt werden müssen!

} //end.systick

//Diese Funktion wird ausgeführt, sobald die linke  Taste gedrückt wurde:
void Aktion_Taste_L(void)
{
	
}

//Diese Funktion wird ausgeführt, sobald die rechte Taste gedrückt wurde:
void Aktion_Taste_R(void)
{

}


//Beim Programmstart in der Funktion main:
initExtended();
*/


//######################################################
// I. benötigte Funktionsbibliotheken
//######################################################
#include <stdlib.h>
#include <string.h>

#ifndef YETI_H
#include "yeti.h" //yeti.h muss vor yeti_extended.c bekannt sein. 
#endif

//######################################################
// II. Vom Benutzer zu ändernde Werte
//######################################################
/* Es können zwei Tasten ausgewertet werden, die an beliebigen Eingängen angeschlossen
sein können. Portnummer und Portname werden mit den folgenden Konstanten festgelegt.*/

//wenn keine Tasten angeschlossen sind, die folgende Zeile auskommentieren:
#define Tasten

//Voreinstellung ist linke Taste an PD7 und rechte Taste an PB4 
#ifdef Tasten
#define Taste_L_Pin 7
#define Taste_L_Port PORTD
#define Taste_R_Pin 4
#define Taste_R_Port PORTB
#endif




//######################################################
// III. Übersicht der enthaltenen Funktionen
//######################################################
// a) Funktionen, die vom Benutzer aufgerufen werden können
//Initialisierung, nötig für die folgenden Funktionen
void initExtended(void);
//String über RS232 ausgeben
void vPrint(unsigned char* pucUsrTmtDat);
//Zahl (16bit) über RS232 ausgeben
void vPrint_int(uint16_t zahl);
//Einen Kanal des Analog-digital-Wandlers auslesen
uint16_t ReadChannel(uint8_t mux);
//Die Akkuspannung messen und ausgeben
uint16_t akkutest(void);
//Die Tasten einlesen (per Timer regelmäßig aufrufen)
#ifdef Tasten 
void TastenPollen(void);
#endif
//Die Front-LEDs blinken lassen (per Timer regelmäßig aufrufen)
void blinkmodus(void);

// b) Funktionen, die nur intern innerhalb dieser Datei benötigt werden
//Den Timer0 für den Interrupt im 33ms-Rhytmus einstellen
void initsystick(void);

// c) Funktionen, die im Hauptprogramm vorhanden sein müssen
//Timer-Interrupt, wird alle 33ms aufgerufen
ISR(TIMER0_OVF_vect);
#ifdef Tasten 
void Aktion_Taste_L(void);
void Aktion_Taste_R(void);
#endif




//######################################################
// IV. Vom Benutzer benötigte (globale) Variablen
//######################################################
//Status Laufmodus
//0 heißt nicht Laufen, ungleich 0 heißt Laufen.
volatile uint8_t Laufmodus=0;
//Status Beeper
//0 heißt nicht piepen, ungleich 0 heißt piepen.
volatile uint8_t Beepmodus=0;

//Variablen für die Blinkfunktionen der Front-LEDs
//blink_x: Blink-Impulslänge in 33ms-Schritten, 0 deaktiviert das Blinken
volatile uint8_t blink_L= 0;
volatile uint8_t blink_R= 0;

////Ab hier müssen normalerweise kein Änderungen vom Benutzer vorgenommen werden////

//######################################################
// V. interne Variablen 
//######################################################

#define PIN(x) (*(&x - 2)) 
#define DDR(x) (*(&x - 1)) 

//Variablen für die Blinkfunktionen der Front-LEDs
//blink_count_x: Zähler für die Blinkschleife
volatile uint8_t blink_count_L = 0;
volatile uint8_t blink_count_R = 0;

//######################################################
// VI. Die einzelnen Funktionen  
//######################################################
void initsystick(void) //Timer0 für den Systick initialisieren und starten, alle 33ms ein Interrupt
{
//Timer 0 auf Prescaler 1024 setzen => alle 33ms ein Int
TCCR0 |= (1<<CS02)|(1<<CS00);
//Overflow-Interrupt aktiv
TIMSK |= (1<<TOIE0);
}

#ifdef Tasten 
//Bitfeld für die Tasten
volatile struct {
    uint8_t L:1;  //Status der Tasten, 1 wenn 
    uint8_t R:1;  //gedrückt, 0 wenn offen
	
	uint8_t L_cnt:1; //vorheriger Zustand der Tasten, 
    uint8_t R_cnt:1; //zur Erkennung von Schaltflanken
	}Taste;

void TastenPollen(void)
{
////////////Linke Taste //////////////
//schaltet Laufmodus um 
 if (bit_is_clear(PIN(Taste_L_Port),Taste_L_Pin)) //momentan gedrückt
	{
		if (Taste.L_cnt==0) //Flanke erkannt; Taste wurde gerade gedrückt 
		{
		Taste.L = 1;
		Aktion_Taste_L();
		}
		Taste.L_cnt=1;
	}
	else  //momentan offen 
	{
		if (Taste.L_cnt==1)  //Flanke erkannt; Taste wurde gerade losgelassen 
		{
		Taste.L = 0;
		}
		Taste.L_cnt=0;
	}

///////////Rechte Taste/////////////

 if(bit_is_clear(PIN(Taste_R_Port),Taste_R_Pin)) //momentan gedrückt
	{
		if (Taste.R_cnt==0) //Flanke erkannt; Taste wurde gerade gedrückt 
		{
		Taste.R = 1;
		Aktion_Taste_R();
		
		}
		Taste.R_cnt=1;
	}
	else  //momentan offen 
	{
		if (Taste.R_cnt==1)  //Flanke erkannt; Taste wurde gerade losgelassen 
		{
		Taste.R = 0;
		}
		Taste.R_cnt=0;
	}	
/////////////////////////////
}//end.TastenPollen
#endif

//Blinkmodus//
void blinkmodus(void)
{
 if (blink_L!=0) 
	{
		blink_count_L++;
		if (blink_count_L>blink_L) 
			{
				blink_count_L=1;
				LEFT_FRONT_LED_TOGGLE;
			}
	}
		
 if (blink_R!=0) 
	{
		blink_count_R++;
		if (blink_count_R>blink_R) 
			{
				blink_count_R=1;
				RIGHT_FRONT_LED_TOGGLE;
			}
	}
}//end.blinkmodus//


//######################################################
//Funktionen zur Ausgabe über die Infrarotschnittstelle
//######################################################

/* Gibt einen String über die Infrarotsschnittstelle aus, ohne dass die Anzahl der zu übetragenden Zeichen
 übergeben werden muss. Dazu wird mit strlen der String durchgezählt und dann vRs232Write aufgerufen.*/ 
void vPrint(unsigned char* pucUsrTmtDat)
{
unsigned char ucNofTmtChr=strlen(pucUsrTmtDat);
vRs232Write(pucUsrTmtDat,ucNofTmtChr);
} //end.vPrint

/* Gibt eine 16bit-Zahl über die Infrarotsschnittstelle aus*/ 
void vPrint_int(uint16_t zahl)
{
unsigned char zahlstr[5];
itoa(zahl, zahlstr,10);
vPrint(zahlstr);
} //end.vPrint_int


//######################################################
//Funktionen für den Analog-digital-Wandler
//######################################################
/* Liest einen Kanal des Anaolg-Digital-Wandlers aus
Quelle: mikrocontroller.net AVR-GCC Tutorial
Übetrgabeparameter: mux ==> Kanal (0..5)
Rückgabe: Messwert vom ADC (16bit)
Der ADC wird vor jeder Messung aktiviert, da die Ultraschall-Routine ihn abgeschaltet haben könnte.
*/
uint16_t ReadChannel(uint8_t mux)
{
  uint8_t i;
  uint16_t result = 0;
   ADCSR |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS2);    // Frequenzvorteiler setzen auf 64 (125000Hz) und 
														//ADC aktivieren
  ADMUX = mux;       // Kanal waehlen
  ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen 
  //"Dummy-Readout"*/
 ADCSR |= (1<<ADSC);              // eine ADC-Wandlung 
  while ( ADCSR & (1<<ADSC) );     // auf Abschluss der Konvertierung warten 
// Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen 
  for(i=0;i<4;i++)
  {
    ADCSR |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSR & (1<<ADSC) );   // auf Abschluss der Konvertierung warten
    result += ADCW;		    // Wandlungsergebnisse aufaddieren
  }
  result /= 4;     // Summe durch vier teilen = arithm. Mittelwert
  return result;
} //end.ReadChannel

//Der ADC-Kanal, an dem die Akkuspannung gemessen werden kann.
#define akkumess_port 5
/*Misst die Akkuspannung und gibt den ungefähren Ladezustand über die Infrarotschnittstelle aus. 
Der Akku ist an Kanal5 angeschlossen (in akkumess_port definiert)
Die Grenzen für die einzelnen Bereiche sind im folgenden Quelltext angegeben. 
Je nach interner Referenzspannung kann es nötig sein, die Werte zu korrigieren. 
Rückgabe: Messwert vom ADC (16bit)*/
uint16_t akkutest(void)
{
	uint16_t akkuspannung = 0;
	akkuspannung = ReadChannel(akkumess_port); //messen

	vPrint("\r\nAkkuwert: "); //Betexten
	vPrint_int(akkuspannung); //Rohwert ausgeben
	
	if (akkuspannung > 999) //ab 5,5V
	vPrint(" Akku Überspannung!");
	else if ((akkuspannung > 836)&(akkuspannung<1000)) //4,7 bis 5,4V
	vPrint(" Akku voll");
	else if ((akkuspannung > 764)&(akkuspannung<837)) //4,3 bis 4,6V
	vPrint(" Akku halbvoll");
	else if ((akkuspannung > 637)&(akkuspannung<765)) //3,8 bis 4,2V 
	//[der IR-Empfänger kann unter 4,5V schon Probleme bereiten!!!]
	vPrint(" Akku fast leer");
	else if (akkuspannung<638) //unter 3,8V
	vPrint(" Akku leer!");
	
	vPrint("\r\n");
	return akkuspannung;
} //end.akkutest


//initialiserung der Funktioen in dieser Datei
//Die Front-LEDs beginnen zu blinken
void initExtended(void)
{
	initsystick();
	#ifdef Tasten 
	blink_L = 6;
	blink_R = 2;
	Taste_L_Port|= (1<<Taste_L_Pin); //Pullups an für Tasten
	Taste_R_Port|= (1<<Taste_R_Pin); 
	DDR(Taste_L_Port) |= _BV(Taste_L_Pin); //Tasten als Eingänge
    DDR(Taste_R_Port) |= _BV(Taste_R_Pin);
	#endif
}	

//ende von yeti_extended.c
(speichern als yeti_extended.c)

Ein kleines Testprogramm, das den Gebrauch demonstriert:
Code:
//Beispiel für die Nutzung der yeti_extended.c

#include "yeti_extended.c"
#include "yeti.h"
#include "yetimove.c"


ISR(TIMER0_OVF_vect) //systick, alle 33ms
{
blinkmodus();
TastenPollen();
//an dieser Stelle können noch weitere Befehle stehen, die regelmäßig erledigt werden müssen!

} //end.systick


//Diese Funktion wird ausgeführt, sobald die linke  Taste gedrückt wurde:
void Aktion_Taste_L(void)
{
	
}


//Diese Funktion wird ausgeführt, sobald die rechte Taste gedrückt wurde:
void Aktion_Taste_R(void)
{

}

int main(void)
{
	vInitYeti();//init micro controller unit to correctly control main pcb hardware
	initExtended(); //erweiterte Funktionen initialisieren
	//transmit yeti version 
	vPrint("\r\nYeti, V1.06\r\n");
	vPrint("YETI sagt Hallo Welt\r\n");
	vStandUpright();
	//yeti ready sound
	vBeep(400,80);
	vBeep(520,80);
	vBeep(360,80);
	vBeep(580,80);	
	
while(1) //hauptschleife
{	
	
	if (Beepmodus !=0)
	{
	vBeep(400,30);
	}
	
	vWaitMilliseconds(500);
	
	vPrint(" Teste erweiterte Funktionen...\r\n");	
	vPrint("Zahlen ausgeben:\r\n");
	for (uint8_t i=1;i<11;i++) 
		{ 	vPrint_int(i);
			vPrint("\r\n");	//Zeilenumbruch im Terminal 
		}
	
	
	if (Laufmodus !=0) 
	{
	vPrint("Laufmodus aktiv... mache einen Schritt\r\n");	
	vMoveForwardXSteps(1);	
	}
	else
	{
	vPrint("Laufmodus inaktiv... stehenbleiben\r\n");		
	}	
}//end.hauptschleife

	return 0;
} //end.main

//ende von test.c
(abspeichern als test.c)