Programmierkurs für PIC-Mikrocontroller in C (CC5X Compiler)
 Teil 3 Fehlersuche

Sehr oft, besonders wenn man hat erst angefangen zu programmieren, schleichen Fehlern in Programm ein. Und bei einem Mikrocontroller ist schwierig sie zu suchen . Weil es gibt wenig Möglichkeiten zu erfahren, was geht da wirklich ab. Einer der Möglichkeiten ist Assemblerprogramm im MPLAB zu kompilieren und anschließend zu simulieren. Auf diese weise lassen sich Variableninhalte, Schleifen, und Programmablauf beobachten.  Auf diese Weise lassen sich logische Fehlern finden. Sobald Signale von außen in Spiel sind und Signale sind zeitbezogen, wird simulieren auf  PC unmöglich. Trotzdem gibt es kleine Tricks, welche helfen raus zu kriegen an welche Stelle bricht sich Programm ab.

Breakpoint läst sich mit einem Taster realisieren. Programm lauft bis einer Stelle und bleibt da stehen bis Taster betätigt wird.

Während Programm in Schleife lauft, kann man Spannungspegeln an Pins mit dem Voltmeter messen oder mit Digitaltester  anschauen.

Dann wird Taster betätigt und Programm läuft  zum nächsten Breackpoint.

Andere Möglichkeit ist, an einem Pin ein Piezowandler anzuschließen und Piepstöne ausgeben. In folgendem   Programm sind 6 Piepstöne eingebaut. Durch Zählen der  Piepstöne finden wir die Stelle oder wenigstens Abschnitt mit dem Fehler.

// Taktfrequenz 4MHz

 

#include <C:\cc5\16F84.h>                // Prozessor-Typ definieren

#pragma config |= 0b.1111.1111.0010      // Konfigurations-Wort

 

bit beep @ PORTB.0;                      // Port definieren an dem Piezowandler ist angeschlossen

bit Taster @ PORTB.1;                    // Port definieren an dem Taster ist angeschlossen

#include <PipTast.c>                     // Hier befinden sich Unterprogramme pip() und tast()

 

void main(void)                               

{

TRISB = 0b.1111.1110;              // Pin 6 –Ausgang (Piezowandler), alle andere Eingänge

pip();                             // Nachdem Einschalten 2 mal piepsen

pip();                             // und so mit Betriebsbereitschaft signalisieren

tast();                            // Hier warten bis Knopf betätigt und losgelassen wird

pip();                             // Danach ein mal Piepsen

tast();                            // Wieder warten bis Knopf betätigt und losgelassen wird

pip();                            

pip();                             // 3 mal Piepsen

pip();

}

Wenn wir Programm ausprobieren, dann wissen wir genau, an welcher Stelle in Quellcode es sich befindet.

Wenn ein Speicherosziloskop zu Hand ist, kann man Ausgabe des Mikrocontrollers auf Bildschirm beobachten. Das ist praktisch einzige Möglichkeit   Programm-Ablauf-Dauer zu messen. Aber meistens kann man es durch Nachzählen von Assemblerbefehls ausrechnen.  

Alle Befehle brauchen Zeit f/4 , außer Sprungbefehlen RETURN, RETLW, RETFILE, GOTO, CALL, die brauchen f/8. Befehle DECFSZ, INCFSZ, BTFSC, BTFSS in normal Fall f/4, wenn nachfolgende Befehl übersprungen wird, dann f/8.

 

Mit einem Logiktester lässt sich Pin - Zustand anzeigen. Grün - 0, Rot - 1, Beide - Pin ist hochohmig , gar keiner - keine Spannungsversorgung. Ein Piezowandler macht hörbar schmale Impulse, welche an LED nicht sichtbar sind. 

 

Eine große Hilfe leistet ein einfacher Adapter zu seriellr Schnittstelle des Rechners und Unterprogramm zur seriellen Kommunikation. Damit kann man Variablen auslesen , Werte ins Programm übertragen. Eine Terminalprogramm am Rechner sendet  und empfängt Zeichen von PIC. Ich verwende ttermpro.exe oder ein selbstgemachtes Programm (wobei eigene ist bequemer, weil die empfangene Zeichen  auch als Zahlen dardestellt werden ). Beispiel der Verwendung serielles Unterprogramms: PIC sendet und empfängt Daten  mit 9600 Baud, kein Paritätsbit ,8 Bit,1 Stop-Bit. Wenn ein Zeichen von PC erwartet wird, bleibt Programm stehen, bis Zeichen empfangen ist.

 

