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

📄 scu_am.c

📁 PATTERNS FOR TIME-TRIGGERED EMBEDDED SYSTEMS by Michael J. Pont This code is copyright (c) 200
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------*-

   SCU_Am.c (v1.00)

  ------------------------------------------------------------------

   This is an implementation of SCU SCHEDULER (LOCAL) for 8051/52.
   AND an implementation of SCU SCHEDULER (RS-232) for 8051/52.

   --- See Chapter 27 ---

   *** MASTER NODE ***
   *** CHECKS FOR SLAVE ACKNOWLEDEMENTS ***
   *** Local / RS-232 version (no 'enable' support) ***

   *** Uses 1232 watchdog timer ***

   *** Both Master and Slave share the same tick rate (5 ms) ***


   COPYRIGHT
   ---------

   This code is from the book:

   PATTERNS FOR TIME-TRIGGERED EMBEDDED SYSTEMS by Michael J. Pont 
   [Pearson Education, 2001; ISBN: 0-201-33138-1].

   This code is copyright (c) 2001 by Michael J. Pont.
 
   See book for copyright details and other information.

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

#include "Main.h"
#include "Port.h"

#include "SCU_Am.H"
#include "Delay_T0.h"
#include "TLight_B.h"

// ------ Public variable definitions ------------------------------

tByte Tick_message_data_G[NUMBER_OF_SLAVES] = {'1','2'};  
tByte Ack_message_data_G[NUMBER_OF_SLAVES];

// ------ Public variable declarations -----------------------------

// The array of tasks (see Sch51.c)
extern sTask SCH_tasks_G[SCH_MAX_TASKS];

// The error code variable (see Sch51.c)
extern tByte Error_code_G;

// ------ Private variable definitions -----------------------------

static tByte Current_slave_index_G = 0;
static bit First_ack_G = 1;
static bit WATCHDOG_state_G = 0;

// ------ Private function prototypes ------------------------------

static void SCU_A_MASTER_Reset_the_Network(void);
static void SCU_A_MASTER_Shut_Down_the_Network(void);
static void SCU_A_MASTER_Switch_To_Backup_Slave(const tByte);

static void SCU_A_MASTER_Send_Tick_Message(const tByte);
static bit  SCU_A_MASTER_Process_Ack(const tByte);

static void  SCU_A_MASTER_Watchdog_Init(void);
static void  SCU_A_MASTER_Watchdog_Refresh(void) reentrant;

// ------ Private constants ----------------------------------------

// Slave IDs may be any NON-ZERO tByte value (all must be different)
// NOTE: ID 0x00 is for error handling.
static const tByte MAIN_SLAVE_IDs[NUMBER_OF_SLAVES] = {0x31,0x32};
static const tByte BACKUP_SLAVE_IDs[NUMBER_OF_SLAVES] = {0x31,0x32};

#define NO_NETWORK_ERROR (1) 
#define NETWORK_ERROR (0)

// Adjust (if required) to increase interval between network resets
// (in the event of sustained network error)
#define SLAVE_RESET_INTERVAL 0U

// ------ Private variables ----------------------------------------

static tWord Slave_reset_attempts_G[NUMBER_OF_SLAVES];

// See MAIN_SLAVE_IDs[] above
static tByte Current_Slave_IDs_G[NUMBER_OF_SLAVES] = {0};

static bit Message_byte_G = 1;

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

  SCU_A_MASTER_Init_T1_T2()

  Scheduler initialisation function.  Prepares scheduler data 
  structures and sets up timer interrupts at required rate.
  You must call this function before using the scheduler.  

  BAUD_RATE - The required baud rate.

-*------------------------------------------------------------------*/
void SCU_A_MASTER_Init_T1_T2(const tWord BAUD_RATE) 
   {
   tByte Task_index;
   tByte Slave_index;

   // No interrupts (yet)
   EA = 0;

   // Start the watchdog
   SCU_A_MASTER_Watchdog_Init();

   Network_error_pin = NO_NETWORK_ERROR;

   // ------ Set up the scheduler ----------------------------------
   // Sort out the tasks
   for (Task_index = 0; Task_index < SCH_MAX_TASKS; Task_index++) 
      {
      SCH_Delete_Task(Task_index);
      }

   // Reset the global error variable
   // - SCH_Delete_Task() will generate an error code, 
   //   (because the task array is empty)
   Error_code_G = 0;

   // We allow any combination of ID numbers in slaves
   // - but reserve ID 0x00
   for (Slave_index = 0; Slave_index < NUMBER_OF_SLAVES; Slave_index++)
      {
      Slave_reset_attempts_G[Slave_index] = 0;
      Current_Slave_IDs_G[Slave_index] = MAIN_SLAVE_IDs[Slave_index];
      }

   // ------ Set the baud rate (begin) -----------------------------
   PCON &= 0x7F;   // Set SMOD bit to 0 (don't double baud rates)

   //  Receiver enabled
   //  *9-bit data*, 1 start bit, 1 stop bit, variable baud rate (asynchronous)
   SCON = 0xD2;

   TMOD |= 0x20;   // T1 in mode 2, 8-bit auto reload

   TH1 = (256 - (tByte)((((tLong)OSC_FREQ / 100) * 3125) 
            / ((tLong) BAUD_RATE * OSC_PER_INST * 1000)));

   TL1 = TH1;  
   TR1 = 1;  // Run the timer
   TI = 1;   // Send first character (dummy)
   // ------ Set the baud rate (end) -------------------------------

   // Serial interrupt *NOT* enabled
   ES = 0;
   // ------ Set up the serial link (end) --------------------------

   // ------ Set up Timer 2 (begin) --------------------------------
   // Crystal is assumed to be 12 MHz, 12 osc/increment
   //
   // The Timer 2 resolution is 0.000001 seconds (1 祍)
   // The required Timer 2 overflow is 0.005 seconds (5 ms)
   // - this takes 5000 timer ticks
   // Reload value is 65536 - 5000 = 60536 (dec) = 0xEC78

   T2CON = 0x04;   // load Timer 2 control register
   T2MOD = 0x00;   // load Timer 2 mode register

   TH2    = 0xEC;  // load timer 2 high byte
   RCAP2H = 0xEC;  // load timer 2 reload capture reg, high byte
   TL2    = 0x78;  // load timer 2 low byte
   RCAP2L = 0x78;  // load timer 2 reload capture reg, low byte
   
   ET2   = 1;  // Timer 2 interrupt is enabled

   TR2   = 1;  // Start Timer 2   
   // ------ Set up Timer 2 (end) ----------------------------------
   }

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

  SCU_A_MASTER_Start()

  Starts the scheduler, by enabling interrupts.

  NOTE: Usually called after all regular tasks are added,
  to keep the tasks synchronised.

  NOTE: ONLY THE SCHEDULER INTERRUPT SHOULD BE ENABLED!!! 

  NOTE: Delays here (2ms) assume a baud rate of at leadt 9600 baud.
  You will need to fine-tune this code if you opt for a lower baud
  rate.
 
