?? mcohwcc01.c
字號:
/**************************************************************************
MODULE: MCOHWCC01
CONTAINS: Preliminary, limited hardware driver implementation for
Atmel 89C51CC01 - tested using the Atmel CANopen Demo Board
using a 20Mhz clock (CANgine board: www.cangine.com)
This version was tested with the Keil compiler system.
www.keil.com
COPYRIGHT: Embedded Systems Academy, Inc. 2002-2003.
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: Users that have purchased a license for PCANopenMagic
(www.esacademy.com/software/pcanopenmagic)
may use this code in commercial projects.
Otherwise only educational use is acceptable.
VERSION: 1.20, Pf/Aa/Ck 27-MAY-03
---------------------------------------------------------------------------
HISTORY: 1.20, Pf 27-MAY-03, Adapted for 20MHz Atmel CANopen Demo Board
added support for CANopen ERR and RUN LED
1.00, Ck 07-OCT-02, First Published Version
---------------------------------------------------------------------------
Known Shortcomings:
Only supports a transmit queue of length "1"
If queue occupied, waits until it is clear
***************************************************************************/
#include <Reg51cc01.h>
#include "mcohw.h"
#ifdef USE_LED
BYTE data m200cnt = 0;
#endif // USE_LED
// Global timer/conter variable, incremented every millisecond
WORD data gTimCnt = 0;
// Global conter for number of receive filters used
BYTE gCANFilter = 0;
#ifdef USE_LED
/**************************************************************************
Variables for LED management
**************************************************************************/
BYTE data mLEDtoggle = 0;
BYTE data mLEDcnt = 0;
BYTE data gRLED = LED_OFF; // Current pattern on run led
BYTE data gELED = LED_OFF; // Current pattern on error led
/**************************************************************************
DOES: This function switches the CANopen Err and Run LEDs
as specified by DR-303-3
It must be called once every 200ms
**************************************************************************/
void MCO_SwitchLEDs
(
void
)
{
mLEDtoggle = ~mLEDtoggle;
mLEDcnt++;
if (mLEDcnt >= 6)
{
mLEDcnt = 0;
}
switch(gRLED) // Run LED
{
case LED_OFF:
LED_RUN = 1;
break;
case LED_ON:
LED_RUN = 0;
break;
case LED_BLINK:
LED_RUN = mLEDtoggle;
break;
case LED_FLASH1:
if (mLEDcnt == 0)
{
LED_RUN = 0;
}
else
{
LED_RUN = 1;
}
break;
default:
break;
}
switch(gELED) // Error LED
{
case LED_OFF:
LED_ERR = 1;
break;
case LED_ON:
LED_ERR = 0;
break;
case LED_BLINK:
LED_ERR = mLEDtoggle;
break;
case LED_FLASH1:
if (mLEDcnt == 1)
{
LED_ERR = 0;
}
else
{
LED_ERR = 1;
}
break;
default:
break;
}
}
#endif // USE_LED
/*======================================================================*/
/* FUNCTION: init_can_125_20 */
/* DESCRIPTION:Initializes the CAN interface. Bus operates at 125kBit, */
/* if processor clock is 20MHz. */
/* CAUTION: Does not initialize filters - nothing will be received */
/* unless screeners are set using set_screener_std */
/* INPUT: none */
/* OUTPUT: none */
/*======================================================================*/
void init_can_125_20 ( void )
{
BYTE i;
/* Enable X2 mode */
CKCON = 0x01;
/* timing for X2 mode, 20MHz, 125kbps */
CANBT1 = 7 << 1;
CANBT2 = (1 << 5) | (7 << 1); // SJW << 5, PRS << 1
CANBT3 = (2 << 4) | (7 << 1); // PHS2 << 4, PHS << 1
/* Clear all acceptance filters and masks, receive nothing */
for (i=0; i<15; i++)
{
CANPAGE = i << 4; /* select msg object i */
CANIDT1 = 0xFF; /* msg id bits 3-10 */
CANIDT2 = 0xE0; /* msg id bits 0-2 */
CANIDT4 = 0x00; /* no remote request */
CANIDM1 = 0xFF; /* mask bits 3-10 */
CANIDM2 = 0xE0; /* mask bits 0-2 */
CANIDM4 = 0x05; /* only accept that msg id */
if (i!=0)
CANSTCH = 0x00; /* clear receive ok (and all other) flags */
else
CANSTCH = 0x40; /* for transmit buffer we need to set TX for first transmit */
/* disable msg object */
CANCONCH = 0x00; /* msg object is disabled */
}
CANGCON = 0x02; /* enable CAN controller */
while (!(CANGSTA & 0x04)); /* wait for can controller to be enabled */
// Initialize Timer interrupt here.
// MCOHW_TimerISR must be executed once every millisecond.
TR0 = 0; /* timer 0: stop */
TMOD |= 1; /* mode 1 */
TH0 = 0xFF;
TL0 = 0xFF;
TR0 = 1; /* timer 0: start */
ET0 = 1; /* enable timer 0 int */
}
/*======================================================================*/
/* FUNCTION: set_screener_std */
/* DESCRIPTION: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. */
/* INPUT: Screener - 1 to 4, one of the four screeners */
/* ID_Match - Match/Code value for ID */
/* OUTPUT: none */
/*======================================================================*/
void set_screener_std ( BYTE Screener, WORD ID_Match )
{
CANPAGE = Screener << 4; /* select msg object */
CANIDT1 = (ID_Match & 0x07F8) >> 3; /* msg id bits 3-10 */
CANIDT2 = (ID_Match & 0x0007) << 5; /* msg id bits 0-2 */
CANIDT4 = 0x00; /* no remote request */
CANIDM1 = 0xFF; /* mask bits 3-10: must match */
CANIDM2 = 0xE0; /* mask bits 0-2: must match */
CANIDM4 = 0x05; /* only accept that msg id */
/* clear receive ok (and all other) flags */
CANSTCH = 0x00; /* initialize */
/* enable msg object */
CANCONCH = 0x88; /* msg object is enabled for receive, expected 8 bytes */
}
BYTE MCOHW_PullMessage (CAN_MSG *pReceiveBuf)
{
DWORD Identifier; /* Definition of vars */
BYTE Length;
BYTE i,j;
for (j=1; j<=gCANFilter; j++) /* Find msg object that has received something */
{
CANPAGE = j << 4; // select msg object
/* Check the CAN status register for received message */
if (CANSTCH & 0x20)
{ /* Message received! */
/* Copy message to application message buffer. */
Identifier = (unsigned int)(CANIDT1 << 3) | (CANIDT2 >> 5);
Length = CANCONCH & 0x0F;
pReceiveBuf->ID = Identifier;
pReceiveBuf->LEN = Length;
/* Read data bytes and write to buffer */
for (i=0; i < Length; i++)
*(BYTE *)(pReceiveBuf->BUF+i) = CANMSG; /* copy bytes */
// clear receive ok flag
CANSTCH &= 0xDF;
// re-enable msg object
CANCONCH = 0x88; /* msg object receives and is enabled */
/* 8 bytes excpected */
return (1); /* Return TRUE, msg rcvd */
}
}
return (0); /* Return False, no msg rcvd */
}
BYTE MCOHW_PushMessage (CAN_MSG *pTransmitBuf)
{
DWORD Identifier; /* CAN message identifier */
BYTE Length; /* length of data frame */
BYTE i; /* local loop counter */
/* Prepare length code and identifier. */
Length = pTransmitBuf->LEN;
Identifier = pTransmitBuf->ID;
CANPAGE = 0 << 4; /* select msg object 0 */
/* Check if write access to CAN controller buffer is allowed */
while (!(CANSTCH & 0x40))
{
}
if (!(CANSTCH & 0x40))
{
return 0;
}
CANCONCH &= 0x3F; /* disable object */
CANSTCH &= ~0x40; /* clear TXOK bit */
CANIDT1 = (Identifier & 0x07F8) >> 3; /* msg id bits 3-10 */
CANIDT2 = (Identifier & 0x0007) << 5; /* msg id bits 0-2 */
CANIDT4 = 0x00; /* no remote request */
/* Write message to transmit buffer */
for (i=0; i < Length; i++) /* write data bytes */
CANMSG = pTransmitBuf->BUF[i]; /* copy data byte */
/* set length and enable msg object => send */
CANCONCH = 0x40 | (Length & 0x0F);
return 1;
}
/**************************************************************************
DOES: Reads and returns the value of the current 1 millisecond system
timer tick.
**************************************************************************/
WORD MCOHW_GetTime (void)
{
WORD tmp;
EA = 0; // Disable Interrupts
tmp = gTimCnt;
EA = 1; // Enable Interrupts
return tmp;
}
BYTE MCOHW_IsTimeExpired(WORD timestamp)
{
WORD time_now;
EA = 0; // Disable Interrupts
time_now = gTimCnt;
EA = 1; // Enable Interrupts
timestamp++; // To ensure the minimum runtime
if (time_now > timestamp)
{
if ((time_now - timestamp) < 0x8000)
return 1;
else
return 0;
}
else
{
if ((timestamp - time_now) > 0x8000)
return 1;
else
return 0;
}
}
/**************************************************************************
DOES: Timer Interrupt Service Routine.
Increments the global millisecond counter tick.
This function needs to be executed once every millisecond!
**************************************************************************/
#define T0_RELOAD 62210
// Time reload to achieve 1 millisecond at 20MHz, 6-clock
void MCOHW_TimerISR (void) interrupt 1
{
TR0 = 0; // Stop Timer 0
TH0 = T0_RELOAD / 256;
TL0 = T0_RELOAD % 256; // Timer reload value
TR0 = 1; // Start Timer 0
gTimCnt++; // Increment global counter
#ifdef USE_LED
m200cnt++;
if (m200cnt >= 200)
{
MCO_SwitchLEDs(); // Call all 200ms
m200cnt = 0;
}
#endif // USE_LED
}
BYTE MCOHW_Init (WORD BaudRate)
{
// This version only supports 125kbit at 20MHz
if (BaudRate == 125)
{
init_can_125_20();
gCANFilter = 0;
return 1;
}
else
{
return 0;
}
}
BYTE MCOHW_SetCANFilter (WORD CANID)
{
gCANFilter++;
if (gCANFilter > 14) // Kl, 10/9/02 Modified for CC01
{
return 0;
}
else
{
set_screener_std(gCANFilter, CANID);
return 1;
}
}
/*----------------------- END OF FILE ----------------------------------*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -