CANOpen紧急报文
生活随笔
收集整理的這篇文章主要介紹了
CANOpen紧急报文
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
緊急報文,當設備內部發生錯誤時觸發該對象,即發送設備內部錯誤代碼。
在canopen內部維持一個錯誤表,對發生的錯誤進行記錄。當錯誤發生后從表中查看該錯誤是否已經發生并未被解決時,則報告主站;如果錯誤被解決則從表中清除,當所有錯都被解決,則報告主站。
canopen記錄了所有錯誤的歷史記錄,當前是否有錯誤發生,所有錯誤掩碼,目前為止發生過的錯誤種數。
/* 緊急報文初始化 */
void emergencyInit(CO_Data *d)
{/* 按索引號0x1003和子索引號0x00注冊字典入口的回調函數 */RegisterSetODentryCallBack(d, 0x1003, 0x00, &OnNumberOfErrorsUpdate);/* 錯誤個數 */*d->error_number = 0;
}/* 緊急報文停止 */
void emergencyStop(CO_Data* d)
{}/* 發送緊急報文 */
UNS8 sendEMCY(CO_Data *d, UNS16 errCode, UNS8 errRegister, const void *Specific, UNS8 SpecificLength)
{Message m;MSG_WAR(0x3051, "sendEMCY", 0);/* cob_id */m.cob_id = (UNS16)(*(UNS32*)d->error_cobid);/* 數據幀 */m.rtr = NOT_A_REQUEST;/* 錯誤碼 */m.Data[0] = errCode & 0xFF;m.Data[1] = (errCode >> 8) & 0xFF;/* 錯誤掩碼 */m.Data[2] = errRegister;/* 集體字段 */if(Specific == NULL){m.Data[3] = 0;m.Data[4] = 0;m.Data[5] = 0;m.Data[6] = 0;m.Data[7] = 0;SpecificLength = 5;}else{if(SpecificLength > 5) SpecificLength = 5;memcpy(&m.Data[3], Specific, SpecificLength); }/* 數據包長度 */m.len = SpecificLength + 3;return canSend(d->canHandle,&m);
}/* 錯誤發生 */
UNS8 EMCY_setError(CO_Data *d, UNS16 errCode, UNS8 errRegMask, UNS16 addInfo)
{UNS8 index;UNS8 errRegister_tmp;/* 遍歷錯誤數據列表 */for(index = 0; index < EMCY_MAX_ERRORS; ++index){/* 如果該錯誤碼已經出現在錯誤列表中 */if(d->error_data[index].errCode == errCode){/* 該錯誤已經存在,則無需重復發送 */if(d->error_data[index].active){MSG_WAR(0x3052, "EMCY message already sent", 0);return 0;}/* 如果該錯誤不存在,則需要上報 */elsed->error_data[index].active = 1;break;}}/* 如果該錯誤在列表中不存在 */if(index == EMCY_MAX_ERRORS){/* 則遍歷列表,看看有沒有錯誤列表項未被錯誤占用 */for(index = 0; index < EMCY_MAX_ERRORS; ++index) {if(d->error_data[index].active == 0) break;}}/* 錯誤列表已經滿了,直接退出 */if(index == EMCY_MAX_ERRORS){MSG_ERR(0x3053, "error_data full", 0);return 1;}/* 將錯誤碼、錯誤掩碼、錯誤發生標志位重新賦值 */d->error_data[index].errCode = errCode;d->error_data[index].errRegMask = errRegMask;d->error_data[index].active = 1;/* 該節點已經存在錯誤 */d->error_state = Error_occurred;/* 遍歷整個錯誤列表 */for(index = 0, errRegister_tmp = 0; index < EMCY_MAX_ERRORS; ++index){/* 如果該錯誤已經發生 */if(d->error_data[index].active == 1){/* 則將錯誤掩碼記錄下來 */errRegister_tmp |= d->error_data[index].errRegMask;}}/* 將錯誤掩碼記錄下來 */*d->error_register = errRegister_tmp;/* 將錯誤歷史記錄向后偏移一個 */for(index = d->error_history_size - 1; index > 0; --index){*(d->error_first_element + index) = *(d->error_first_element + index - 1);}*(d->error_first_element) = errCode | ((UNS32)addInfo << 16);/* 已經發生的錯誤種數 */if(*d->error_number < d->error_history_size) {++(*d->error_number);}/* 發送緊急報文 */if(d->CurrentCommunicationState.csEmergency)return sendEMCY(d, errCode, *d->error_register, NULL, 0);else return 1;
}/* 錯誤恢復 */
void EMCY_errorRecovered(CO_Data* d, UNS16 errCode)
{UNS8 index;UNS8 errRegister_tmp;UNS8 anyActiveError = 0;/* 遍歷錯誤列表,找到該錯誤項 */for(index = 0; index < EMCY_MAX_ERRORS; ++index){if(d->error_data[index].errCode == errCode){ break;}}/* 如果找到該錯誤項并且未被解決 */if((index != EMCY_MAX_ERRORS) && (d->error_data[index].active == 1)){/* 首先將該錯誤置為已經解決 */d->error_data[index].active = 0;/* 遍歷錯誤列表,重新計算錯誤掩碼 */for(index = 0, errRegister_tmp = 0; index < EMCY_MAX_ERRORS; ++index){/* 如果該錯誤未被解決 */if(d->error_data[index].active == 1){/* 依然存在未解決錯誤 */anyActiveError = 1;/* 更新錯誤掩碼 */errRegister_tmp |= d->error_data[index].errRegMask;}}/* 如果不存在錯誤 */if(anyActiveError == 0){/* 將錯誤狀態設置為無錯誤 */d->error_state = Error_free;/* 發送緊急報文,通知主站所有錯誤已經解決 */if(d->CurrentCommunicationState.csEmergency)sendEMCY(d, 0x0000, 0x00, NULL, 0);}/* 記錄錯誤掩碼 */*d->error_register = errRegister_tmp;}elseMSG_WAR(0x3054, "recovered error was not active", 0);
}/* 緊急報文處理 */
void proceedEMCY(CO_Data* d, Message* m)
{UNS8 nodeID;UNS16 errCode;UNS8 errReg;MSG_WAR(0x3055, "EMCY received. Proceed. ", 0);/* 緊急報文數據長度始終8字節 */if(m->len != 8) {MSG_ERR(0x1056, "Error size EMCY. CobId : ", m->cob_id);return;}nodeID = m->cob_id & 0x7F;errCode = m->Data[0] | ((UNS16)m->Data[1] << 8);errReg = m->Data[2];/* 從節點上報錯誤回調函數 */(*d->post_emcy)(d, nodeID, errCode, errReg);
}
總結
以上是生活随笔為你收集整理的CANOpen紧急报文的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAN总线电平(隐性与显性)
- 下一篇: 大数据如何促进经济增长?中国优势及应对