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)
Lesezeichen