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

📄 f580_can0_receive.c

📁 C8051F58x CAN BUS 可以提供傳輸 溝通介面 節省開發時間
💻 C
字号:
//-----------------------------------------------------------------------------
// F580_CAN0_Receive.c
//-----------------------------------------------------------------------------
// Copyright 2008 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This program receives data from another CAN node using a configurable number
// of message objects and datasize.  The message identifier is set based on the 
// message object number.  The corresponding transmit firmware is 
// F580_CAN0_Transmit.c.  The following two #defines should be set to the
// same values in both the transmit and receive code:
//
// #define MESSAGE_OBJECTS          
// #define MESSAGE_SIZE  
//
// #define RX_COMPLETE_MASK should also be set.  See definition for details     
//
// The purpose of this example is to show how to initialize a message object
// for receive mode and how to handle certain error conditions.
//
// How To Test:
//
// 1) Verify the LED and switch pin jumpers are populated 
//    (J19 for device A and J11 for device B).
//
// 2) Make sure the CAN jumpers in J17 (for A side) and J26 (for B side)
//    are connected.
//
// 3) Download the code to a F580-TB (either device A or device B) that is
//    connected as above to another device running the F580_CAN0_Transmit 
//    code.
//
// 4) Run the code on the Receiver first, then run the code on the Transmitter.
//
// 5) While the receiver is waiting for transmissions, the LED will blink.
//    Once transmissions are complete, the LED will remain lit. 
//
// Target:         C8051F580 (Side B of a C8051F580-TB)
// Tool chain:     Keil C51 8.0 / Keil EVAL C51
// Command Line:   None
//
// Release 1.0 / 21 JUL 2008 (ADT)
//    - Initial Revision
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include "compiler_defs.h"
#include "C8051F580_defs.h"            // SFR declarations

//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------

typedef union UU64
{
   U32 U32[2];
   U16 U16[4];
   U8 U8[8];
} UU64;

//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void PORT_Init (void);
void CAN0_Init (void);

INTERRUPT_PROTO (CAN0_ISR, INTERRUPT_CAN0);

//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------

#define SYSCLK       24000000          // System clock speed in Hz

#define MESSAGE_OBJECTS    32          // Number of message objects to use
                                       // Range is 1-32
#define MESSAGE_SIZE        8          // Size in bytes of each CAN message
                                       // Range is 1-8

#define RX_COMPLETE_MASK  0xFFFFFFFF   // Set this to (2^MESSAGE_OBJECTS - 1)

//-----------------------------------------------------------------------------
// Bit Definition Masks
//-----------------------------------------------------------------------------

// CAN0STAT
#define BOff  0x80                     // Busoff Status
#define EWarn 0x40                     // Warning Status
#define EPass 0x20                     // Error Passive
#define RxOk  0x10                     // Receive Message Successfully
#define TxOk  0x08                     // Transmitted Message Successfully
#define LEC   0x07                     // Last Error Code

//-----------------------------------------------------------------------------
// Pin Definitions
//-----------------------------------------------------------------------------

SBIT (LED, SFR_P1, 3);                 // LED = 1 turns on the LED

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

bit CAN_ERROR = 0;                     // 0 = No Errors occurred
                                       // 1 = Some error(s) occurred

UU32 CAN_RX_COMPLETE;                  // Bit status register that is updated
                                       // when a RX complete is received for
                                       // a specific message object.  Should be
                                       // equal to RX_COMPLETE_MASK when done

//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------

