C-Programming Hands-on Teil 2 Björn Meyer Fachgebiet Technische Informatik 1
Inhalt dieser Hands-on Session Vorstellung projektrelevanter Funktionalitäten EK-EVALBOT Firmware Development Package Stellaris Peripheral Driver Library Stellaris IQmath Library Aufgaben 2
Firmware Dev. Package Sensor- und Aktor-Module Display Ansteuerung LED / Taster Motor Ansteuerung Radencoder und Bumper Ablaufsteuerung Kommandozeilentool Einfacher Task Scheduler Serielle Kommunikation UART Standard I/O Modul 3
Funktionen zum: Initialisieren An- Ausschalten Display löschen Zeichnen von Strings Zeichnen von Bildern // Print the string centered tboolean bclear = true; Display96x16x1StringDrawCentered(pcStr, uly, bclear); Display96x16x1Clear(); // Print a string with length restriction unsigned long ullen = 11; Display96x16x1StringDrawLen(pcStr, ullen, ulx, uly); Display96x16x1Clear(); // Turn the display off Display96x16x1DisplayOff(); Display Ansteuerung // Initialize the display with fast I2C Display96x16x1Init(true); // Turn the display on Display96x16x1DisplayOn(); // Print a text to the OLED Display const char *pcstr = Displaytext ; unsigned long ulx = 0; unsigned long uly = 0; //valid: 0 or 1 Display96x16x1StringDraw(pcStr, ulx, uly); // clear the display content Display96x16x1Clear(); 4
LED und Taster Ansteuerung LED An / Aus Blinken Taster Ohne Entprellfunktionalität Entprellfunktion // Init the LEDs LEDsInit(); // Turn LED 1 ON LED_On(LED_1); // Toggle LED 2 LED_Toggle(LED_2); // wait for some time // Turn LED OFF LED_Off(LED_1); LED_Off(LED_2); // Initialize the buttons PushButtonsInit(); tboolean b1_p = false; tboolean b2_p = false; for (;;) { // Call this function periodically // better: use timer (e.g. 10ms) PushButtonDebouncer(); b1_p = PushButtonGetDebounced(BUTTON_1); b2_p = PushButtonGetDebounced(BUTTON_2); if (b1_p) { LED_On(LED_1); } if (b2_p) { LED_Off(LED_1); } } 5
Initialisieren Motor-, Richtungs- und Geschwindigkeits-Wahl LEFT_SIDE or RIGHT_SIDE FORWARD or REVERSE Geschwindigkeit Start / Stop // Initialize the motor driver MotorsInit(); // Set the motor direction of the left motor MotorDir(LEFT_SIDE, FORWARD); // Set the motor speed of the left motor to 50% MotorSpeed(LEFT_SIDE, (50 << 8)); // Start the left motor MotorRun(LEFT_SIDE); // some times later: MotorStop(LEFT_SIDE); Motor Ansteuerung 6
Rad-Encoder und Bumper Bumper Rad Rotation // Include the drivers.h #include sensors.h tboolean b1_p = false; tboolean b2_p = false; BumpSensorsInit(); for(;;) { // Call periodically the debouncer BumpSensorDebouncer(); // Get the current status of a bumper b1_p = BumpSensorGetDebounced(BUMP_LEFT); b2_p = BumpSensorGetDebounced(BUMP_RIGHT); if (b1_p) { LED_On(LED_1); } if (b2_p) { LED_Off(LED_1); } } // Include the drivers.h #include sensors.h computespeedfunc(twheel ewheel) { // compute the speed } // Initialize and enable the sensors // Specification of a call-back function // -> will be called on each pulse WheelSensorsInit(computeSpeedFunc); WheelSensorEnable(); // Enable the interrupt for the left wheel WheelSensorIntEnable(WHEEL_LEFT); 7
Kommandozeilentool Einfache Schnittstelle für die Kommandozeile Anwendung: Steuerung eines Bots z.b. über UART Funktionsweise: Eingabe: Buffer, der einen String enthält Eingabe String wird in Kommandos und Parameter unterteilt Kommando wird in einer definierten Tabelle gesucht Wird das Kommando gefunden, wird die zugehörige Funktion mit den übergeben Parametern aufgerufen 8
Beispiel // The foo function int ProcessFoo(int argc, char *argv[]) { // Do something } // Help Function: shows the user possible commands int ProcessHelp(int argc, char *argv[]) { // Do something } // The table with the supported commands (by the app) tcmdlineentry g_scmdtable[] = { { "foo", ProcessFoo, "The foo command." }, { "help", ProcessHelp, "Application help." } }; // Test function for command processing int Test(void) { // A buffer for the user command unsigned char puccmd[256]; // Retrieve a command from the user into puccmd. UARTgets(&pucCmd, 256); // Process the command line. return(cmdlineprocess(puccmd)); } Kommandozeilentool 9
Einfacher Task Scheduler Für Anwendungen, die Funktionen in bestimmten Zeitabständen aufrufen Task Tabelle Listet Funktionen Task Definition Funktions-Zeiger Funktions-Parameter Zeitintervall zwischen aufeinander folgenden Aufrufen Flag zum Aktivieren der Task Struct: typedef struct { void (*pfnfunction)(void *); void *pvparam; unsigned long ulfrequencyticks; unsigned long ullastcall; tboolean bactive; } tschedulertask 10
Einfacher Task Scheduler Beispiel // Define system tick rate. Here: result in 10ms tick period #define TICKS_PER_SECOND 100 // Function prototypes static void Foo(void *pvparam); static void ToggleLED(void *pvparam); // Definition of the function table tschedulertask g_psschedulertable[] = { {ToggleLED, (void *)0, 50, 0, true}, {Foo, (void *)0, 10, 0, true} }; // Compute the number of table entries unsigned long g_ulschedulernumtasks = (sizeof(g_psschedulertable) / sizeof(tschedulertask)); static void ToggleLED(void *pvparam) { long lstate; lstate = GPIOPinRead(LED_GPIO_BASE (pvparam? LED1_GPIO_PIN : LED0_GPIO_PIN)); GPIOPinWrite(LED_GPIO_BASE, (pvparam? LED1_GPIO_PIN : LED0_GPIO_PIN), ~lstate); } static void Foo(void *pvparam) { // Do something } 11
Einfacher Task Scheduler Beispiel... // The main task int main(void) { // Initialize system clock and any peripherals that are to be used. SystemInit(); // Initialize the task scheduler and configure the SysTick to interrupt // 100 times per second. SchedulerInit(TICKS_PER_SECOND); // Turn on interrupts at the CPU level. IntMasterEnable(); for(;;) { // Tell the scheduler to call any periodic task that are due to be called SchedulerRun(); } } 12
Einfache Verwendung von UART UARTprintf() UARTgets() UART Standard I/O Modul Unbuffered Mode UART_BUFFERED beim Build des Moduls deaktiviert Kein unmittelbarer Rücksprung nach dem Aufruf einer Modulfunktion Programm wartet bis z.b. UARTprintf() seine Daten in den UART FIFO geschrieben hat Buffered Mode UART_BUFFERED beim Build des Moduls aktiviert UART HW FIFO wird im SRAM erweitert UART Interrupt werden dazu benutzt Daten vom SRAM in den HW FIFO zu schieben UARTStdioIntHandler() muss von der Anwendung aufgerufen werden 13
UART Standard I/O Modul Achtung: UARTprintf() verwirft die verbleibenden Zeichen eines Strings, wenn der Ausgabe-Buffer voll ist Sicherstellen, dass Ausgabe-Buffer leer ist: UARTFlushTx() String sollte nicht größer als der Buffer im SRAM sein Erkennen eines Zeilenendes: UARTPeek() Beispiel: // Configure the appropriate pins as UART pins; // in this case, PA0/PA1 are used for UART0. SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 GPIO_PIN_1); // Initialize the UART standard IO module. UARTStdioInit(0); // Print a string. UARTprintf("Hello world\n"); 14
Bietet zwei Pogrammiermodelle Beide Modelle sind kombiniert nutzbar Peripheral Driver Library Software Treiber (schnellere Entwicklung, wenn Geschwindigkeit unkritisch) Direkter Registerzugriff (kleine Codegröße, effizient, hohe Geschwindigkeit) Peripherie wird durch direktes schreiben von Registern programmiert (Vereinfachter Zugriff: Makros: inc/lm3s9b92.h) Namenskonvention Makros: Register CR0 in Modul SSI0: SSIO_CR0_R Analog Digital Converter (ADC) GPIO 15
Analog Digital Converter (ADC) Bis zu 8 Kanäle (plus interner Temperatursensor) Funktionsübersicht: Abtastung einstellbar Lesen der Messwerte Setzen eines Interrupt Handlers Interrupt maskieren/löschen Aufzeichnung von 4 Messfolgen: 1. Folge: 8 Messwerte 2./3. Folge: 4 Messwerte 4. Folge: 1 Messwert Messwerte einer Folge können von gleichen oder unterschiedlichen Kanälen stammen Prioritäten für Messfolgen einstellbar à Reihenfolge, wenn mehrere konfigurierte Events gleichzeitig anliegen 16
Verwendung von Oversampling Entfernung von Rauschen / Störsignalen Analog Digital Converter (ADC) Verbesserung des SNR und der Liniarität des ADC Hardware Oversampling Einstellung für alle Messfolgen Unterstützte Oversampling Faktoren: 2x, 4x, 8x, 16x, 32x Verringert den Durchsatz in Abhängigkeit vom gewählten Faktor Software Oversampling Pro Messfolge konfigurierbar Unterstützte Oversampling Faktoren: 2x, 4x, 8x Reduziert die Anzahl Messwerte pro Messfolge (z.b. 1. Messfolge, SW Oversampling 2x à nur noch 4 Messwerte) 17
API Funktionsübersicht Konfiguration von Messfolgen Aktivieren / Deaktivieren von Messfolgen Daten einer Messung auslesen FIFO Over- und Underflow Behandlung Einstellen des Oversamplings Prozessor Trigger Interrupt Behandlung Analog Digital Converter (ADC) 18
Analog Digital Converter (ADC) Beispiel unsigned long ulvalue; // Enable the first sample sequence to capture the value of channel 0 when // the processor trigger occurs. ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0); ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_IE ADC_CTL_END ADC_CTL_CH0); ADCSequenceEnable(ADC0_BASE, 0); // Trigger the sample sequence. ADCProcessorTrigger(ADC0_BASE, 0); // Wait until the sample sequence has completed. while(adcintstatus(adc0_base, 0, false)) { } // Read the value from the ADC. ADCSequenceDataGet(ADC0_BASE, 0, &ulvalue); 19
Überblick Bis zu 8 GPIO Bänke mit jeweils bis zu 8 Ein-/Ausgängen Eigenschaften eines I/O Pins: Konfigurierbar als Ein- / Ausgang; Default: Eingang Eingang kann Interrupt erzeugen (abhängig vom Signalpegel oder Flanke) Ausgang kann 2mA, 4mA oder 8mA treiben; Default: 2mA Optional weak pull-up oder pull-down Widerstand konfigurierbar Optional Open-Drain konfigurierbar GPIO oder Peripherie konfigurierbar GPIO 20
GPIO Aktivieren des Interrupt Handlers auf Port Ebene PINs als Eingänge konfigurieren PINs als Ausgänge konfigurieren Steigende Flanke als Interrupt Event High-Level als Interrupt Event PINs auslesen PINs schreiben GPIOPortIntRegister(GPIO_PORTA_BASE, PortAIntHandler); GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_2 GPIO_PIN_4); GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_0 GPIO_PIN_3); GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_RISING_EDGE); GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_PIN_5, GPIO_HIGH_LEVEL); int ival; ival = GPIOPinRead(GPIO_PORTA_BASE, (GPIO_PIN_0 GPIO_PIN_2 GPIO_PIN_3 GPIO_PIN_4 GPIO_PIN_5)); GPIOPinWrite(GPIO_PORTA_BASE, (GPIO_PIN_0), 0xF8); 21
IQmath Library Bibliothek für Festkommaberechnungen Einsatz nötig, da keine Fließkommaeinheit vorhanden ist Funktionsumfang Optimierte floating point Operationen 32 Bit floating point Verschiedene Bereiche nutzbar (IQ1 bis IQ30) Format Konvertierung Arithmetische Funktionen (mult, div,...) Trigonometrische Funktionen (sin, cos,...) Weitere mathematische Funktionen (exp, sqrt,...) Verschiedenes (abs,...) 22
Aufgaben Drei Aufgaben zur Auswahl Jede sollte mindestens einmal bearbeitet werden 23