📄 fcancont.c51
字号:
#pragma large
#pragma debug
#pragma registerbank(3)
#pragma pagelength(80) pagewidth(110)
/***********************************************************************
************************************************************************
* *
* F U L L - C A N C O N T R O L L E R *
* *
************************************************************************
************************************************************************
* *
* Funktion: *
* *
* Direkte HW-Steuerung des Intel 82526 Full-CAN Controllers. *
* Ausf乭rung aller Low-Level Funktionen. Dieses Modul ist das *
* einzige, dass direkt in die HW-Register des CAN-Controllers *
* schreiben darf. *
* *
* Die Adressierung der einzelnen Objekte im DPRAM des Controllers *
* erscheint im ersten Moment vielleicht ein wenig simpel *
* gel攕t. Da bei dieser Implementation jedoch vorallem bez乬lich *
* des Laufzeitverhaltens optimiert wurde, liess sich ein gewisses *
* Mass an fehlender Eleganz nicht vermeiden.
* *
* *
* Filename : FCANCONT.C51 *
* *
* Modulename : FCANCONT *
* *
* Zielsystem : jedes 8051 System mit einem Intel 82526 *
* CAN-Controller *
* *
* Entwicklungssystem : Keil C-51 *
* *
************************************************************************
* Versionen: *
* *
* 1.0 28.01.1991 Th. Fischler : Erste Version *
* *
************************************************************************
* Copyright 1991 .. 2001 METTLER & FUCHS AG, CH-8953 Dietikon *
************************************************************************/
/*---------------------------------------------------------------------*
* D E F I N I T I O N E N *
*---------------------------------------------------------------------*/
#include "abbrev.h"
#include "fcancont.h"
#include "candefs.h"
/* Maximale Anzahl der Sende-Versuche bei Bus-Problemen */
/* von BCACNCONF.A51 */
extern const unsigned int code NBR_OF_SEND_TRIALS;
/* Definition der einzelnen Bits im STATUS-REGISTER */
/* des CAN-Controllers */
union can_status_typ {
struct {
byte reset_request : 1;
byte halt_status : 1;
byte error_status : 1;
byte transmit_status : 1;
byte rec_status : 1;
byte bus_status : 1;
byte dpram_status : 1;
byte : 1;
} status_bits;
byte status_byte;
};
/*---------------------------------------------------------------------*
* I M P O R T S *
*---------------------------------------------------------------------*/
#include "canutil.h"
/*---------------------------------------------------------------------*
* M O D U L G L O B A L E V A R I A B L E N *
*---------------------------------------------------------------------*/
/* Definition der Intel 82526 HW-Register, diese werden an die */
/* Speicherstelle des Symbols FCAN_REG im Assembler-Modul */
/* FCANCONF.A51 alloziert. (absolute Variable) */
extern xdata volatile union {
struct {
byte control;
byte status;
byte intr;
byte bus_tim_0;
byte bus_tim_1;
byte out_contr;
} r; /* Allgemeine Register im DPRAM */
byte mem[63]; /* Ganzes DPRAM als Array */
} fcan_reg;
#pragma eject
/*---------------------------------------------------------------------*
* L O K A L E P R O Z E D U R E N *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* C A N _ R E S E T _ R E Q U E S T
*---------------------------------------------------------------------*
* Funktion:
* Setzt den CAN-Controller in den Reset-Zustand
*
*---------------------------------------------------------------------*
* Parameter:
* --
*
*---------------------------------------------------------------------*/
static void can_reset_request (void)
{
fcan_reg.r.control = fcan_reg.r.control | 0x01;
/* Testen ob ein Reset-Request w刪rend dem Betrieb verlangt wurde */
/* und solange warten, bis Reset-Zustand quittiert wird */
while (!(fcan_reg.r.status & 0x01)) {
/* Falls n攖ig den Interrupt-Pointer zur乧ksetzen */
if (fcan_reg.r.intr != 0xff) {
fcan_reg.r.intr = 0xff;
}
}
/* Falls n攖ig den Interrupt-Pointer zur乧ksetzen */
if (fcan_reg.r.intr != 0xff) {
fcan_reg.r.intr = 0xff;
}
}
/*---------------------------------------------------------------------*
* C A N _ H A L T _ R E Q U E S T
*---------------------------------------------------------------------*
* Funktion:
* Setzt den CAN-Controller in den Halt-Zustand
*
*---------------------------------------------------------------------*
* Parameter:
* --
*
*---------------------------------------------------------------------*/
static void can_halt_request (void)
{
/* Status Register testen ob Controller Bus-Off ist */
if (fcan_reg.r.status & 0x20) {
/* Controller ist Bus-Off, Halt alleine gen乬t nicht */
/* Es muss ein Reset ausgel攕t werden */
can_reset_request();
}
/* Nur Halt-setzen falls nicht schon reset gesetzt ist */
if (!(fcan_reg.r.status & 0x01)) {
fcan_reg.r.control = fcan_reg.r.control | 0x02;
/* Nun Abwarten bis der Haltzustand vom Controller quittiert wird */
while (!(fcan_reg.r.status & 0x02));
}
}
/*---------------------------------------------------------------------*
* C A N _ S E T _ I M P
*---------------------------------------------------------------------*
* Funktion:
* Setzt das IMP-Access-Flag des durch OBJ_ADR adressierten Objektes
*
*---------------------------------------------------------------------*
* Parameter:
*
* obj_adr : Interne Start-Adresse des Objektes
* (siehe C_INIT_OBJ)
*
*---------------------------------------------------------------------*/
static void can_set_imp (byte obj_adr)
{
fcan_reg.mem[obj_adr] = fcan_reg.mem[obj_adr] | 0x80;
}
/*---------------------------------------------------------------------*
* C A N _ C L E A R _ I M P
*---------------------------------------------------------------------*
* Funktion:
* L攕cht das IMP-Access-Flag des durch OBJ_ADR adressierten Objektes
*
*---------------------------------------------------------------------*
* Parameter:
*
* obj_adr : Interne Start-Adresse des Objektes
* (siehe C_INIT_OBJ)
*
*---------------------------------------------------------------------*/
static void can_clear_imp (byte obj_adr)
{
fcan_reg.mem[obj_adr] = fcan_reg.mem[obj_adr] & 0x7f;
}
/*---------------------------------------------------------------------*
* C A N _ C H E C K _ W R I T E _ A C C E S S
*---------------------------------------------------------------------*
* Funktion:
* Pr乫t ob auf ein Objekt schreibend zugegriffen werden darf
* Falls zugegriffen werden darf, ist der IMP-Access nach dieser
* Routine gesperrt.
*
*---------------------------------------------------------------------*
* Parameter:
*
* obj_adr : Interne Start-Adresse des Objektes
* (siehe C_INIT_OBJ)
*
* Returnwert : TRUE --> Zugriff ok
* FALSE --> Zugriff verweigert
*
*---------------------------------------------------------------------*/
static byte can_check_write_access (byte obj_adr)
{
unsigned int nbr_of_trials; /* Anzahl Sendeversuche bis Abbruch */
nbr_of_trials = 0;
can_clear_imp (obj_adr);
if (fcan_reg.mem[obj_adr+2] & 0x80) {
/* TX-Request = 1, das Objekt ist noch am Senden */
/* warten bis fertig */
can_set_imp (obj_adr);
while (fcan_reg.mem[obj_adr+2] & 0x80) {
/* while TX-Request=1 */
nbr_of_trials++;
if (nbr_of_trials > NBR_OF_SEND_TRIALS) {
/* Vermutlich kein anderer Controller am Bus */
/* Abbrechen */
return FALSE;
}
}
nbr_of_trials = 0;
can_clear_imp (obj_adr);
} /* end if */
/* Das Objekt w剅e bereit zum Senden, pr乫en ob CPU-Access */
if (!(fcan_reg.mem[obj_adr+1] & 0x01)) {
/* CPU-Access ist nicht frei */
if (fcan_reg.mem[obj_adr+1] & 0x02) {
/* Remote-Frame ist gerade eingetroffen, Controller */
/* will senden */
can_set_imp (obj_adr);
}
/* Nun warten bis CPU-Access frei ist */
while (!(fcan_reg.mem[obj_adr+1] & 0x01)) {
nbr_of_trials++;
if (nbr_of_trials > NBR_OF_SEND_TRIALS) {
/* Vermutlich kein anderer Controller am Bus */
/* Abbrechen */
return FALSE;
}
}
can_clear_imp (obj_adr);
} /* end if */
return TRUE;
}
#pragma eject
/*---------------------------------------------------------------------*
* E X P O R T I E R T E P R O Z E D U R E N *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* C _ F I R S T _ I N I T
*---------------------------------------------------------------------*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -