⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 r591can.c

📁 基于p87c591的can通讯驱动程序源码
💻 C
字号:
/*======================================================================*/
/* NAME:    r591can.c                                                   */
/* INFO:    CAN module for the PHYTEC training board equipped with      */
/*          PHYTEC phyCORE 591 and Philips P8x591 Microcontroller       */
/* RIGHTS:  Embedded Systems Academy   www.esacademy.com                */
/* DETAILS: Using a CAN bit rate of 125kbit with a 12MHz clock          */
/*          Filters can be set to screen for 11-bit ID and 2 data bytes */
/*----------------------------------------------------------------------*/
/* To get BTRx timing values for other speeds, consult the              */
/* Microcontroller Peripheral Timing Calculators provided by the        */
/* Embedded Systems Academy at www.esacademy.com/faq/calc/philips.htm   */
/*----------------------------------------------------------------------*/
/*          BASED ON THE CAN EXAMPLE PROVIDED BY PHYTEC                 */
/* HISTORY: V1.0   Pf    21-FEB-2000                                    */
/*          V1.1   Pf    16-JUN-2000                                    */
/*======================================================================*/

#include "reg591.h"
#include "reg591ex.h"
#include "r591can.h"


/*----------------------- GLOBAL SUBROUTINES ---------------------------*/

/*======================================================================*/
/* FUNCTION:   init_can_125_12                                          */
/* DESCRIPTION:Initializes the CAN interface. Bus operates at 125kBit,  */
/*             if processor clock is 12MHz. Screeners are set to        */
/*             "one long filter for std messages.                       */
/* 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_12 ( void )
{
BYTE i;

   CANMOD = 0x01;                   /* Reset mode for initialization */

/* BTR0 and BTR1 determine the baudrate and sample point position       */
   CANADR = BTR0;                   /* set address to BTR0 register */
   CANDAT = 0x85;                   /* write data to BTR0 (auto INC CANADR */
   CANADR = BTR1;                   /* set address to BTR1 register */
   CANDAT = 0x2B;                   /* write data to BTR1 */

/* To get BTRx timing values for other speeds, consult the              */
/* Microcontroller Peripheral Timing Calculators provided by the        */
/* Embedded Systems Academy at www.esacademy.com/faq/calc/philips.htm   */

/* Clear all acceptance filters and masks, receive nothing */
   CANADR = ACR0;
   for(i=1;i>=32;i++)
      CANDAT = 0;

/* Set acceptance filter mode to accept standard frames with single     */
/* acceptance filter.                                                   */
   CANADR = ACFMODE;                /* acceptance filter mode register */
   CANDAT = 0x55;                   /* all banks -> one long filter */
   CANADR = ACFENA;                 /* acceptance filter enable register */
   CANDAT = 0x55;                   /* enable filter for all banks */

   CANMOD = 0x00;                   /* release CAN controller */

   while (CANSTA & 0x80);           /* wait until controller is active */
}


/*======================================================================*/
/* FUNCTION:   set_screener_std                                         */
/* DESCRIPTION:Sets one of the four screeners (acceptance filters) of   */
/*             the CAN controller.                                      */
/* CAUTION:    Does assume the screeners are set-up to be used as "one  */
/*             long filter for standard messages"                       */
/* INPUT:      Screener - 1 to 4, one of the four screeners             */
/*             ID_Mask - Bit set: corresponding bit in ID is don't care */
/*               Bit clear: corresponding bit in ID must match ID_Match */
/*             ID_Match - Match/Code value for ID                       */
/*             B1_Mask - Bit set: cor. bit in data byte 1 is don't care */
/*               Bit clear: cor. bit in data byte 1 must match B1_Match */
/*             B1_Match - Match/Code value for data byte 1              */
/*             B2_Mask - Bit set: cor. bit in data byte 2 is don't care */
/*               Bit clear: cor. bit in data byte 2 must match B2_Match */
/*             B2_Match - Match/Code value for data byte 2              */
/* OUTPUT:     none                                                     */
/*======================================================================*/
void set_screener_std ( BYTE Screener,
                        WORD ID_Mask, WORD ID_Match,
                        BYTE B1_Mask, BYTE B1_Match,
                        BYTE B2_Mask, BYTE B2_Match)
{
   Screener -= 1;
   Screener &= 0x3;                 /* ensure 0 <= Screener <= 3 */

   CANADR = ACFENA;                 /* acceptance filter enable register*/

   switch (Screener)
   {
   case 0: CANDAT &= 0xFE; break;   /* disable bank 1 */
   case 1: CANDAT &= 0xFB; break;   /* disable bank 2 */
   case 2: CANDAT &= 0xEF; break;   /* disable bank 3 */
   case 3: CANDAT &= 0xBF; break;   /* disable bank 4 */
   }

/* Initialize acceptance filter - Mask  */
   CANADR = AMR0 + (Screener * 8);  /* acceptance mask register bank "Screener" */
   CANDAT = (BYTE) (ID_Mask >> 3);
   CANDAT = (BYTE) (((ID_Mask & 0x07) << 5) | 0x1F);
   CANDAT = B1_Mask;
   CANDAT = B2_Mask;

/* Initialize acceptance filter - Code / Match */
   CANADR = ACR0 + (Screener * 8);  /* acceptance code register bank "Screener" */
   CANDAT = (BYTE) (ID_Match >> 3);
   CANDAT = (BYTE) (ID_Match & 0x07) << 5;
   CANDAT = B1_Match;
   CANDAT = B2_Match;

   CANADR = ACFENA;                 /* acceptance filter enable register*/
   switch (Screener)
   {
   case 0: CANDAT |= 0x01; break;   /* enable bank 1 */
   case 1: CANDAT |= 0x04; break;   /* enable bank 2 */
   case 2: CANDAT |= 0x10; break;   /* enable bank 3 */
   case 3: CANDAT |= 0x40; break;   /* enable bank 4 */
   }
}


/*======================================================================*/
/* FUNCTION:   transmit_message                                         */
/* DESCRIPTION:Transmits a single CAN message                           */
/* CAUTION:    Before transmitting, the function WAITS until the        */
/*             CAN controller is ready for the next data set            */
/* INPUT:      pTransmitBuf - data structure with the message           */
/* OUTPUT:     none                                                     */
/*======================================================================*/
void transmit_message ( MSG_BUF *pTransmitBuf )
{
DWORD Identifier;                   /* CAN message identifier */
BYTE  Length;                       /* lenght of data frame */
BYTE  i;                            /* local loop counter */

/* Prepare length code and identifier.                                  */
   Length     = pTransmitBuf->LEN;
   Identifier = (pTransmitBuf->ID << 5);

/* Wait until write access to CAN controller buffer is allowed          */
   while ( !(CANSTA & 0x04) );

/* Write message to transmit buffer                                     */
   CANADR = TBF;                    /* adress to transmit buffer */
   CANDAT = Length;                 /* write Length code */
   CANDAT = (BYTE)(Identifier >> 8);
   CANDAT = (BYTE)Identifier;       /* write identifier */
   for (i=0; i < Length; i++)       /* write data bytes */
      CANDAT = *(BYTE *)(pTransmitBuf->BUF+i); /* copy data byte  */

/* Init a transmission request.                                         */
   CANCON  = 0x01;
}


/*======================================================================*/
/* FUNCTION:   receive_message                                          */
/* DESCRIPTION:Receives a single standard ID CAn mesage                 */
/* CAUTION:    Will only recive something, if a message is actually     */
/*             pending in the FIFO of the CAN controller                */
/* INPUT:      pReceiveBuf - Pointer to data structure for message      */
/* OUTPUT:     pReceiveBuf - the received message                       */
/*             RETURNS 0, if there was no message to receive            */
/*             RETURNS 0xFF, if a message was received                  */
/*======================================================================*/
BYTE receive_message(MSG_BUF *pReceiveBuf)
{
DWORD Identifier;                   /* Definition of vars */
BYTE  Length;
BYTE  i;

/* Check the CAN status register for received message                   */
   if ( CANSTA & 0x01)
   {                                /* Message received! */

      CANADR       = RBF;           /* set address to receive buffer */
      Length       = CANDAT & 0x0F;
      Identifier   = (DWORD)CANDAT; /* read identifier */
      Identifier <<= 8;
      Identifier  |= (DWORD) CANDAT;
      Identifier >>= 5;
      CANADR       = RBF + 3;       /* set address to data bytes */

/* Copy message to application message buffer.                          */
      pReceiveBuf->ID = Identifier;
      pReceiveBuf->LEN = Length;

/* Read data bytes and write to buffer                                  */
      for (i=0; i < Length; i++)
    	   *(BYTE *)(pReceiveBuf->BUF+i) = CANDAT; /* copy bytes */

      CANCON = 0x0C;                /* release receive buffer */

      return (0xFF);                /* Return TRUE, msg rcvd */
   }
   else                             /* Return False, no msg rcvd */
      return (0);
}


/*======================================================================*/
/* FUNCTION:   check_busoff_state                                       */
/* DESCRIPTION:Checks, if the CAN controller went into BUS OFF state    */
/* INPUT:      none                                                     */
/* OUTPUT:     RETURNS 0, if CAN controller still active                */
/*             RETURNS 0xFF, if CAN controller in BUS OFF state         */
/*======================================================================*/
BYTE check_busoff_state (void)
{
/* Check status register for bus-off state                              */
   if (CANSTA & 0x80)
      return (0xFF);	            /* CAN controller is in bus-off */
   else
      return (0);                   /* CAN controller active */
}

/*----------------------- END OF FILE ----------------------------------*/






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -