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

📄 scc_m515.c

📁 基于8051共享时钟调度器的can总线通讯
💻 C
📖 第 1 页 / 共 2 页
字号:
            }
         else
            {
            // No backup available (or backup failed too) - have to continue
            Slave_index++;
            }
         }
      } while (Slave_index < NUMBER_OF_SLAVES);

   // DEAL WITH CASE OF MISSING SLAVE(S) HERE ...
   if (Num_active_slaves < NUMBER_OF_SLAVES)
      {
      // User-defined error handling here...
      // 1 or more slaves have not replied
      // NOTE: In some circumstances you may wish to abort if slaves are missing
      // - or reconfigure the network.

      // Simplest solution is to display an error and carry on
      // (this is what we do here)      
      Error_code_G = ERROR_SCH_ONE_OR_MORE_SLAVES_DID_NOT_START;
      Network_error_pin = NETWORK_ERROR;
      }
   else
      {
      Error_code_G = 0;
      Network_error_pin = NO_NETWORK_ERROR;
      }

   // Start the scheduler
   IRCON = 0;
   EAL = 1;   
   }

/*------------------------------------------------------------------*-

  SCC_A_MASTER_Update_T2

  This is the scheduler ISR.  It is called at a rate determined by 
  the timer settings in SCC_A_MASTER_Init_T2().  This version is 
  triggered by Timer 2 interrupts: timer is automatically reloaded.
 
-*------------------------------------------------------------------*/
void SCC_A_MASTER_Update_T2(void) interrupt INTERRUPT_Timer_2_Overflow  
   {
   tByte Index;
   tByte Previous_slave_index;
   bit Slave_replied_correctly;

   TF2 = 0;  // Must clear this. 

   // Refresh the watchdog
   SCC_A_MASTER_Watchdog_Refresh();

   // Default
   Network_error_pin = NO_NETWORK_ERROR;

   // Keep track of the current slave
   Previous_slave_index = Slave_index_G;   // First value of prev slave is 0...

   if (++Slave_index_G >= NUMBER_OF_SLAVES)
      {
      Slave_index_G = 0;
      }    

   // Check that the appropriate slave responded to the previous message:
   // (if it did, store the data sent by this slave)
   if (SCC_A_MASTER_Process_Ack(Previous_slave_index) == RETURN_ERROR)
      {
      Error_code_G = ERROR_SCH_LOST_SLAVE;
      Network_error_pin = NETWORK_ERROR;

      // If we have lost contact with a slave, we attempt to
      // switch to a backup device (if one is available)
      if (Current_Slave_IDs_G[Slave_index_G] != BACKUP_SLAVE_IDs[Slave_index_G])
         {
         // There is a backup available: switch to backup and try again
         Current_Slave_IDs_G[Slave_index_G] = BACKUP_SLAVE_IDs[Slave_index_G];
         }
      else
         {
         // There is no backup available (or we are already using it) 
         // Try main device.
         Current_Slave_IDs_G[Slave_index_G] = MAIN_SLAVE_IDs[Slave_index_G];
         }

      // Try to connect to the slave
      Slave_replied_correctly = SCC_A_MASTER_Start_Slave(Current_Slave_IDs_G[Slave_index_G]);

      if (!Slave_replied_correctly)
         {
         // No backup available (or backup failed too) - we shut down
         // OTHER BEHAVIOUR MAY BE MORE APPROPRIATE IN YOUR APPLICATION
         SCC_A_MASTER_Shut_Down_the_Network();
         }
      }
  
   // Send 'tick' message to all connected slaves
   // (sends one data byte to the current slave)
   SCC_A_MASTER_Send_Tick_Message(Slave_index_G);

   // Check the last error codes on the CAN bus via the status register
   if ((CAN_sr & 0x07) != 0)
      {
      Error_code_G = ERROR_SCH_CAN_BUS_ERROR;
      Network_error_pin = NETWORK_ERROR;
   
      // See Infineon c515c manual for error code details
      CAN_error_pin0 = ((CAN_sr & 0x01) == 0);
      CAN_error_pin1 = ((CAN_sr & 0x02) == 0);
      CAN_error_pin2 = ((CAN_sr & 0x04) == 0);
      }
   else
      {
      CAN_error_pin0 = 1;
      CAN_error_pin1 = 1;
      CAN_error_pin2 = 1;
      }

   // NOTE: calculations are in *TICKS* (not milliseconds)
   for (Index = 0; Index < SCH_MAX_TASKS; Index++)
      {
      // Check if there is a task at this location
      if (SCH_tasks_G[Index].pTask)
         {
         if (SCH_tasks_G[Index].Delay == 0)
            {
            // The task is due to run
            SCH_tasks_G[Index].RunMe += 1;  // Incr. the 'Run Me' flag

            if (SCH_tasks_G[Index].Period)
               {
               // Schedule rperiodic tasks to run again
               SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
               }
            }
         else
            {
            // Not yet ready to run: just decrement the delay 
            SCH_tasks_G[Index].Delay -= 1;
            }
         }         
      }
   }   

