|
Bitte beachte die Copyrighthinweise.
PIDRegler mit 80C537 in C51
1 Aufgabenstellung
· Programmierung eines PID-Reglers in C51
2 C51 Compiler (Windows)
Vor dem Starten von Windows wurde folgende Batchdatei ausgeführt, die die Pfade des BIN/, INC und LIB Verzeichnisses setzt. Somit muss dies nicht bei jedem neuen Projekt unter [Options]-[Environment Pathspecs] eingestellt werden. Wird dies nicht durchgeführt, erscheint die Fehlermeldung: Could not execute Translator.
C51a.bat:
@rem Umgebung fuer uVision C51 Compiler setzen
path =g:\c51eval\bin;%path%
SET C51LIB=G:\C51EVAL\LIB
SET C51INC=G:\C51EVAL\INC
Danach wurde Windows und das Programm mVision/51 evaluation (Bin\uvw51e.exe) gestartet (Eval Version 1.01, Toolset Keil 8051 C Compiler ver5).
Zum Schreiben, zur Fehlersuche und zum Testen der Übersetzbarkeit reicht es, nur die *.C - Datei zu laden und über [Project]-[Compile File] zu kompilieren. Hierbei wird jedoch nur eine *.OBJ - Datei erzeugt. Möchte man das Programm auf den Microcontroller mittels des Monitors M51 ausführen, benötigt man eine *.HEX - Datei.
Dazu ist es nötig, über [Project]-[New Project] ein neues Projekt anzulegen und die Quelldatei über [Insert] hinzuzufügen. Über [Project]-[Make: Build Project] kann nun die *.HEX - Datei erstellt werden.
2.1 Aufgetretene Fehler und Ursachen:
Fehler |
Ursache |
Lösung |
Could not execute Translator. |
Pfade nicht gesetzt. |
Pfade über [Options] oder Batchdatei setzten. |
Linking *** Error: Command File <Pfad> not found |
Verzeichnisname enthält einen Bindestrich. |
Verzeichnis umbenennen. |
Could not read RETVAL file |
Projektdateien befinden sich im ROOT-Verzeichnis eines Datenträgers. |
Dateien in Unterverzeichnis verschieben. |
Linking *** Fatal Error 210 I/O Error on Input File Exeption 0021H: Path or File not found File: <Pfad><*.OBJ> |
Im selben Verzeichnis befindet sich die Datei C51.bat. |
C51.bat umbenennen (Wird vermutlich statt BIN\C51.EXE ausgeführt). |
3 Testprogramm
Vor dem Testen des eigentlichen PID-Reglers wurde ein Testprogramm ausgeführt, welches auf Port 4 Flanken ausgibt.
51Test2.c:
/*************************************************************************
/* Editor: Rosenauer, Schnabel @ HTBLA Karlstein, Austria-3830 Waidhofen
/* Datum: 30/Jan/1997 Klasse/Gruppe/Kat.Nr : V-EA/-/--
/*************************************************************************
/* Sprache : C51 fuer MC 80C537
/* Programm Nr. : Labor Gamper VEA 14
/* Kurzbeschreibung : Testprogramm, gibt auf P4.0 Flanken aus
/* geht mit und ohne 'defines' am Anfang
/*************************************************************************
*/
// const float VERSION = 1.00;
/************************************************************************/
#include <reg517.h>
#include <stdio.h>
#define Kp 10 /* max. 255 */
#define Ta 1 /* ms */
#define Tn 100 /* ms */
#define Tv 2000 /* ms */
void main()
{
for (;;) P4++;
}
Nach dem Kompilieren des Projekts konnten mit dem Oszilloskop P1 die Flanken gemessen werden, das Programm funktionierte.
Die #defines am Anfang stammten noch vom PID-Regler. Das Programm funktionierte wie erwartet unabhängig von ihrem Vorhandensein.
Es wurde noch folgende main Routine getestet, die ebenfalls funktionierte:
51Test3.c (main - Routine):
void main()
{
while (1) P4++;
}
4 PID-Regler
Das Programm konnte kompiliert, aus Zeitgründen jedoch nicht mehr getestet werden.
/*************************************************************************
/* Editor: Rosenauer, Schnabel @ HTBLA Karlstein, Austria-3830 Waidhofen
/* Datum: 30/Jan/1997 Klasse/Gruppe/Kat.Nr : IV-EA/-/--
/*************************************************************************
/* Sprache : C51 fuer MC 80C537
/* Programm Nr. : Labor Gamper VEA 14
/* Kurzbeschreibung : PI-Regler
/*
/*************************************************************************
*/
// const float VERSION = 0.21;
/************************************************************************/
#include <reg517.h>
#include <stdio.h>
#define Kp 10 /* max. 255 */
#define Ta 1 /* ms */
#define Tn 100 /* ms */
#define Tv 2000 /* ms */
signed int ea, ia;
unsigned char Pid (unsigned char w, unsigned char xu, bit piden)
{
signed int e, p, i, pid16;
signed long d, pid32;
unsigned char ret;
e = (signed int) w-xu;
p = e*Kp;
if (e>0 && p<0) p=32767;
if (e<0 && p>0) p=-32768;
if (piden == 1)
{
i = ia+(e / (Tn/(Ta*Kp)));
if (ia>0 && e>0 && i<0) i=32767;
if (ia<0 && e<0 && i>0) i=-32768;
d = (signed long) (e-ea) * ((Kp*Tv)/Ta);
if (d>32767) d=32767;
if (d<-32768) d=-32768;
}
else
{
i = 0;
d = 0;
}
pid32 = (signed long) p+i+d;
if (pid32>32767) pid16=32767;
else if (pid32<-32768) pid16=-32768;
else pid16 = (signed int) pid32;
pid16 = (pid16/256)+128;
ret = (unsigned char) pid16;
ea = e;
ia = i;
return (ret);
}
void t2ov () interrupt 5 using 0
{
unsigned int w, xu, out;
ADCON1 = 0; /* Kanal 0 P7.0 */
DAPR = 0; /* starten */
while (BSY == 1); /* warten*/
w = ADDAT; /* Ergebnis auf w schreiben */
ADCON1 = 1; /* Kanal 1 P7.1 */
DAPR = 0; /* starten */
while (BSY == 1); /* warten */
xu = ADDAT; /* Ergebnis auf xu schreiben */
out = Pid(w,xu,1); /* berechnen */
P4 = out; /* ausgeben */
}
void Init()
{
/**************** T2 ***************/
T2CON = T2CON | 0x10; /* Auto-Reload ein */
T2CON = T2CON | 0x70;
CRC = 0xFFFF - (Ta*1000); /* Reloadwert */
T2 = 0xFFFF - (Ta*1000); /* Anfangswert */
/**************** AD ***************/
ADCON0 = 0; /* keine dauernde Konversion */
/* kein externer Start */
/************ alles ein ************/
T2I0 = 1; /* T2 ein */
ET2 = 1; /* T2-Int ein */
EAL = 1; /* alle Int ein */
}
void main()
{
ea = 0;
ia = 0;
Init();
while (1);
}
5 Interpretation der Messergebnisse
Die Programmierung des 80C537 in C stellt eine komfortable Lösung dar - unter der Voraussetzung, dass sich die fehlerfreie Quelldatei kompilieren und linken lässt.