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:
(speichern als yeti_extended.c)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
Ein kleines Testprogramm, das den Gebrauch demonstriert:
(abspeichern als test.c)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







Zitieren

Lesezeichen