// 4 MHz

#include <C:\cc5\16F84.H>

 

#pragma bit Opin @ PORTA.0         // Ausgang für serielle Daten definieren

#pragma bit Ipin @ PORTA.1         // Eingang für serielle Daten definieren

#include <Seriel4.c>               // Beinhaltet Treiber zu serieller Kommunikation

 

void main(void)

{

TRISA = 0b.1111.1110;              // Nicht vergessen, Ein/Ausgänge einstellen

TRISB = 0b.0000.0000;

anfang:

 

PORTB = empfang();                 // Zeichen empfangen und ins Register PORTB übertragen

senden(PORTB);                     // Wert des PORTB seriell senden

goto  anfang;

}

 

Funktion „empfang()“ übergibt eine 8-Bit-Zahl (0..255). Funktion „senden(7)“ braucht ein Parameter , Zahl die gesendet wird. Zum Beispiel senden(170); senden(‚K’);. Funktion SerString("Ein1"); sendet ganzes Wort oder Satz. Hier ist Foto des Testaufbaus.

Zum Schaltung: Sie wundern sich wahrscheinlich, dass TTL – IC an seriellem Port des Rechners einfach so angeschlossen ist. Es funktioniert aber. Nach Tabellenbuch  „1“ist -3V...-15V und „0“ ist +3V...+15V. Durch Experimente habe ich festgestellt, dass 0V als „1“ erkannt werden und mehrer als +3V als „0“ erkannt. Und dies alles mit einem Nullmodemkabel mit 2m Länge funktioniert ziemlich sicher. Ausgangspannung der seriellen Schnittstelle (-12V...+12V) wird mit einer Zehnerdiode auf  –0,7V...+5,1V stabilisiert. 

 

Programmentwicklung

Am Anfang gibt es eine Idee. Funktion des Gerätes ausdenken. Hardware ausdenken, Anbindungen an andere ICs. Versuchsaufbau. Einzelne Programmchen entwickeln, die Hardware ansprechen. Einzelne Hardwareteile per Programmchen testen. Diese einzelne Testprogramme in Unterprogramme umbauen und universeller machen( Treibern bilden ). Hauptprogramm machen in dem man Zusammenspiel einzelner Hardwareteilen bestimmt.

(Ich plane sogenannte Treibern, die ich benutze, auf dieser Homepage auszulegen )

Wenn Ihnen gelungen ist das etwas funktioniert, dann speichern Sie das Programm. Wenn Sie weiter am Programm  arbeiten und es geht nichts mehr, dann haben Sie Möglichkeit zurück an dem Punkt zu gehen, wo es noch funktioniert hat. Man kann dann auch alte Version mit neuen vergleichen um Raszufinden wie neue Code funktionierendes Programm beeinflusst .   

Mögliche Fehlern

Ein C-Programm ist erfolgreich kompiliert und in PIC gebrannt . Mikrocontroller macht nichts.

Spannungsversorgung prüfen.

Mit Osziloskop prüfen, ob Quarz schwingt. Wenn nicht, Einstellung des Konfigurationswortes prüfen.

Wenn Quarz schwingt, Spannungspegel  an MCLR - Pin  prüfen, er soll 5V sein. (sonst Dauerreset)

Ermitteln Schaltzustände an Pins: High, Low oder hochohmig. Mit Port-Einstellung in Programm vergleichen. TRISx-Befehl.

Nachschauen, welchem Programmteil entsprechen  diese Port–Zustände.

Mikrocontroller macht etwas.

In Programmcode suchen.  Wen alles logisch und richtig scheint zu sein, und PIC trotz dem Unsinn macht, und Sie wissen nicht weiter, dann gehen Sie schlafen. Am nächsten, Tag am besten morgen, durchdenken Sie das Programm.(Wirksamste Methode bei mir ).

Fallen: Speicherbank vergessen umzuschalten, Speicherbank zurückschalten, Ein/Ausgänge falsch konfiguriert. Interrupt ausersehen aktiviert, benutzen gleicher Variable in geschachtelten Schleifen, Unterprogramm ruft Unterprogramm geschachtelt mehr als 8 mal.