|
|
#include "zcanreceiver.hpp"
#ifdef HAL_CAN_MODULE_ENABLED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stm32basic/zbasic.h"
#define TAG "ZCanReceiver"
#define OVER_TIME_MS 100
#ifdef ENABLE_OLD_CAN_PROTOCOL
#include "stm32halport/stm32halport.hpp"
extern "C" { void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0CompleteCallback"); } void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1CompleteCallback"); } void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2CompleteCallback"); } void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0AbortCallback"); } void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1AbortCallback"); } void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2AbortCallback"); } void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { ZCanReceiver::ins()->STM32_HAL_onCAN_RxFifo0MsgPending(hcan); } void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo0FullCallback"); } void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1MsgPendingCallback"); } void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1FullCallback"); } void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_SleepCallback"); } void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_WakeUpFromRxMsgCallback"); } void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { ZCanReceiver::ins()->STM32_HAL_onCAN_Error(hcan); } }
ZCanReceiver *ZCanReceiver::ins() { static ZCanReceiver ins; return &ins; }
ZCanReceiver::CFG *ZCanReceiver::createCFG(uint8_t deviceId) { CFG *cfg = new CFG(); ZASSERT(cfg != NULL); cfg->deviceId = deviceId; #ifdef STM32F103xB
cfg->canHandle = &hcan; #else
cfg->canHandle = &hcan1; #endif
cfg->canFilterIndex0 = 0; cfg->maxFilterNum = 7; cfg->rxfifoNum = CAN_RX_FIFO0; return cfg; } void ZCanReceiver::init(CFG *cfg) { HAL_StatusTypeDef hal_status; m_config = cfg;
/**
* @brief 初始化CAN */
/**
* @brief 初始化消息接收buf */ m_canPacketRxBuffer[0].dataIsReady = false; m_canPacketRxBuffer[0].id = 1; // 只接收来自主机的消息
m_canPacketRxBuffer[0].m_canPacketNum = 0;
/**
* @brief 初始化过滤器 */ hal_status = initializeFilter(); if (hal_status != HAL_OK) { ZLOGE(TAG, "start can initializeFilter fail\r\n"); return; } /**
* @brief 启动CAN */ hal_status = HAL_CAN_Start(m_config->canHandle); // 开启CAN
if (hal_status != HAL_OK) { ZLOGE(TAG, "start can fail\r\n"); return; }
HAL_StatusTypeDef status = activateRxIT(); if (status != HAL_OK) { ZLOGE(TAG, "activateRxIT fail\r\n"); return; } } HAL_StatusTypeDef ZCanReceiver::initializeFilter() { /**
* @brief ID区帧格式 * [ 27:0 ] * [ STDID ] [ EXTID ] * [11 :9] [8:6] [5:0] [17:16] [15:8] [7:0] * 优先级 属性 帧类型 目标ID 源ID */ HAL_StatusTypeDef HAL_Status; CAN_FilterTypeDef sFilterConfig;
uint32_t filterId; uint32_t mask;
memset(&sFilterConfig, 0, sizeof(sFilterConfig)); sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // 设为MASK模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // CAN_FILTERSCALE_16BIT
sFilterConfig.FilterFIFOAssignment = m_config->rxfifoNum; // 关联过滤器到rxfifoNum
sFilterConfig.FilterActivation = ENABLE; // 激活过滤器
sFilterConfig.SlaveStartFilterBank = m_config->maxFilterNum; // slave filter start index
/*******************************************************************************
* 接收所有消息 * *******************************************************************************/ filterId = (0); //
mask = (0); //
sFilterConfig.FilterBank = m_config->canFilterIndex0; //
sFilterConfig.FilterMaskIdLow = mask & 0xffff; //
sFilterConfig.FilterMaskIdHigh = (mask & 0xffff0000) >> 16; //
sFilterConfig.FilterIdLow = filterId & 0xffff; //
sFilterConfig.FilterIdHigh = (filterId & 0xffff0000) >> 16; //
HAL_Status = HAL_CAN_ConfigFilter(m_config->canHandle, &sFilterConfig); if (HAL_Status != HAL_OK) { ZLOGE(TAG, "HAL_CAN_ConfigFilter filter0 fail"); return HAL_Status; } ZLOGI(TAG, "HAL_CAN_ConfigFilter filterID1 %08x", filterId >> 3); return HAL_Status; }
void ZCanReceiver::registerListener(zcanbus_on_rx_t listener) { m_onRxData = listener; } void ZCanReceiver::sendPacket(uint8_t *packet, size_t len, int overtime) { /**
* @brief */ int npacket = len / 8 + (len % 8 == 0 ? 0 : 1); if (npacket > 255) { ZLOGE(TAG, "sendPacket fail, len:%d", len); return; } int finalpacketlen = len % 8 == 0 ? 8 : len % 8;
for (uint8_t i = 0; i < npacket; i++) { bool suc = false; if (i == npacket - 1) { suc = sendPacketSub(npacket, i, packet + i * 8, finalpacketlen, overtime); } else { suc = sendPacketSub(npacket, i, packet + i * 8, 8, overtime); } if (!suc) { ZLOGE(TAG, "sendPacket fail, packet(%d:%d)", npacket, i); return; } } }
void ZCanReceiver::sendAck(transmit_disinfection_protocol_header_t *cmdheader, uint8_t *data, size_t len) { transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff; memcpy(txheader, cmdheader, sizeof(transmit_disinfection_protocol_header_t)); txheader->packetType = kpt_ack; memcpy(txheader->data, data, len); sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + len, OVER_TIME_MS); }
void ZCanReceiver::sendErrorAck(transmit_disinfection_protocol_header_t *cmdheader, int16_t errcode) { transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff; memcpy(txheader, cmdheader, sizeof(transmit_disinfection_protocol_header_t)); txheader->packetType = kpt_error_ack; memcpy(txheader->data, &errcode, sizeof(errcode)); sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + 2, OVER_TIME_MS); } void ZCanReceiver::sendReport(uint16_t cmdid, uint8_t subcmdid, uint8_t *attachments, size_t len) { transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff; txheader->packetindex = report_index++; txheader->cmdid = cmdid; txheader->subcmdid = subcmdid; txheader->packetType = kpt_status_report; memcpy(txheader->data, attachments, len); sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + len, OVER_TIME_MS); }
bool ZCanReceiver::sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems) { CAN_TxHeaderTypeDef pHeader; uint8_t aData[8] /*8byte table*/; uint32_t txMailBox = 0;
uint32_t enterticket = HAL_GetTick();
memset(&pHeader, 0, sizeof(pHeader)); memset(aData, 0, sizeof(aData)); pHeader.StdId = 0x00; pHeader.ExtId = (m_config->deviceId << 16) | (npacket << 8) | packetIndex; pHeader.IDE = CAN_ID_EXT; pHeader.RTR = CAN_RTR_DATA; pHeader.DLC = len; pHeader.TransmitGlobalTime = DISABLE;
memcpy(aData, packet, len);
m_lastTransmitStatus = HAL_CAN_AddTxMessage(m_config->canHandle, &pHeader, aData, &txMailBox); if (m_lastTransmitStatus != HAL_OK) { ZLOGE(TAG, "HAL_CAN_AddTxMessage fail"); return false; }
while (HAL_CAN_IsTxMessagePending(m_config->canHandle, txMailBox)) { if (zhas_passedms(enterticket) > (uint32_t)overtimems) { m_lastTransmitStatus = HAL_TIMEOUT; HAL_CAN_AbortTxRequest(m_config->canHandle, txMailBox); return false; } // m_os->sleepMS(1);
} return true; }
bool ZCanReceiver::getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/) { /**
* @brief 读取当前FIFO中缓存了多少帧的数据 */ uint32_t level = HAL_CAN_GetRxFifoFillLevel(m_config->canHandle, m_config->rxfifoNum); if (level == 0) { return false; } HAL_StatusTypeDef HAL_RetVal; HAL_RetVal = HAL_CAN_GetRxMessage(m_config->canHandle, m_config->rxfifoNum, pHeader, aData); if (HAL_OK == HAL_RetVal) { // 处理接收到的can总线数据
return true; } return false; } void ZCanReceiver::registerListener(CanPacketRxBufferCB_t cb) { m_listenerCBList.push_back(cb); }
void ZCanReceiver::STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *canHandle) { /**
* @brief 中断上下文 */ // ZLOG_INFO("%s\n", __FUNCTION__);
// printf("------------------%s\n", __FUNCTION__);
if (canHandle != m_config->canHandle) { return; } /**
* @brief 处理can接收到消息 */ CAN_RxHeaderTypeDef pHeader; uint8_t aData[8] /*8byte table*/; while (getRxMessage(&pHeader, aData)) { /**
* @brief 消息格式 * * [2] [3bit] [8bit] [8bit] [8bit] * , from frameNum frameId */ uint8_t from = (pHeader.ExtId >> 16 & 0xFF); uint8_t nframe = (pHeader.ExtId & 0xFF00) >> 8; uint8_t frameId = (pHeader.ExtId & 0x00FF); CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[0];
// CAN_ID_STD
// CAN_ID_EXT
if (pHeader.IDE == CAN_ID_STD) { // 只接收扩展帧数据帧
continue; }
if (from != rxbuf->id) { // 目前只接收来自主机的消息
continue; }
if (rxbuf->dataIsReady) { // 上次接收到的消息还没有来的急处理
continue; } /**
* @TODO:判断是否丢包 */ if (frameId == 0) { rxbuf->m_canPacketNum = 0; }
if (rxbuf->m_canPacketNum < 255) { rxbuf->m_canPacket[rxbuf->m_canPacketNum].pHeader = pHeader; memcpy(rxbuf->m_canPacket[rxbuf->m_canPacketNum].aData, aData, 8); rxbuf->m_canPacketNum++; } if (nframe == frameId + 1) { rxbuf->dataIsReady = true; rxbuf->maxFrameId = frameId; } }
// deactivateRxIT();
} void ZCanReceiver::STM32_HAL_onCAN_Error(CAN_HandleTypeDef *canHandle) { if (canHandle != m_config->canHandle) { return; } ZLOGE(TAG, "onCAN_Error\r\n"); } void ZCanReceiver::loop() { CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[0]; if (rxbuf->dataIsReady) { int dataoff = 0; for (size_t i = 0; i < rxbuf->m_canPacketNum; i++) { memcpy(rxdata + dataoff, rxbuf->m_canPacket[i].aData, rxbuf->m_canPacket[i].pHeader.DLC); dataoff += rxbuf->m_canPacket[i].pHeader.DLC; memset(&rxbuf->m_canPacket[i], 0, sizeof(rxbuf->m_canPacket[i])); } if (m_onRxData) { m_onRxData(rxbuf, rxdata, dataoff); }
for (auto &var : m_listenerCBList) { if (var) var(rxbuf, rxdata, dataoff); } rxbuf->dataIsReady = false; } } HAL_StatusTypeDef ZCanReceiver::activateRxIT() { HAL_StatusTypeDef hal_status = HAL_ERROR; if (m_config->rxfifoNum == CAN_RX_FIFO0) { hal_status = HAL_CAN_ActivateNotification(m_config->canHandle, CAN_IT_RX_FIFO0_MSG_PENDING); } else if (m_config->rxfifoNum == CAN_RX_FIFO1) { hal_status = HAL_CAN_ActivateNotification(m_config->canHandle, CAN_IT_RX_FIFO1_MSG_PENDING); } else { ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n"); return hal_status; } return hal_status; } HAL_StatusTypeDef ZCanReceiver::deactivateRxIT() { HAL_StatusTypeDef hal_status = HAL_ERROR; if (m_config->rxfifoNum == CAN_RX_FIFO0) { hal_status = HAL_CAN_DeactivateNotification(m_config->canHandle, CAN_IT_RX_FIFO0_MSG_PENDING); } else if (m_config->rxfifoNum == CAN_RX_FIFO1) { hal_status = HAL_CAN_DeactivateNotification(m_config->canHandle, CAN_IT_RX_FIFO1_MSG_PENDING); } else { ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n"); return hal_status; } return hal_status; }
#endif
#endif
|