void main (void)
{ 
   U16 iter;                           // Loop counter

   SFRPAGE = ACTIVE_PAGE;              // Set for PCA0MD

   PCA0MD &= ~0x40;                    // Disable Watchdog Timer

   OSCILLATOR_Init ();                 // Initialize oscillator
   PORT_Init ();                       // Initialize crossbar and GPIO
   CAN0_Init ();                       // Start CAN peripheral

   CAN_RX_COMPLETE.U32 = 0x0000;       // Initialize as no messages received

   EIE2 |= 0x02;                       // Enable CAN interupts
   EA = 1;                             // Enable global interrupts

   // While all messages have not been received, blink the LED
   while ((CAN_RX_COMPLETE.U32 != RX_COMPLETE_MASK) || (CAN_ERROR))
   {
      LED = !LED;
      for (iter = 0; iter < 65000; iter++);
   }

   // Once all transmissions are complete, keep the LED on
   LED = 1;                            // Turn on LED

   while (1);
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Initialize the internal oscillator to 24 MHz
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
   U8 SFRPAGE_save = SFRPAGE;
   SFRPAGE = CONFIG_PAGE;

   OSCICN = 0x87;                      // Set internal oscillator divider to 1

   SFRPAGE = SFRPAGE_save;
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function configures the crossbar and ports pins.
//
// P0.6   digital  push-pull        CAN TX
// P0.7   digital  open-drain       CAN RX
//
// P1.3   digital  push-pull        LED
//
//-----------------------------------------------------------------------------

void PORT_Init (void)
{
   U8 SFRPAGE_save = SFRPAGE;
   SFRPAGE  = CONFIG_PAGE;             // Port SFR's on Configuration page

   P0MDOUT  |= 0x40;                   // P0.6 (CAN0 TX) is push-pull
   P1MDOUT  |= 0x08;                   // P1.3 (LED) is push-pull

   XBR0     = 0x02;                    // Enable CAN0 on Crossbar
   XBR2     = 0x40;                    // Enable Crossbar and weak pull-ups

   SFRPAGE = SFRPAGE_save;
}

//-----------------------------------------------------------------------------
// CAN0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function initializes the CAN peripheral and all of the message objects
//
// The following settings are chosen for the peripheral and message objects:
//
// CAN Bit Clock : 1 Mbps
// Auto Retransmit : Automatic Retransmission is enabled
// MsgVal        : Set to Valid based on the #define MESSAGE_OBJECTS
// Filtering     : Enabled for all valid message objects
// Message Identifier : 11-bit standard; Each message object is only used by
//                      one message ID and the ID is equal to the object number
// Direction     : All valid message objects are configured for receive
// End of Buffer : All message objects are treated as separate buffers
//
// The following interrupts are enabled and are handled by CAN0_ISR
//
// Error Interrupts
// Status Change Interrupt
// Receive Interrupt
//
//-----------------------------------------------------------------------------

void CAN0_Init (void)
{
   U8 iter;

   U8 SFRPAGE_save = SFRPAGE;
   SFRPAGE  = CAN0_PAGE;               // All CAN register are on page 0x0C

   CAN0CN |= 0x01;                     // Start Intialization mode

   //---------Initialize general CAN peripheral settings

   CAN0CN |= 0x4E;                     // Enable Status, Error, 
                                       // Module Interrupts
                                       // Enable access to bit timing register

   // See the CAN Bit Timing Spreadsheet for how to calculate this value
   CAN0BT = 0x1402;                    // Based on 24 Mhz CAN clock, set the
                                       // CAN bit rate to 1 Mbps

   //---------Initialize settings common to all message objects

   // Command Mask Register
   CAN0IF1CM = 0x00F0;                 // Write Operation
                                       // Transfer ID Mask, MDir, MXtd
                                       // Transfer ID, Dir, Xtd, MsgVal
                                       // Transfer Control Bits
                                       // Don't set TxRqst or transfer data

   // Mask Registers
   CAN0IF1M1 = 0x0000;                 // Mask Bits 15-0 not used for filtering
   CAN0IF1M2 = 0x5FFC;                 // Ignore Extended Identifier for 
                                       // filtering
                                       // Used Direction bit for filtering
                                       // Use ID bits 28-18 for filtering

   // Arbitration Registers
   CAN0IF1A1 = 0x0000;                 // 11-bit ID, so lower 16-bits not used

   // Message Control Registers
   CAN0IF1MC = 0x1480 | MESSAGE_SIZE;  // Enable Receive Interrupt
                                       // Message Object is a Single Message
                                       // Message Size set by #define


   //---------Initialize unique settings for each valid message object

   for (iter = 0; iter < MESSAGE_OBJECTS; iter++)
   {
      // For example purposes, set 11-bit identifier based on the message 
      // object that is used to receive it.

      // Arbitration Registers
      CAN0IF1A2 = 0x8000 | (iter << 2);  // Set MsgVal to valid
                                         // Set Object Direction to read
                                         // Set 11-bit Identifier to iter

      CAN0IF1CR = iter;                // Start command request
	  
	   while (!(CAN0IF1CRH & 0x80));    // Poll on Busy bit
   }

   //---------Initialize settings for unused message objects

   for (iter = MESSAGE_OBJECTS; iter < 32; iter++)
   {
      // Set remaining message objects to be Ignored
      CAN0IF1A2 = 0x0000;              // Set MsgVal to 0 to Ignore
      CAN0IF1CR = iter;                // Start command request
	  
	   while (!(CAN0IF1CRH & 0x80));    // Poll on Busy bit
   }

   CAN0CN &= ~0x41;                    // Return to Normal Mode and disable
                                       // access to bit timing register

   SFRPAGE = SFRPAGE_save;
}


//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// CAN0_ISR
//-----------------------------------------------------------------------------
//
// The ISR is triggered upon any CAN errors or upon reception of message
//
// If an error occurs, a global counter is updated
//
//-----------------------------------------------------------------------------

INTERRUPT (CAN0_ISR, INTERRUPT_CAN0)
{
   U8 iter;
   UU64 rx_data;

   // SFRPAGE is set to CAN0_Page automatically when ISR starts

   U8 status = CAN0STAT;               // Read status, which clears the Status
                                       // Interrupt bit pending in CAN0IID

   U8 Interrupt_ID = CAN0IID;          // Read which message object caused
                                       // the interrupt

   // new_data variable will now tell which message object is new.
   
   CAN0IF1CM = 0x007F;                 // Read all of message object to IF1
                                       // Clear IntPnd and newData

   CAN0IF1CR = Interrupt_ID;           // Start command request
	  
   while (!(CAN0IF1CRH & 0x80));       // Poll on Busy bit

   if (status & RxOk)                  // If transmit completed successfully
   {
       // Read all 8 data bytes to rxdata, even though they might not be valid
       rx_data.U16[0] = CAN0IF1DA1;    // First pair of bytes
       rx_data.U16[1] = CAN0IF1DA2;    // Second pair of bytes
       rx_data.U16[2] = CAN0IF1DB1;    // Third pair of bytes
       rx_data.U16[3] = CAN0IF1DB2;    // Fourth and last pair of bytes

       // Message Object 0 reports as 0x20 in the CAN0IID register, so 
       // convert it to 0x00
       if (Interrupt_ID == 0x20) 
       {
          Interrupt_ID = 0x00; 
       }

       for (iter = 0; iter < MESSAGE_SIZE; iter++)
	    {
          if (rx_data.U8[iter] != (Interrupt_ID + iter)) 
          {
             CAN_ERROR = 1; 
          } 
	    }

       // Set variable to indicate this message object's transfer completed
       // Bit-shifting doesn't work with an operator greater than 15, so
       // account for it 
       if (Interrupt_ID <= 15) 
       {
	       CAN_RX_COMPLETE.U32 |= (U16) (0x01 << Interrupt_ID); 
       }
       else if (Interrupt_ID <= 0x1F)
       {
          CAN_RX_COMPLETE.U16[MSB] |= (U16) (0x01 << (Interrupt_ID - 16)); 
       }
   }

   // If an error occured, simply update the global variable and continue
   if (status & LEC)                 
   {
       // The LEC bits identify the type of error, but those are grouped here
       if ((status & LEC) != 0x07) 
       {
          CAN_ERROR = 1; 
       }
   }

   if (status & BOff)
   {
      CAN_ERROR = 1;
   }

   if (status & EWarn)
   {
      CAN_ERROR = 1;
   }

   // Old SFRPAGE is popped off stack when ISR exits
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

⌨️ 快捷键说明

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