/*------------------------------------------------------------------*-

  SCC_A_MASTER_Send_Tick_Message()

  This function sends a tick message, over the CAN network.
  The receipt of this message will cause an interrupt to be generated
  in the slave(s): this invoke the scheduler 'update' function
  in the slave(s).

-*------------------------------------------------------------------*/
void SCC_A_MASTER_Send_Tick_Message(const tByte SLAVE_INDEX) 
   {
   // Find the slave ID for this slave 
   // ALL SLAVES MUST HAVE A UNIQUE (non-zero) ID
   tByte Slave_ID = (tByte) Current_Slave_IDs_G[SLAVE_INDEX];
   CAN_messages[0].Data[0] = Slave_ID;   

   // Fill the data fields 
   CAN_messages[0].Data[1] = Tick_message_data_G[SLAVE_INDEX][0];   
   CAN_messages[0].Data[2] = Tick_message_data_G[SLAVE_INDEX][1];   
   CAN_messages[0].Data[3] = Tick_message_data_G[SLAVE_INDEX][2];   
   CAN_messages[0].Data[4] = Tick_message_data_G[SLAVE_INDEX][3];   

   // Send the message on the CAN bus
   CAN_messages[0].MCR1 = 0xE7;  // TXRQ, reset CPUUPD
   }

/*------------------------------------------------------------------*-

  SCC_A_MASTER_Process_Ack()

  Make sure the slave (SLAVE_ID) has acknowledged the previous
  message that was sent.  If it has, extract the message data
  from the USART hardware: if not, call the appropriate error
  handler.

  PARAMS:   The index of the slave. 

  RETURNS:  RETURN_NORMAL - Ack received (data in Ack_message_data_G)
            RETURN_ERROR  - No ack received (-> no data)

-*------------------------------------------------------------------*/

bit SCC_A_MASTER_Process_Ack(const tByte SLAVE_INDEX) 
   {
   tByte Ack_ID, Slave_ID;

   // First time this is called there is no ack tick to check 
   // - we simply return 'OK'
   if (First_ack_G)
      {
      First_ack_G = 0;
      return RETURN_NORMAL;
      }

   if ((CAN_messages[1].MCR1 & 0x03) == 0x02)    // if NEWDAT
      {
      // An ack message was received
      //
      // Extract the data
      Ack_ID = CAN_messages[1].Data[0];   // Get data byte 0

      Ack_message_data_G[SLAVE_INDEX][0] = CAN_messages[1].Data[1];   
      Ack_message_data_G[SLAVE_INDEX][1] = CAN_messages[1].Data[2];   
      Ack_message_data_G[SLAVE_INDEX][2] = CAN_messages[1].Data[3];   
      Ack_message_data_G[SLAVE_INDEX][3] = CAN_messages[1].Data[4];   

      CAN_messages[1].MCR0 = 0xfd;  // reset NEWDAT, INTPND
      CAN_messages[1].MCR1 = 0xfd;
      
      // Find the slave ID for this slave 
      Slave_ID = (tByte) Current_Slave_IDs_G[SLAVE_INDEX];

      if (Ack_ID == Slave_ID)
         {
         return RETURN_NORMAL;
         }
      }

   // No message, or ID incorrect
   return RETURN_ERROR;  
   }


