?? canopdriver.c
字號:
ErrorReport(ERROR_SYNC_TIME_OUT, SYNCtimeCopy);
}
}
/*******************************************************************************
Process CANopen from main function (non blocking function)
*******************************************************************************/
//defines for using timers in main() (timers are immune on overflow)
#define TMR16Z(ttimerVariable) ttimerVariable = Timer16TempValue //time value set to 0
#define TMR16(ttimerVariable) (Timer16TempValue - ttimerVariable) //read time value
#define TMR8Z(ttimerVariable) ttimerVariable = Timer8TempValue //time value set to 0
#define TMR8(ttimerVariable) (Timer8TempValue - ttimerVariable) //read time value
//functions for using in main
void CO_SDOresponse(unsigned char cmd, unsigned long Data){
CO_SDOTXdata[0] = cmd;
CO_SDOTXdata[1] = CO_SDORXdata[1];
CO_SDOTXdata[2] = CO_SDORXdata[2];
CO_SDOTXdata[3] = CO_SDORXdata[3];
CO_SDOTXdata[4] = BYTE0(Data);
CO_SDOTXdata[5] = BYTE1(Data);
CO_SDOTXdata[6] = BYTE2(Data);
CO_SDOTXdata[7] = BYTE3(Data);
CO_CanSendOther(CO_NO_USR_CAN_BUFF);
}
void CO_ProcessMain(void){
static unsigned char i;
//timers (see "def.h")
unsigned int Timer16TempValue; //1ms interval, 65536 ms
unsigned char Timer8TempValue; //4ms interval, 1024 ms
//Status leds
static unsigned char tLEDflicker = 0, tLEDblink = 0;
static unsigned int tLEDflash = 0;
static char LEDflashState = 0;
//Heartbeat producer
static unsigned int tProducerHeartbeatTime = 0;
//EEPROM
static unsigned char EEPROM_index = 0;
//set timer 1ms temporary variables
INTCONbits.GIEL = 0;
Timer16TempValue = CO_Timer16Value; //1ms, max duration 65,535 sec
INTCONbits.GIEL = 1;
Timer8TempValue = Timer16TempValue >> 2; //4ms, max duration 1,023 sec
/* Reset communication ********************************************************/
if(CO_IsrHighSignal.ResetComm){
INTCONbits.GIEH = 0;
CO_InitResetComm();
INTCONbits.GIEH = 1;
}
/* Error handling and Emergency message sending *******************************/
//check errors from IsrHigh
if(CO_IsrHighSignal.Error.byte){
if(CO_IsrHighSignal.Error.bits.NMTlength){ErrorReport(ERROR_CO_RXMSG_NMTlength, 0); CO_IsrHighSignal.Error.bits.NMTlength = 0;}
if(CO_IsrHighSignal.Error.bits.NMTcmd){ErrorReport(ERROR_CO_RXMSG_NMTcmd, 0); CO_IsrHighSignal.Error.bits.NMTcmd = 0;}
if(CO_IsrHighSignal.Error.bits.HeartBeatLength){ErrorReport(ERROR_CO_RXMSG_HeartBeatLength, 0); CO_IsrHighSignal.Error.bits.HeartBeatLength = 0;}
if(CO_IsrHighSignal.Error.bits.SyncLength){ErrorReport(ERROR_CO_RXMSG_SyncLength, 0); CO_IsrHighSignal.Error.bits.SyncLength = 0;}
if(CO_IsrHighSignal.Error.bits.SDOlength){ErrorReport(ERROR_CO_RXMSG_SDOlength, 0); CO_IsrHighSignal.Error.bits.SDOlength = 0;}
if(CO_IsrHighSignal.Error.bits.PDOlength){ErrorReport(ERROR_CO_RXMSG_PDOlength, 0); CO_IsrHighSignal.Error.bits.PDOlength = 0;}
}
//check if errors are gone
// if((ERROR_BIT_READ(ERROR_CAN_TX_BUS_OFF)) && !COMSTATbits.TXBO)
// ErrorReset(ERROR_CAN_TX_BUS_OFF, COMSTAT);
if((ERROR_BIT_READ(ERROR_CAN_TX_BUS_PASSIVE)) && !COMSTATbits.TXBP)
ErrorReset(ERROR_CAN_TX_BUS_PASSIVE, COMSTAT);
if((ERROR_BIT_READ(ERROR_CAN_RX_BUS_PASSIVE)) && !COMSTATbits.RXBP)
ErrorReset(ERROR_CAN_RX_BUS_PASSIVE, COMSTAT);
if((ERROR_BIT_READ(ERROR_CAN_BUS_WARNING)) && !(COMSTAT&0x07))
ErrorReset(ERROR_CAN_BUS_WARNING, COMSTAT);
//calculate Error register
if(ErrorControl.CheckErrors){
ErrorControl.CheckErrors = 0;
//generic error
if(ERROR_REGISTER_BIT0_CONDITION) ODE_Error_Register |= 0x01;
else ODE_Error_Register &= 0xFE;
//communication error (overrun, error state)
if(ERROR_REGISTER_BIT4_CONDITION) ODE_Error_Register |= 0x10;
else ODE_Error_Register &= 0xEF;
//device profile specific error
if(ERROR_REGISTER_BIT5_CONDITION) ODE_Error_Register |= 0x20;
else ODE_Error_Register &= 0xDF;
//manufacturer specific error
if(ERROR_REGISTER_BIT7_CONDITION) ODE_Error_Register |= 0x80;
else ODE_Error_Register &= 0x7F;
//send emergency message
if(CO_NMToperatingState==NMT_PRE_OPERATIONAL || CO_NMToperatingState==NMT_OPERATIONAL){
static unsigned int tInhibitEmergency = 0;
//is new emergency, buffer free and no inhibit?
if(ErrorControl.EmergencyToSend && !(CO_TXCAN_SEMsendReq&2) &&
(TMR16(tInhibitEmergency) > (ODE_Inhibit_Time_Emergency/10))){
CO_EmergencyTXdata[0] = ErrorControl.EmergencyErrorCode & 0xFF;
CO_EmergencyTXdata[1] = ErrorControl.EmergencyErrorCode >> 8;
CO_EmergencyTXdata[2] = ODE_Error_Register;
CO_EmergencyTXdata[3] = ErrorControl.CodeVal;
CO_EmergencyTXdata[4] = ERROR_EMERGENCY_BYTE5;
CO_EmergencyTXdata[5] = ERROR_EMERGENCY_BYTE6;
CO_EmergencyTXdata[6] = ERROR_EMERGENCY_BYTE7;
CO_EmergencyTXdata[7] = ERROR_EMERGENCY_BYTE8;
CO_TXCAN_SEMsendReq |= 2;
PIE3bits.TXB2IE = 1; //inform ISR
ErrorControl.EmergencyToSend = 0;
TMR16Z(tInhibitEmergency);
//write to history
#if CO_NO_ERROR_FIELD > 0
if(ODE_Pre_Defined_Error_Field_NoOfErrors < CO_NO_ERROR_FIELD)
ODE_Pre_Defined_Error_Field_NoOfErrors++;
for(i=ODE_Pre_Defined_Error_Field_NoOfErrors-1; i>0; i--)
ODE_Pre_Defined_Error_Field[i] = ODE_Pre_Defined_Error_Field[i-1];
ODE_Pre_Defined_Error_Field[0] = ErrorControl.EmergencyErrorCode;
#endif
}
}
}
//in case of error enter pre-operational state
if(ODE_Error_Register && (CO_NMToperatingState == NMT_OPERATIONAL))
CO_NMToperatingState = NMT_PRE_OPERATIONAL;
/* SDO handling ***************************************************************/
//SDO download means, that SDO client wants to WRITE to object dictionary of SDO server (this node)
//SDO upload means, that SDO client wants to READ from object dictionary
//supported is only expedited transfer, that means max 4byte size of OD entry is possible
if(CO_SDOrequest){
unsigned int ii;
rom CO_objectDictionaryEntry* pODE = &CO_OD[0]; //pointer to selected object dictionary entry
PCB_BANDWIDTH_IsrLow(1);PCB_BANDWIDTH_IsrLow(1);//find pointer
for(ii=0; ii<CO_OD_NoOfElements; ii++){
if(CO_SDORXdata[2] == ((pODE->index)>>8) && CO_SDORXdata[1] == ((pODE->index)&0xff) &&
CO_SDORXdata[3] == pODE->subindex) break;
pODE++;
}
if(ii == CO_OD_NoOfElements) //object does not exist in OD
CO_SDOresponse(0x80, 0x06020000);
else if(pODE->length > 4) //length of ODE is not valid
CO_SDOresponse(0x80, 0x06040047); //general internal incompatibility in the device
else{
switch(CO_SDORXdata[0]>>5){ //check CCS
case 1: //Initiate SDO Download - request (only expedited transfer)
if((CO_SDORXdata[0] & 0x03) != 0x03)
CO_SDOresponse(0x80, 0x06010000); //unsupported access to an object
else if((4 - ((CO_SDORXdata[0]>>2)&0x03)) != pODE->length)
CO_SDOresponse(0x80, 0x06070010); //Length of service parameter does not match
else if(pODE->attribute == ATTR_RO || pODE->attribute == ATTR_CO)
CO_SDOresponse(0x80, 0x06010002); //attempt to write a read-only object
else{
if(pODE->pData>=0x1000){
#ifdef CO_ALLOW_FLASH_WRITE
INTCONbits.GIEH = 0;
//following function takes ~32 miliseconds
memcpyram2flash((rom void*)(pODE->pData), (void*)&CO_SDORXdata[4], pODE->length);
INTCONbits.GIEH = 1;
CO_SDOresponse(0x60, 0L);
#else
CO_SDOresponse(0x80, 0x06010002); //attempt to write a read-only object
#endif
}
else{
memcpy((void*)(pODE->pData), (void*)&CO_SDORXdata[4], pODE->length);
CO_SDOresponse(0x60, 0L);
}
}
break;
case 2: //Initiate SDO Upload - request (only expedited transfer)
if(pODE->attribute == ATTR_WO)
CO_SDOresponse(0x80, 0x06010001); //attempt to read a write-only object
else
CO_SDOresponse(0x43 | ((4-pODE->length) << 2),
(pODE->pData>=0x1000) ? *((rom unsigned long*)(pODE->pData)) : *((unsigned long*)(pODE->pData)));
break;
case 4: //Abort SDO transfer
break;
default:
CO_SDOresponse(0x80, 0x05040001); //send abort, command specifier not valid
}
}
CO_SDOrequest = 0;
}
/* Heartbeat producer message *************************************************/
//Sent only if not in TX passive, bootup send always
if((ODE_Producer_Heartbeat_Time && (TMR16(tProducerHeartbeatTime) >= ODE_Producer_Heartbeat_Time))
|| CO_NMToperatingState == NMT_INTIALIZING){
TMR16Z(tProducerHeartbeatTime);
CO_CanSendOther(CO_NO_USR_CAN_BUFF+1);
if(CO_NMToperatingState == NMT_INTIALIZING){
if((ODE_NMT_Startup & 0x04) == 0) CO_NMToperatingState = NMT_OPERATIONAL;
else CO_NMToperatingState = NMT_PRE_OPERATIONAL;
}
}
/* Heartbeat consumer message handling ****************************************/
//DS 301: "Monitoring starts after the reception of the first heartBeat. (Not bootup)"
#if CO_NO_CONS_HEARTBEAT > 0
for(i=0; i<CO_NO_CONS_HEARTBEAT; i++){
if((unsigned int)ODE_Consumer_Heartbeat_Time[i]){
if(CO_HBcons_NMTstate[i]){//Monitoring starts after the reception of the first heartbeat
unsigned int tTemp;
INTCONbits.GIEH = 0;
Timer16TempValue = CO_Timer16Value; //variable must be updated
tTemp = CO_HBcons_TimerValue[i];
INTCONbits.GIEH = 1;
if(TMR16(tTemp) > (unsigned int)ODE_Consumer_Heartbeat_Time[i]){
ErrorReport(ERROR_HEARTBEAT_CONSUMER, 0);
CO_HBcons_NMTstate[i] = NMT_INTIALIZING;
}
}
}
}
#endif
/* Status LEDs ****************************************************************/
//10Hz
if(TMR8(tLEDflicker) >= 25) TMR8Z(tLEDflicker);
if(TMR8(tLEDflicker) < 12) CO_StatusLED.Flickering = 0; else CO_StatusLED.Flickering = 1;
//2.5Hz
if(TMR8(tLEDblink) >= 100) TMR8Z(tLEDblink);
if(TMR8(tLEDblink) < 50) CO_StatusLED.Blinking = 0; else CO_StatusLED.Blinking = 1;
//flashes
switch(LEDflashState){
case 0: if(TMR16(tLEDflash) < 200) break;
LEDflashState++;
CO_StatusLED.SingleFlash = CO_StatusLED.DoubleFlash = CO_StatusLED.TripleFlash = 1;
case 1: if(TMR16(tLEDflash) < 400) break;
LEDflashState++;
CO_StatusLED.SingleFlash = CO_StatusLED.DoubleFlash = CO_StatusLED.TripleFlash = 0;
case 2: if(TMR16(tLEDflash) < 600) break;
LEDflashState++;
CO_StatusLED.DoubleFlash = CO_StatusLED.TripleFlash = 1;
case 3: if(TMR16(tLEDflash) < 800) break;
LEDflashState++;
CO_StatusLED.DoubleFlash = CO_StatusLED.TripleFlash = 0;
case 4: if(TMR16(tLEDflash) < 1000) break;
LEDflashState++;
CO_StatusLED.TripleFlash = 1;
case 5: if(TMR16(tLEDflash) < 1200) break;
LEDflashState++;
CO_StatusLED.TripleFlash = 0;
case 6: if(TMR16(tLEDflash) < 2000) break;
LEDflashState = 0;
TMR16Z(tLEDflash);
}
//green RUN LED (DR 303-3)
switch(CO_NMToperatingState){
case NMT_STOPPED:
PCB_RUN_LED(CO_StatusLED.SingleFlash);
break;
case NMT_PRE_OPERATIONAL:
PCB_RUN_LED(CO_StatusLED.Blinking);
break;
case NMT_OPERATIONAL:
PCB_RUN_LED(CO_StatusLED.On);
break;
}
//red ERROR LED (DR 303-3)
if(ERROR_BIT_READ(ERROR_CAN_TX_BUS_OFF)) PCB_ERROR_LED(CO_StatusLED.On);
else if(ERROR_BIT_READ(ERROR_SYNC_TIME_OUT)) PCB_ERROR_LED(CO_StatusLED.TripleFlash);
else if(ERROR_BIT_READ(ERROR_HEARTBEAT_CONSUMER)) PCB_ERROR_LED(CO_StatusLED.DoubleFlash);
else if( ERROR_BIT_READ(ERROR_CAN_TX_BUS_PASSIVE)
|| ERROR_BIT_READ(ERROR_CAN_RX_BUS_PASSIVE)
|| ERROR_BIT_READ(ERROR_CAN_BUS_WARNING)) PCB_ERROR_LED(CO_StatusLED.SingleFlash);
else if(ODE_Error_Register) PCB_ERROR_LED(CO_StatusLED.Blinking);//not in CiA standard
else PCB_ERROR_LED(CO_StatusLED.Off);
/* Update EEPROM **************************************************************/
//update one byte at a cycle
#ifdef CO_USE_EEPROM
if(EECON1bits.WR == 0){ //write is not in progress
if(EEPROM_index == 0) EEPROM_index = sizeof(ODE_EEPROM);
EEPROM_index--;
i = *((unsigned char*)&ODE_EEPROM + EEPROM_index);
//read eeprom
EEADR = EEPROM_index;
EECON1bits.EEPGD = 0;
EECON1bits.CFGS = 0;
EECON1bits.RD = 1;
if(EEDATA != i){
//write to EEPROM
EEDATA = i;
EECON1bits.WREN = 1;
INTCONbits.GIEH = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1;
INTCONbits.GIEH = 1;
EECON1bits.WREN = 0;
}
}
#endif
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -