📄 scc_m515.c
字号:
}
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 + -