-*------------------------------------------------------------------*/
void SCU_A_MASTER_Start(void) 
   {
   tByte Slave_ID;
   tByte Num_active_slaves;
   tByte Id, i;
   bit First_byte = 0;
   bit Slave_replied_correctly;
   tByte Slave_index;

   // Refresh the watchdog
   SCU_A_MASTER_Watchdog_Refresh();

   // Place system in 'safe state'
   SCU_A_MASTER_Enter_Safe_State();

   // Report error as we wait to start
   Network_error_pin = NETWORK_ERROR;

   Error_code_G = ERROR_SCH_WAITING_FOR_SLAVE_TO_ACK;
   SCH_Report_Status(); // Sch not yet running - do this manually

   // Pause here (3000 ms), to time-out all the slaves
   // (This is the means by which we synchronise the network)
   for (i = 0; i < 100; i++)
      {
      Hardware_Delay_T0(30);
      SCU_A_MASTER_Watchdog_Refresh();
      }     

   // Currently disconnected from all slaves
   Num_active_slaves = 0;

   // After the initial (long) delay, all (operational) slaves will have timed out.
   // All operational slaves will now be in the 'READY TO START' state
   // Send them a (single-byte) message to get them started
   // DO THIS TWICE IN A ROW, WITH COMMAND BIT 
   // This cannot happen under normal circumstances
   Slave_index = 0;
   do {
      // Refresh the watchdog
      SCU_A_MASTER_Watchdog_Refresh();

      // Clear 'first byte' flag
      First_byte = 0;

      // Find the slave ID for this slave 
      Slave_ID = (tByte) Current_Slave_IDs_G[Slave_index];  

      // Send a 'Slave ID' message
      TI = 0;
      TB8 = 1; // Set command bit
      SBUF = Slave_ID;          

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

      // Check we had a reply 
      if (RI == 1) 
         {
         // Get the reply data
         Id = (tByte) SBUF;  
         RI = 0;

         // Check reply - with command bit
         if ((Id == Slave_ID) && (RB8 == 1))
            {
            First_byte = 1;
            }
         }   

      // Send second byte
      TI = 0;
      TB8 = 1;
      SBUF = Slave_ID;   

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

      // Check we had a reply
      Slave_replied_correctly = 0;
      if (RI != 0)
         {
         // Get the reply data
         Id = (tByte) SBUF;  
         RI = 0;

         if ((Id == Slave_ID) && (RB8 == 1) && (First_byte == 1))
            {
            Slave_replied_correctly = 1;
            }
         }

      if (Slave_replied_correctly)
         {
         // Slave responded correctly
         Num_active_slaves++;
         Slave_index++;
         }
      else
         {
         // Slave did not reply correctly 
         // - try to switch to backup device (if available)
         if (Current_Slave_IDs_G[Slave_index] != BACKUP_SLAVE_IDs[Slave_index])
            {
            // There is a backup available: switch to backup and try again
            Current_Slave_IDs_G[Slave_index] = BACKUP_SLAVE_IDs[Slave_index];
            }
         else
            {
            // No backup available (or backup failed too) - have to continue
            // NOTE: we don't abort the loop, to allow for more flexible
            // error handling (below).
            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.

      // Here we display error and shut down the network
      Error_code_G = ERROR_SCH_ONE_OR_MORE_SLAVES_DID_NOT_START;
      SCU_A_MASTER_Shut_Down_the_Network();
      }
   else
      {
      Error_code_G = 0;
      Network_error_pin = NO_NETWORK_ERROR;
      }

   // Get ready to send first tick message
   Message_byte_G = 1;
   First_ack_G = 1;
   Current_slave_index_G = 0;

   // Start the scheduler
   EA = 1;   
   }


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

  SCU_A_MASTER_Update_T2

⌨️ 快捷键说明

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