工具:
KEIL5.23
cubemx 6.0.1
广成科技USBCAN卡
步骤1:cubemx生成基础工程
1 时钟配置比较简单,不做介绍,CAN时钟配置成80Mhz,根据“Prescaler”“Seg1”“Seg2”计算可得到波特率位500kbps(Nominal和Data可以设置为不同波特率,这里为了方便,均设置为500K)。
2 Can发送配置。一定要把“Tx Fifo Queue Elmts Nbr”“Tx Fifo Queue Mode”“Tx Elmt Size”设置如下所示。发送只需要FIFO,没有发送滤波器。
3 Can接收配置。接收相比发送,主要是多了一个滤波器,注意:cubemx只是设置了滤波器,接收滤波器更详细的设计需要用户另外添加。cubemx只需要设置(以标准帧为例)“Std Filters Nbr”和“Rx Fifo0 Elmts Nbr”“Rx Fifo0 Elmt Size”即可。
4 生成基础工程。
步骤2:手动添加代码,实现发送和接收
主函数如下:在背景循环实现发送,在中断接收回调函数,处理接收的数据。
/* USER CODE BEGIN PV */
FDCAN_TxHeaderTypeDef TxHeader;
FDCAN_RxHeaderTypeDef RxHeader;
uint8_t TxData[8] = {0};
uint8_t RxData[8];
void FDCAN1_Config(void);
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_FDCAN1_Init();
/* USER CODE BEGIN 2 */
FDCAN1_Config();
// if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
// {
// Error_Handler();
// }
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
TxHeader.Identifier = 0x11111;
TxHeader.IdType = FDCAN_EXTENDED_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
++TxData[7];
if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK) {
Error_Handler();
}
HAL_Delay(1000);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
}
/* USER CODE END 3 */
}
接收的话,主要多了一个“MX_FDCAN1_Init();”的初始化函数,分别是配置接收滤波器、初始化FDCAN,激活中断。
重点介绍一下滤波器的4个参数,FilterType设置为0,即设置了ID1-ID2之间的滤波器,FilterConfig设置为1,如果ID匹配,则存储在FIFO0.
不要管手册里面如何介绍ID2,我这边吧ID1 ID2分别当做滤波器上下限处理的。
sFilterConfig.FilterType = FDCAN_FILTER_RANGE; //
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x04;
sFilterConfig.FilterID2 = 0x06;
/* USER CODE BEGIN 4 */
void FDCAN1_Config(void)
{
FDCAN_FilterTypeDef sFilterConfig;
/* Configure Rx filter */
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x04;
sFilterConfig.FilterID2 = 0x06;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
/* Configure global filter:
Filter all remote frames with STD and EXT ID
Reject non matching frames with STD ID and EXT ID */
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
{
Error_Handler();
}
/* Start the FDCAN module */
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
Error_Handler();
}
}
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
{
Error_Handler();
}
}
/* USER CODE END 4 */
步骤3:can分析仪
参考广成科技提供的操作说明,先安驱动,然后打开后使用自动检测波特率,检测出为500k。
因为发送放在了背景循环,所以一直在接收固定ID的数据。
如果要给stm32发送数据,点下面的“帧格式”为“标准帧”,设置帧ID为ID1-ID2之间的值。数据写好。点发送按钮。
我在debug模式下调试的,把接收变量添加到watch1,数据显示正常。