一、CAN发送
CAN_TxHeaderTypeDef TXHeader;
CAN_RxHeaderTypeDef RXHeader;
uint8_t TXmessage[8] = {0};
uint8_t RXmessage[8];
void CANSendData(void)
{
uint32_t pTxMailBox;
TXHeader.StdId=0x401 + (BMUID << 3);
TXHeader.ExtId=0;
TXHeader.DLC=8;
TXHeader.IDE=CAN_ID_STD;
TXHeader.RTR=CAN_RTR_DATA;
TXHeader.TransmitGlobalTime = DISABLE;
if(rpmFan > 0)
{
TXmessage[0] = 1;//Fan working
}
else
{
TXmessage[0] = 0;
}
TXmessage[1] = 0;
TXmessage[2] = 0;
TXmessage[3] = 0;
TXmessage[4] = 0;
TXmessage[5] = 0;
TXmessage[6] = 0;
TXmessage[7] = 0;
if((BMUID != 0) && (CANSendEn_flg == 1))
{
HAL_CAN_AddTxMessage(&hcan,&TXHeader,TXmessage,&pTxMailBox);
}
}
二、CAN接收
CAN接收通常是通过中断接收,并将接收的信息暂存到一个buffer里,并周期性的去处理接收到的信息。
1.CAN接收中断,调用RXDateStackPress()函数,将接收信息压缩进buffer里
#define CAN_BUF_SIZE 100
#define BT_BASIC_TX_CAN_ID 0x703
#define BT_BASIC_RX_CAN_ID 0x702
#define BT_SERVER_TX_CAN_ID (BT_BASIC_TX_CAN_ID | (BMUID<<3))
#define BT_SERVER_RX_CAN_ID (BT_BASIC_RX_CAN_ID | (BMUID<<3))
#define BT_SERVER_CAN_CHL 0x00
typedef union
{
uint8_t W[19];
struct
{
uint32_t TimeStamp;
uint8_t Channel;
uint8_t DLC;
uint8_t IDE;
uint32_t ID;
uint8_t Data[8];
} B; /* Big-endian */
}CANBUF_tag; /* CAN Buffer */
typedef struct
{
uint8_t Channel;
uint32_t ID;
uint8_t Length;
uint8_t Extended;
uint8_t Remote;
uint8_t Data[8];
}CAN_APP_DATATYPE;
CAN_TxHeaderTypeDef TXHeader;
CAN_RxHeaderTypeDef RXHeader;
uint8_t TXmessage[8] = {0};
uint8_t RXmessage[8];
CANBUF_tag CanBuf[CAN_BUF_SIZE];
uint32_t can_rx_idx=0;
uint32_t can_rd_idx=0;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t RXmessage[8] = {0};
if(hcan->Instance==CAN)
{
if(HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&RXHeader,RXmessage) == HAL_OK)
{
RXDateStackPress(hcan, CAN_RX_FIFO0, &RXHeader, RXmessage);
}
}
}
void RXDateStackPress(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])
{
CanBuf[can_rx_idx].B.TimeStamp = 0;
CanBuf[can_rx_idx].B.Channel = 0;
if(pHeader->IDE == 4)
{
CanBuf[can_rx_idx].B.ID = pHeader->ExtId;
}
else
{
CanBuf[can_rx_idx].B.ID = pHeader->StdId;
}
CanBuf[can_rx_idx].B.DLC = pHeader->DLC;
CanBuf[can_rx_idx].B.IDE = pHeader->IDE;
memcpy(&CanBuf[can_rx_idx].B.Data, &aData[0], pHeader->DLC);
can_rx_idx++;
if(can_rx_idx >= CAN_BUF_SIZE)
{
can_rx_idx = 0;
}
}
2.周期性的检查buffer中是否有未处理的数据
void HandleRXData(void)
{
CANBUF_tag iCanBufStr;
uint8_t rx_data[8];
uint8_t rx_dlc;
uint16_t rx_id;
if(RXDateStackPop(&iCanBufStr))//received can buff not handle finish
{
memcpy(rx_data,iCanBufStr.B.Data,iCanBufStr.B.DLC);
rx_id = iCanBufStr.B.ID;
rx_dlc = iCanBufStr.B.DLC;
//boot message
if((rx_id == BT_SERVER_RX_CAN_ID)
&& (rx_dlc == 8)
&& (rx_data[0] == 0x02)
&& (rx_data[1] == 0x10)
&& (rx_data[2] == 0x03))
{
vStartBootLoader();
}
}
}
uint8_t RXDateStackPop(CANBUF_tag *tmp_buf)
{
uint8_t SearchMsgResult = 0;
if(can_rx_idx != can_rd_idx)
{
*tmp_buf = CanBuf[can_rd_idx];
can_rd_idx++;
if(can_rd_idx >= CAN_BUF_SIZE)
{
can_rd_idx = 0;
}
SearchMsgResult =1;
}
return SearchMsgResult;
}