📄 mcohwcc01.c
字号:
/**************************************************************************
MODULE: MCOHWCC01
CONTAINS: Preliminary, limited hardware driver implementation for
Atmel 89C51CC01 - tested using the Atmel demo board
and CANopen demo board.
This version was tested with the Keil compiler system.
www.keil.com
This version re-uses functions provided by
www.esacademy.com/faq/progs
COPYRIGHT: Embedded Systems Academy, Inc. 2002-2007
All rights reserved. www.microcanopen.com
This software was written in accordance to the guidelines at
www.esacademy.com/software/softwarestyleguide.pdf
DISCLAIM: Read and understand our disclaimer before using this code!
www.esacademy.com/disclaim.htm
LICENSE: THIS IS THE EDUCATIONAL VERSION OF MICROCANOPEN
See file license_educational.txt or
www.microcanopen.com/license_educational.txt
VERSION: 3.30, ESA 30-JAN-07
$LastChangedDate: 2007-01-30 10:38:13 -0800 (Tue, 30 Jan 2007) $
$LastChangedRevision: 232 $
---------------------------------------------------------------------------
Known shortcoming:
Only supports a transmit queue of length "1"
If queue occupied, waits until it is clear
***************************************************************************/
#ifdef __RC51__
#include "c51cc01.h" // For Raisonance
#else
#include <Reg51CC01.h> // For Keil
#endif
#include "mcohw.h"
// Atmel development boards supported by this driver
#define CANARY 0 // Atmel CANARY demo board
#define CANOPEN 1 // Atmel CANopen demo board
// specify which board type to use
// change this to match the board you are using
#define BOARDTYPE CANOPEN
// Global timer/conter variable, incremented every millisecond
UNSIGNED16 MEM_NEAR gTimCnt = 0;
// Counts number of filters (CAN message objects) used
UNSIGNED8 MEM_FAR gCANFilter = 0;
/**************************************************************************
DOES: Sets one of the four screeners (acceptance filters) of
the CAN controller.
CAUTION: For the AT89C51CC01 from Atmel the screeners translate
to individual message buffers 1-14. The parameters
x_Mask and Bx_Match are ignored.
RETURNS: nothing
**************************************************************************/
void set_screener_std
(
UNSIGNED8 Screener, // 1 - 4, one of the four screeners
UNSIGNED16 ID_Match // match/code value for id
)
{
// select message object
CANPAGE = Screener << 4;
// message id bits 3 - 10
CANIDT1 = (ID_Match & 0x07F8) >> 3;
// message id bits 0 - 2
CANIDT2 = (ID_Match & 0x0007) << 5;
// no remote request
CANIDT4 = 0x00;
// mask bits 3 - 10: must match
CANIDM1 = 0xFF;
// mask bits 0 - 2: must match
CANIDM2 = 0xE0;
// only accept that message id
CANIDM4 = 0x05;
// clear receive ok (and all other) flags
CANSTCH = 0x00;
// enable msg object - message object is enabled for receive, expecting 8 bytes
CANCONCH = 0x88;
}
/**************************************************************************
DOES: Gets the next received CAN message and places it in
a receive buffer
RETURNS: 0 if no message received, 1 if message received and
copied to the buffer
**************************************************************************/
UNSIGNED8 MCOHW_PullMessage
(
CAN_MSG MEM_FAR *pReceiveBuf // pointer to a single message sized buffer
// to hold the received message
)
{
// variable declarations
UNSIGNED32 Identifier;
UNSIGNED8 Length;
UNSIGNED8 i,j;
// loop through all the receive message objects
for (j=1; j<=gCANFilter; j++)
{
// select message object
CANPAGE = j << 4;
// check the CAN status register for received message
// has a message been received?
if (CANSTCH & 0x20)
{
// get message identifer and length
Identifier = (unsigned int)(CANIDT1 << 3) | (CANIDT2 >> 5);
Length = CANCONCH & 0x0F;
// copy message identifer and length to application message buffer
pReceiveBuf->ID = Identifier;
pReceiveBuf->LEN = Length;
// copy message data to application message buffer
for (i=0; i < Length; i++)
{
*(UNSIGNED8 *)(pReceiveBuf->BUF+i) = CANMSG;
}
// clear receive ok flag so we can receive another message
CANSTCH &= 0xDF;
// re-enable message object - message object receives and is enabled
// 8 bytes expected
CANCONCH = 0x88;
// return 1 - message received
return (1);
}
}
// return 0 - no message received
return (0);
}
/**************************************************************************
DOES: Transmits a CAN message
RETURNS: 0 if the message could not be transmitted, 1 if the
message was transmitted
**************************************************************************/
UNSIGNED8 MCOHW_PushMessage
(
CAN_MSG MEM_FAR *pTransmitBuf // pointer to buffer containing CAN
// message to transmit
)
{
// CAN message identifier
UNSIGNED32 Identifier;
// length of data frame
UNSIGNED8 Length;
// local loop counter
UNSIGNED8 i;
// Prepare length code and identifier
Length = pTransmitBuf->LEN;
Identifier = pTransmitBuf->ID;
// select message object 0
CANPAGE = 0 << 4;
// Check if write access to CAN controller buffer is allowed
while (!(CANSTCH & 0x40));
// write access not allowed right now so give up
if (!(CANSTCH & 0x40))
{
return 0;
}
// disable message object
CANCONCH &= 0x3F;
// clear TXOK bit
CANSTCH &= ~0x40;
// store message identifier bits 0 - 10
CANIDT1 = (Identifier & 0x07F8) >> 3;
CANIDT2 = (Identifier & 0x0007) << 5;
// no remote request
CANIDT4 = 0x00;
// write data to transmit buffer
for (i=0; i < Length; i++)
{
CANMSG = pTransmitBuf->BUF[i];
}
// set length and enable msg object => causes transmission
CANCONCH = 0x40 | (Length & 0x0F);
// message sent
return 1;
}
/**************************************************************************
DOES: Gets the value of the current 1 millisecond system timer
RETURNS: The current timer tick
**************************************************************************/
UNSIGNED16 MCOHW_GetTime
(
void
)
{
UNSIGNED16 tmp;
// disable interrupts
EA = 0;
// get copy of timer tick
tmp = gTimCnt;
// enable interrupts
EA = 1;
// return timer tick copy
return tmp;
}
/**************************************************************************
DOES: Checks if a moment in time has passed (a timestamp has expired)
RETURNS: 0 if timestamp has not yet expired, 1 if the
timestamp has expired
**************************************************************************/
UNSIGNED8 MCOHW_IsTimeExpired
(
UNSIGNED16 timestamp // timestamp to check for expiration
)
{
UNSIGNED16 time_now;
// disable interrupts
EA = 0;
// get a copy of the current time
time_now = gTimCnt;
// enable interrupts
EA = 1;
// to ensure the minimum runtime
timestamp++;
// if timestamp is less than the current time...
if (time_now > timestamp)
{
// check if the timestamp has expired
if ((time_now - timestamp) < 0x8000)
{
return 1;
}
// timestamp has not expired
else
{
return 0;
}
}
// if timestamp is greater than the current time...
else
{
// check if the timestamp has expired
if ((timestamp - time_now) > 0x8000)
{
return 1;
}
// timestamp has not expired
else
{
return 0;
}
}
}
/**************************************************************************
DOES: Timer interrupt service routine
Increments the global millisecond counter tick
This function needs to be called once every millisecond
RETURNS: nothing
**************************************************************************/
void MCOHW_TimerISR
(
void
) interrupt 1
{
// stop timer 0
TR0 = 0;
#if (BOARDTYPE == CANARY)
// reload for 1ms at 12MHz, X2 mode
TH0 = 0xF8;
TL0 = 0x30;
#elif (BOARDTYPE == CANOPEN)
// reload for 1ms at 20MHz, X2 mode
TH0 = 0xF2;
TL0 = 0xFB;
#endif
// start timer 0
TR0 = 1;
// increment global counter
gTimCnt++;
}
/**************************************************************************
DOES: Initializes the CAN interface.
CAUTION: Does not initialize filters - nothing will be received
unless screeners are set using set_screener_std
RETURNS: 0 for failed init, 1 for successful init
**************************************************************************/
UNSIGNED8 MCOHW_Init
(
UNSIGNED16 BaudRate // desired baudrate in kbps
)
{
UNSIGNED8 i;
UNSIGNED8 baudrateok = 0;
// enable X2 mode - 6 clocks/cycle
CKCON = 0x01;
// this version only supports 125kbps
if (BaudRate == 125)
{
#if (BOARDTYPE == CANARY)
// timing for X2 mode, 12MHz, 125kbps
CANBT1 = 0x0A;
CANBT2 = 0x0A;
CANBT3 = 0x1C;
#elif (BOARDTYPE == CANOPEN)
// timing for X2 mode, 20MHz, 125kbps
CANBT1 = 0x12;
CANBT2 = 0x2E;
CANBT3 = 0x18;
#endif
// the baudrate is supported
baudrateok = 1;
}
// no filters configured
gCANFilter = 0;
// clear all acceptance filters and masks, receive nothing
for (i=0; i<15; i++)
{
// select message object
CANPAGE = i << 4;
// message id bits 0 - 10
CANIDT1 = 0xFF;
CANIDT2 = 0xE0;
// no remote request
CANIDT4 = 0x00;
// mask bits 0 - 10
CANIDM1 = 0xFF;
CANIDM2 = 0xE0;
// only accept that message id
CANIDM4 = 0x05;
// is this a receive message object?
if (i!=0)
{
// clear receive ok and all other flags
CANSTCH = 0x00;
}
// transmit message object?
else
{
// set tx for first transmission
CANSTCH = 0x40;
}
// disable msg object
CANCONCH = 0x00;
}
// enable can controller
CANGCON = 0x02;
// wait for can controller to be enabled
while (!(CANGSTA & 0x04));
// initialize timer interrupt here.
// MCOHW_TimerISR must be executed once every millisecond.
// stop timer 0
TR0 = 0;
// mode 1
TMOD |= 1;
#if (BOARDTYPE == CANARY)
// reload for 1ms at 12MHz, X2 mode
TH0 = 0xF8;
TL0 = 0x30;
#elif (BOARDTYPE == CANOPEN)
// reload for 1ms at 20MHz, X2 mode
TH0 = 0xF2;
TL0 = 0xFB;
#endif
// start timer 0
TR0 = 1;
// enable timer 0
ET0 = 1;
// return result of initialization
return baudrateok;
}
/**************************************************************************
DOES: Initializes the next available filter
RETURNS: 0 for failed init, 1 for successful init
**************************************************************************/
UNSIGNED8 MCOHW_SetCANFilter
(
UNSIGNED16 CANID // identifier to receive
)
{
// get the number of the next available filter
gCANFilter++;
// if all filters used then fail
if (gCANFilter > 14)
{
return 0;
}
// filter available
else
{
// configure the filter
set_screener_std(gCANFilter, CANID);
return 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -