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

📄 canopdriver.c

📁 Pic18Fxx8单片机下的canopen协议源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
         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 + -