📄 can1.c
字号:
//****************************************************************************
// Module On-Chip CAN Interface 1 (CAN1)
// Controller Infineon C167CS/CR or ST10F168
//****************************************************************************
#ifdef C167CS
#include <c167cs.h> // register definitions for C167CS device
#endif
#ifdef C167CR
#include <REG167.h> // register definitions for C167CR device
#endif
#ifdef ST10F168
#include <REG168.h> // register definitions for ST10 device
#endif
#include <can.h> // register definitions for on-chip CAN
#include <string.h>
#include <intrins.h>
// Definitions for Interrupt Enable Control Registers
#define IC_IE(x) (((x) == 0) ? 0x0000 : 0x0040)
#define IC_ILVL(x) (((x) << 2) & 0x003C)
#define IC_GLVL(x) ((x) & 0x0003)
/****** C A N I D D E F I N I T I O N S *****************************************/
// Macros for CAN Message Configuration and DLC register
#define CanTX 0x08 // Transmit
#define CanRX 0x00 // Receive
#define CanIDE 0x04 // ID extended (29-bit)
#define SetDLC(v) ((unsigned char)((v)<<4))
// Define Message Object 1 Identifiers (handled in polling mode)
#define ID1 (CanID29(0x00000100))
#define ID1MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID1TYP (CanTX | CanIDE | SetDLC(1)) // Transmit, ID extended (29-bit),
// 1 Byte message length
// Define Message Object 2 Identifiers (handled in polling mode)
#define ID2 (CanID29(0x00000101))
#define ID2MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID2TYP (CanRX | CanIDE | SetDLC(1)) // Receive, ID extended (29-bit),
// 1 Byte message length
// Define Message Object 3 Identifiers (handled in interrupt mode)
#define ID3 (CanID29(0x00000102))
#define ID3MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID3TYP (CanTX | CanIDE | SetDLC(8)) // Transmit, ID extended (29-bit),
// 8 Byte message length
#define ID3IntChk (C1MOBJ[3].msg_ctl & RXIE_MASK) // Interrupt Status for Message Object 2
// Define Message Object 4 Identifiers (handled in interrupt mode)
#define ID4 (CanID29(0x00000103))
#define ID4MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID4TYP (CanRX | CanIDE | SetDLC(8)) // Receive, ID extended (29-bit),
// 8 Byte message length
#define ID4IntChk (C1MOBJ[4].msg_ctl & TXIE_MASK) // Interrupt Status for Message Object 3
// Define Message Object 5 Identifiers (remote request sender)
#define ID5 (CanID29(0x00000104))
#define ID5MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID5TYP (CanRX | CanIDE | SetDLC(8)) // Transmit, ID extended (29-bit),
// 8 Byte message length
// Define Message Object 6 Identifiers (remote frame replier)
#define ID6 (CanID29(0x00000105))
#define ID6MSK (CanID29(0x1FFFFFFF) | CanIDEMSK)
#define ID6TYP (CanTX | CanIDE | SetDLC(8)) // Receive, ID extended (29-bit),
// 8 Byte message length
// IDxTYP table for all used message objects
unsigned char const id_typ[] = {
0, // dummy element
ID1TYP,
ID2TYP,
ID3TYP,
ID4TYP,
ID5TYP,
ID6TYP,
};
// Set value in Arbitration registers
#define CanID29(id)((((unsigned long)(id) >> 21) & 0x000000ff) | \
(((unsigned long)(id) >> 5) & 0x0000ff00) | \
(((unsigned long)(id) << 11) & 0x00ff0000) | \
(((unsigned long)(id) << 27)))
#define CanID11(id) (CanID29((unsigned long)(id) << 18))
#define CanSetID(val,ch) C1MOBJ[(ch)].arbitr = (val);
// ===== CAN Baudrate Calculation ======================
// Tscl = (1+BRP)/(2*f_CPU)
// Tbit = 1 + (TSEG1+1) + (TSEG2+1) * Tscl
// Examples:
// 125kHz CAN Baudrate, f_CPU=10MHz
// TSEG1 = 4, TSEG2 = 3, BRP = 15
// Tscl = 16/10.0 MHz = 0.800 礢ec
// Tbit = (1 + (4+1)+(3+1)) * Tscl = 10 * 0.800uSec = 8 礢ec -> 125kHz Baudrate
// Examples:
// 1MHz CAN Baudrate, f_CPU=10MHz
// TSEG1 = 6, TSEG2 = 1, BRP = 0
// Tscl = 1/10.0 MHz = 0.100 礢ec
// Tbit = (1 + (1+6)+(1+1)) * Tscl = 10 * 0.100uSec = 1 礢ec -> 1MHz Baudrate
#define BRP 0
#define SJW 0
#define TSEG1 4
#define TSEG2 3
// Clear all bits in Message Control register (MCR)
#define MCR_CLRALL (INTPND_CLR & RXIE_CLR & TXIE_CLR & MSGVAL_CLR & \
NEWDAT_CLR & CPUUPD_CLR & TXRQ_CLR & RMTPND_CLR)
// Enable Message Object; clear all other bits in MCR
#define MCR_ENA (INTPND_CLR & RXIE_CLR & TXIE_CLR & MSGVAL_SET & \
NEWDAT_CLR & CPUUPD_CLR & TXRQ_CLR & RMTPND_CLR)
// Enable Message Object & Transmit Interrupt; clear all other bits in MCR
#define MCR_ENA_TXIE (INTPND_CLR & RXIE_CLR & TXIE_SET & MSGVAL_SET & \
NEWDAT_CLR & CPUUPD_CLR & TXRQ_CLR & RMTPND_CLR)
// Enable Message Object & Receive Interrupt; clear all other bits in MCR
#define MCR_ENA_RXIE (INTPND_CLR & RXIE_SET & TXIE_CLR & MSGVAL_SET & \
NEWDAT_CLR & CPUUPD_CLR & TXRQ_CLR & RMTPND_CLR)
/*
* CAN Initialization:
* - reset CAN controller
* - initialize CAN message object (ID, MSK, control)
* - clear message object status register
* - clear unused message object (ID, MSK, control, status)
* - enable CAN controller
*/
void CAN1Init (void) {
int i;
_bfld_(DP4,0x0020,0x0000); // set P4.5 (CAN_RxD) to alternate input
// P4.6 (CAN_TxD) is set to output by hardware
C1CSR = 0x0041; // set INIT and CCE
// set CAN Baudrate
C1BTR = (BRP) | (SJW << 6) | (TSEG1 << 8) | (TSEG2 << 12);
C1GMS = 0xE0FF; // set global mask short register
C1UGML = 0xFFFF; // set upper global mask long register
C1LGML = 0xF8FF; // set lower global mask long register
// Initialize Message Object 1
C1MOBJ[1].msg_ctl = MCR_ENA; // set message control register
C1MOBJ[1].msg_cfg = ID1TYP; // set message configuration register
CanSetID (ID1, 1); // set arbitration register
// Initialize Message Object 2
C1MOBJ[2].msg_ctl = MCR_ENA; // set message control register
C1MOBJ[2].msg_cfg = ID2TYP; // set message configuration register
CanSetID (ID2, 2); // set arbitration register
// Initialize Message Object 3
C1MOBJ[3].msg_ctl = MCR_ENA_TXIE; // set message control register
C1MOBJ[3].msg_cfg = ID3TYP; // set message configuration register
CanSetID (ID3, 3); // set arbitration register
// Initialize Message Object 4
C1MOBJ[4].msg_ctl = MCR_ENA_RXIE; // set message control register
C1MOBJ[4].msg_cfg = ID4TYP; // set message configuration register
CanSetID (ID4, 4); // set marbitration register
// Initialize Message Object 5
C1MOBJ[5].msg_ctl = MCR_ENA; // set message control register
C1MOBJ[5].msg_cfg = ID5TYP; // set message configuration register
CanSetID (ID5, 5); // set arbitration register
// Initialize Message Object 6
C1MOBJ[6].msg_ctl = MCR_ENA; // set message control register
C1MOBJ[6].msg_cfg = ID6TYP; // set message configuration register
CanSetID (ID6, 6); // set arbitration register
// Disable Message Object 7 .. 15
for (i = 7; i <= 15; i++) {
C1MOBJ[i].msg_ctl = MCR_CLRALL; // Disable Message Control register
}
#ifdef C167CS
C1IR = 0; // required by C167CS to enable outputs
#endif
// Enable XP0INT (CAN1 Interrupt)
XP0IC = IC_IE(1) | IC_ILVL(1) | IC_GLVL(1); // Enable, Interrupt Level 1, Group Level 1
// Initialize CAN Control/Status Register, Enable Interrupts
C1CSR = CAN_IE_; // Reset CCE & INIT, Set IE
}
/***** CAN I/O Routines for Polling Mode ******************************************/
/*
* Can1Send:
* Input Parameter: ch := message object channel (1 .. 15)
* p := Pointer to data
*
* Return Value: 0 message transferred to buffer, transmission started
* -1 message object not defined for transmission
* -2 previous message not yet transferred
*
* - check if CAN message object is defined for transmit
* - check if a previous message is transmitted OK
* - copy new message to message object buffer
* - set message object for transmission
*/
int CAN1Send(unsigned int ch, void *p) {
unsigned char typ;
// check if CAN message object is defined for transmit
if (ch >= sizeof (id_typ)) return (-1);
typ = id_typ[ch];
if ((typ & DIR_MASK) != CanTX) {
return (-1); // channel is not a transmission channel
}
if ((C1MOBJ[ch].msg_ctl & TXRQ_)) {
return (-2); // previous message not yet send!
}
memcpy (C1MOBJ[ch].msg, p, (typ >> 4));
C1MOBJ[ch].msg_ctl = TXRQ_SET & CPUUPD_CLR; // set TXRQ, reset CPUUPD
return 0;
}
/*
* CAN1Read:
* Input Parameter: ch := message object channel (1 .. 15)
* p := Pointer to data buffer
*
* Return Value: 0 new message read from message data registers
* -1 message object not defined for receiving
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -