CAN通信是控制电机运动的重要通信方式之一,具体使用方法如下:
can.h文件与can.cpp的使用
can .h
#pragma once
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_can.h"
#include <cstdlib>
#include <cstring>
class CAN
{
public:
void Init(CAN_TypeDef* instance);
void InitFilter();
HAL_StatusTypeDef Transmit(const uint32_t ID,
const uint8_t*const pData,
const uint8_t len = 8);
CAN_HandleTypeDef hcan;
uint8_t data[8][8];
private:
CanTxMsgTypeDef TxMessage;
CanRxMsgTypeDef RxMessage;
};
extern CAN can1, can2;
can.cpp
#include "can.h"
#include "PID.h"
void CAN::Init(CAN_TypeDef* instance)
{
hcan.Instance = instance;
hcan.Init.Prescaler = 6;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SJW = CAN_SJW_1TQ;
hcan.Init.BS1 = CAN_BS1_2TQ;
hcan.Init.BS2 = CAN_BS2_4TQ;
hcan.Init.TTCM = DISABLE;
hcan.Init.ABOM = ENABLE;
hcan.Init.AWUM = ENABLE;
hcan.Init.NART = DISABLE;
hcan.Init.RFLM = DISABLE;
hcan.Init.TXFP = DISABLE;
HAL_CAN_Init(&hcan);
HAL_CAN_Transmit_IT(&hcan);
HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);
InitFilter();
}
void CAN::InitFilter()
{
//can1 &can2 use same filter config
CAN_FilterConfTypeDef CAN_FilterConfigStructure;
CAN_FilterConfigStructure.FilterNumber = 0;
CAN_FilterConfigStructure.FilterMode = CAN_FILTERMODE_IDMASK;
CAN_FilterConfigStructure.FilterScale = CAN_FILTERSCALE_32BIT;
CAN_FilterConfigStructure.FilterIdHigh = 0x0000;
CAN_FilterConfigStructure.FilterIdLow = 0x0000;
CAN_FilterConfigStructure.FilterMaskIdHigh = 0x0000;
CAN_FilterConfigStructure.FilterMaskIdLow = 0x0000;
CAN_FilterConfigStructure.FilterFIFOAssignment = CAN_FilterFIFO0;
//can1(0-13)和can2(14-27)分别得到一半的filter
CAN_FilterConfigStructure.BankNumber = 0;
CAN_FilterConfigStructure.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&hcan, &CAN_FilterConfigStructure);
//filter config for can2
//can1(0-13)和can2(14-27)分别得到一半的filter
CAN_FilterConfigStructure.FilterNumber = 14;
HAL_CAN_ConfigFilter(&hcan, &CAN_FilterConfigStructure);
hcan.pTxMsg = &TxMessage;
hcan.pRxMsg = &RxMessage;
}
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
GPIO_InitTypeDef GPIO_InitStruct;
if (hcan->Instance == CAN1)
{
/* Peripheral clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**CAN1 GPIO Configuration
PD0 ------> CAN1_RX
PD1 ------> CAN1_TX*/
GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(CAN1_TX_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_TX_IRQn);
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
}
else if (hcan->Instance == CAN2)
{
/* Peripheral clock enable */
__HAL_RCC_CAN2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**CAN1 GPIO Configuration
PB12 ------> CAN2_RX
PB13 ------> CAN2_TX*/
GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(CAN2_TX_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN2_TX_IRQn);
HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn);
}
}
extern "C" void CAN1_TX_IRQHandler()
{
HAL_CAN_IRQHandler(&can1.hcan);
}
extern "C" void CAN1_RX0_IRQHandler()
{
HAL_CAN_IRQHandler(&can1.hcan);
}
extern "C" void CAN2_TX_IRQHandler()
{
HAL_CAN_IRQHandler(&can2.hcan);
}
extern "C" void CAN2_RX0_IRQHandler()
{
HAL_CAN_IRQHandler(&can2.hcan);
}
HAL_StatusTypeDef CAN::Transmit(const uint32_t ID, const uint8_t*const pData, const uint8_t len)
{
hcan.pTxMsg->StdId = ID;
hcan.pTxMsg->IDE = CAN_ID_STD;
hcan.pTxMsg->RTR = CAN_RTR_DATA;
hcan.pTxMsg->DLC = len;
memcpy(hcan.pTxMsg->Data, pData, len);
return HAL_CAN_Transmit(&hcan, 10);
}
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
{
if (hcan == &can1.hcan)memcpy(can1.data[hcan->pRxMsg->StdId - 0x201], hcan->pRxMsg->Data, sizeof(uint8_t) * 8);
else memcpy(can2.data[hcan->pRxMsg->StdId - 0x201], hcan->pRxMsg->Data, sizeof(uint8_t) * 8);
/*#### add enable can it again to solve can receive only one ID problem!!!####**/
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP0);
}
将我们的项目文件添加如上两个文件,文件中包括CAN通信的收发方式,可以更方便我们使用CAN通信来进行电机代码的编写