/*------------------------------------------------------------------*-

  SCC_A_MASTER_Shut_Down_the_Network()

  This function will be called when a slave fails to 
  acknowledge a tick message.

-*------------------------------------------------------------------*/
void SCC_A_MASTER_Shut_Down_the_Network(void)
   {
   EAL = 0;

   while(1)
      {
      SCC_A_MASTER_Watchdog_Refresh();
      }  
   }

/*------------------------------------------------------------------*-

  SCC_A_MASTER_Enter_Safe_State()

  This is the state enterted by the system when:
  (1) The node is powered up or reset
  (2) The Master node cannot detect a slave
  (3) The network has an error

  Try to ensure that the system is in a 'safe' state in these 
  circumstances.

-*------------------------------------------------------------------*/
void SCC_A_MASTER_Enter_Safe_State(void)
   {
   // USER DEFINED - Edit as required

   TRAFFIC_LIGHTS_Display_Safe_Output();
   } 

/*------------------------------------------------------------------*-

   SCC_A_MASTER_Watchdog_Init()

  This function sets up the watchdog timer.

-*------------------------------------------------------------------*/
void SCC_A_MASTER_Watchdog_Init(void)   
   {
   // Watchdog timer prescaler (1/16) enabled 
   // Watchdog timer reload value is 0x6B
   // Oscillator is 10 MHz -> watchdog period is ~103 ms
   WDTREL = 0xEB;
  
   // Start watchdog timer
   WDT  = 1;
   SWDT = 1;
   }

/*------------------------------------------------------------------*-

  SCC_A_MASTER_Watchdog_Refresh()

  Feed the internal c515c watchdog.

-*------------------------------------------------------------------*/
void SCC_A_MASTER_Watchdog_Refresh(void) reentrant
   {
   WDT = 1; 
   SWDT = 1;
   }   

/*------------------------------------------------------------------*-

  SCC_A_MASTER_Start_Slave()

  Try to connect to a slave device.

-*------------------------------------------------------------------*/
tByte SCC_A_MASTER_Start_Slave(const tByte SLAVE_ID) reentrant
   {
   tByte Slave_replied_correctly = 0;

//   tByte Slave_ID;
   tByte Ack_ID, Ack_00;

   // Send a 'Slave ID' message
   CAN_messages[0].Data[0] = 0x00;  // Not a valid slave ID    
   CAN_messages[0].Data[1] = SLAVE_ID;    
   CAN_messages[0].MCR1 = 0xE7;  // Send it

   // Wait to give slave time to reply
   Hardware_Delay_T0(5);   

   // Check we had a reply
   if ((CAN_messages[1].MCR1 & 0x03) == 0x02)    // if NEWDAT
      {
      // An ack message was received - extract the data
      Ack_00 = (tByte) CAN_messages[1].Data[0];  // Get data byte 0
      Ack_ID = (tByte) CAN_messages[1].Data[1];  // Get data byte 1

      CAN_messages[1].MCR0 = 0xfd;  // reset NEWDAT, INTPND
      CAN_messages[1].MCR1 = 0xfd;

      if ((Ack_00 == 0x00) && (Ack_ID == SLAVE_ID)) 
         {
         Slave_replied_correctly = 1;
         }
      }

   return Slave_replied_correctly;
   }
  

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

⌨️ 快捷键说明

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