赞
踩
自制STM32F407VGT6控制板
串口调试助手X-COM
泥人CAN转USB及其配套上位机软件
本文所需要实现的目标是,通过泥人CAN转USB,以上位机为主机,向STM32发送相关指令,32控制板在接收到CAN信息后将所接收数据通过串口打印至上位机的串口调试软件。
相比于上一篇内部回传的CAN配置,本次需要更改部分参数,将Operating Mode改为Normal。同时别忘了打开接收中断。
这里偷个懒,直接将实际使用的程序拿来用了,发送函数和接收中断函数等可以直接借鉴使用哈,屎山代码勿喷。
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file can.h * @brief This file contains all the function prototypes for * the can.c file ****************************************************************************** * @attention * * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __CAN_H__ #define __CAN_H__ #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "main.h" /* USER CODE BEGIN Includes */ extern int32_t X_tar; extern int now_station; extern int run_in_can; extern uint16_t test_time; extern int32_t encoder1; extern int32_t encoder2; /* USER CODE END Includes */ extern CAN_HandleTypeDef hcan1; extern CAN_HandleTypeDef hcan2; /* USER CODE BEGIN Private defines */ #define CAN1_FILTER_BANK 0 ///< CAN1过滤器组编号 #define CAN2_FILTER_BANK 14 ///< CAN2过滤器组编号 /* USER CODE END Private defines */ void MX_CAN1_Init(void); void MX_CAN2_Init(void); /* USER CODE BEGIN Prototypes */ void CAN_Start_Init(void); void CAN1Filter_Config(void); void CAN1Filter_Config(void); void CAN1_Send_Test(void); void CAN1_Send(uint8_t* cdata); void CAN2Filter_Config(void); void CAN2Filter_Config(void); void CAN2_Send_Test(void); void CAN2_Send(uint8_t* cdata); void GET_encoder1(void); void GET_encoder2(void); /* USER CODE END Prototypes */ #ifdef __cplusplus } #endif #endif /* __CAN_H__ */
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file can.c * @brief This file provides code for the configuration * of the CAN instances. ****************************************************************************** * @attention * * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "can.h" /* USER CODE BEGIN 0 */ #include <stdio.h> #include "user.h" #include "usart.h" #include "gpio.h" static CAN_TxHeaderTypeDef TxMessage; //CAN发送的消息的消息头 static CAN_RxHeaderTypeDef RxMessage; //CAN接收的消息的消息头 /* USER CODE END 0 */ CAN_HandleTypeDef hcan1; CAN_HandleTypeDef hcan2; /* CAN1 init function */ void MX_CAN1_Init(void) { /* USER CODE BEGIN CAN1_Init 0 */ /* USER CODE END CAN1_Init 0 */ /* USER CODE BEGIN CAN1_Init 1 */ /* USER CODE END CAN1_Init 1 */ hcan1.Instance = CAN1; hcan1.Init.Prescaler = 7; hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan1.Init.TimeSeg1 = CAN_BS1_4TQ; hcan1.Init.TimeSeg2 = CAN_BS2_7TQ; hcan1.Init.TimeTriggeredMode = DISABLE; hcan1.Init.AutoBusOff = DISABLE; hcan1.Init.AutoWakeUp = DISABLE; hcan1.Init.AutoRetransmission = DISABLE; hcan1.Init.ReceiveFifoLocked = DISABLE; hcan1.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN CAN1_Init 2 */ /* USER CODE END CAN1_Init 2 */ } /* CAN2 init function */ void MX_CAN2_Init(void) { /* USER CODE BEGIN CAN2_Init 0 */ /* USER CODE END CAN2_Init 0 */ /* USER CODE BEGIN CAN2_Init 1 */ /* USER CODE END CAN2_Init 1 */ hcan2.Instance = CAN2; hcan2.Init.Prescaler = 7; hcan2.Init.Mode = CAN_MODE_NORMAL; hcan2.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan2.Init.TimeSeg1 = CAN_BS1_4TQ; hcan2.Init.TimeSeg2 = CAN_BS2_1TQ; hcan2.Init.TimeTriggeredMode = DISABLE; hcan2.Init.AutoBusOff = DISABLE; hcan2.Init.AutoWakeUp = DISABLE; hcan2.Init.AutoRetransmission = DISABLE; hcan2.Init.ReceiveFifoLocked = DISABLE; hcan2.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN CAN2_Init 2 */ /* USER CODE END CAN2_Init 2 */ } static uint32_t HAL_RCC_CAN1_CLK_ENABLED=0; void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(canHandle->Instance==CAN1) { /* USER CODE BEGIN CAN1_MspInit 0 */ /* USER CODE END CAN1_MspInit 0 */ /* CAN1 clock enable */ HAL_RCC_CAN1_CLK_ENABLED++; if(HAL_RCC_CAN1_CLK_ENABLED==1){ __HAL_RCC_CAN1_CLK_ENABLE(); } __HAL_RCC_GPIOB_CLK_ENABLE(); /**CAN1 GPIO Configuration PB8 ------> CAN1_RX PB9 ------> CAN1_TX */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; 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(GPIOB, &GPIO_InitStruct); /* CAN1 interrupt Init */ HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn); /* USER CODE BEGIN CAN1_MspInit 1 */ /* USER CODE END CAN1_MspInit 1 */ } else if(canHandle->Instance==CAN2) { /* USER CODE BEGIN CAN2_MspInit 0 */ /* USER CODE END CAN2_MspInit 0 */ /* CAN2 clock enable */ __HAL_RCC_CAN2_CLK_ENABLE(); HAL_RCC_CAN1_CLK_ENABLED++; if(HAL_RCC_CAN1_CLK_ENABLED==1){ __HAL_RCC_CAN1_CLK_ENABLE(); } __HAL_RCC_GPIOB_CLK_ENABLE(); /**CAN2 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); /* CAN2 interrupt Init */ HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn); /* USER CODE BEGIN CAN2_MspInit 1 */ /* USER CODE END CAN2_MspInit 1 */ } } void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle) { if(canHandle->Instance==CAN1) { /* USER CODE BEGIN CAN1_MspDeInit 0 */ /* USER CODE END CAN1_MspDeInit 0 */ /* Peripheral clock disable */ HAL_RCC_CAN1_CLK_ENABLED--; if(HAL_RCC_CAN1_CLK_ENABLED==0){ __HAL_RCC_CAN1_CLK_DISABLE(); } /**CAN1 GPIO Configuration PB8 ------> CAN1_RX PB9 ------> CAN1_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9); /* CAN1 interrupt Deinit */ HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn); /* USER CODE BEGIN CAN1_MspDeInit 1 */ /* USER CODE END CAN1_MspDeInit 1 */ } else if(canHandle->Instance==CAN2) { /* USER CODE BEGIN CAN2_MspDeInit 0 */ /* USER CODE END CAN2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_CAN2_CLK_DISABLE(); HAL_RCC_CAN1_CLK_ENABLED--; if(HAL_RCC_CAN1_CLK_ENABLED==0){ __HAL_RCC_CAN1_CLK_DISABLE(); } /**CAN2 GPIO Configuration PB12 ------> CAN2_RX PB13 ------> CAN2_TX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12|GPIO_PIN_13); /* CAN2 interrupt Deinit */ HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn); /* USER CODE BEGIN CAN2_MspDeInit 1 */ /* USER CODE END CAN2_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /******************* 接受信息过滤器 *******************/ void CAN1Filter_Config(void) { CAN_FilterTypeDef sFilterConfig; sFilterConfig.FilterBank = CAN1_FILTER_BANK; //CAN过滤器编号,范围0-27 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; //CAN过滤器模式,掩码模式或列表模式 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //CAN过滤器尺度,16位或32位 sFilterConfig.FilterIdHigh = 0x000 << 5; //32位下,存储要过滤ID的高16位 sFilterConfig.FilterIdLow = 0x0000; //32位下,存储要过滤ID的低16位 sFilterConfig.FilterMaskIdHigh = 0x0000; //掩码模式下,存储的是掩码 sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterFIFOAssignment = 0; //报文通过过滤器的匹配后,存储到哪个FIFO sFilterConfig.FilterActivation = ENABLE; //激活过滤器 sFilterConfig.SlaveStartFilterBank = CAN2_FILTER_BANK; if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) { Error_Handler(); } else{ printf("HAL_CAN_ConfigFilter1 is HAL_OK\r\n"); } } void CAN2Filter_Config(void) { CAN_FilterTypeDef sFilterConfig; sFilterConfig.FilterBank = CAN2_FILTER_BANK; //CAN过滤器编号,范围0-27 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; //CAN过滤器模式,掩码模式或列表模式 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //CAN过滤器尺度,16位或32位 sFilterConfig.FilterIdHigh = 0x000 << 5; //32位下,存储要过滤ID的高16位 sFilterConfig.FilterIdLow = 0x0000; //32位下,存储要过滤ID的低16位 sFilterConfig.FilterMaskIdHigh = 0x0000; //掩码模式下,存储的是掩码 sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterFIFOAssignment = 0; //报文通过过滤器的匹配后,存储到哪个FIFO sFilterConfig.FilterActivation = ENABLE; //激活过滤器 sFilterConfig.SlaveStartFilterBank = 0; if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK) { Error_Handler(); } else{ printf("HAL_CAN_ConfigFilter2 is HAL_OK\r\n"); } } /******************* 发送函数 *******************/ void GET_encoder1(void) { uint32_t TxMailbox; uint8_t data[4] = {0x04,0x01,0x01,0x00}; TxMessage.IDE = CAN_ID_STD; //设置ID类型 TxMessage.StdId = 0x01; //设置ID号 TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧 TxMessage.DLC = 4; //设置数据长度 if (HAL_CAN_AddTxMessage(&hcan1, &TxMessage, data, &TxMailbox) != HAL_OK) { Error_Handler(); } } void GET_encoder2(void) { uint32_t TxMailbox; uint8_t data[4] = {0x04,0x02,0x01,0x00}; TxMessage.IDE = CAN_ID_STD; //设置ID类型 TxMessage.StdId = 0x01; //设置ID号 TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧 TxMessage.DLC = 4; //设置数据长度 if (HAL_CAN_AddTxMessage(&hcan1, &TxMessage, data, &TxMailbox) != HAL_OK) { Error_Handler(); } } void CAN1_Send_Test(void) { uint32_t TxMailbox; uint8_t data[4] = {0x04,0x01,0x01,0x00}; TxMessage.IDE = CAN_ID_STD; //设置ID类型 TxMessage.StdId = 0x01; //设置ID号 TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧 TxMessage.DLC = 4; //设置数据长度 if (HAL_CAN_AddTxMessage(&hcan1, &TxMessage, data, &TxMailbox) != HAL_OK) { Error_Handler(); } else{ printf("HAL_CAN_AddTxMessage1 is HAL_OK\r\n"); } } void CAN1_Send(uint8_t* cdata) { uint32_t TxMailbox; TxMessage.IDE = CAN_ID_STD; //设置ID类型 TxMessage.StdId = 0x122; //设置ID号 TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧 TxMessage.DLC = 8; //设置数据长度 if (HAL_CAN_AddTxMessage(&hcan1, &TxMessage, cdata, &TxMailbox) != HAL_OK) { Error_Handler(); } } void CAN2_Send_Test(void) { uint32_t TxMailbox; uint8_t data[4] = {0x04,0x01,0x01,0x00}; TxMessage.IDE = CAN_ID_STD; //设置ID类型 TxMessage.StdId = 0x01; //设置ID号 TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧 TxMessage.DLC = 4; //设置数据长度 if (HAL_CAN_AddTxMessage(&hcan2, &TxMessage, data, &TxMailbox) != HAL_OK) { Error_Handler(); } else{ printf("HAL_CAN_AddTxMessage2 is HAL_OK\r\n"); } } void CAN2_Send(uint8_t* cdata) { uint32_t TxMailbox; TxMessage.IDE = CAN_ID_STD; //设置ID类型 TxMessage.StdId = 0x111; //设置ID号 TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧 TxMessage.DLC = 8; //设置数据长度 if (HAL_CAN_AddTxMessage(&hcan2, &TxMessage, cdata, &TxMailbox) != HAL_OK) { Error_Handler(); } } /******************* CAN启动函数 *******************/ void CAN_Start_Init(void) { if (HAL_CAN_Start(&hcan1) != HAL_OK) { Error_Handler(); } else{ printf("HAL_CAN1_Star1 is HAL_OK\r\n"); } if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) { Error_Handler(); } else{ printf("HAL_CAN1_ActivateNotification is HAL_OK\r\n"); } if (HAL_CAN_Start(&hcan2) != HAL_OK) { Error_Handler(); } else{ printf("HAL_CAN2_Start is HAL_OK\r\n"); } if (HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) { Error_Handler(); } else{ printf("HAL_CAN2_ActivateNotification is HAL_OK\r\n"); } } /******************* 中断接受 *******************/ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { uint8_t data[8]; HAL_StatusTypeDef status; status = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, data); // if (HAL_OK == status) // { // printf("--->Data Receieve!\r\n"); // printf("RxMessage.StdId is %#x\r\n", RxMessage.StdId); // printf("data[0] is 0x%02x\r\n", data[0]); // printf("data[1] is 0x%02x\r\n", data[1]); // printf("data[2] is 0x%02x\r\n", data[2]); // printf("data[3] is 0x%02x\r\n", data[3]); // printf("data[4] is 0x%02x\r\n", data[4]); // printf("data[5] is 0x%02x\r\n", data[5]); // printf("data[6] is 0x%02x\r\n", data[6]); // printf("data[7] is 0x%02x\r\n", data[7]); // printf("<---\r\n"); // } if (hcan->Instance == hcan1.Instance)//数据来自编码器 { //来自编码器1的回信 if (data[1] == 0x01) { if (data[0] == 0x07 && data[2] == 0x01) //此时为查询当前位置的返回值 { encoder1 = data[3] + data[4]*256 + data[5]*65536; printf("编码器1的当前位置为:%d \r\n",encoder1); } else //此时为其他命令的返回数据 { switch (data[2]) { case 0x02: //此时为返回新设置的编码器ID break; case 0x03: //此时为返回新设置的波特率 break; case 0x04: //此时为返回新设置的编码器运行模式 break; case 0x05: //此时为返回新设置的编码器自动回传时间 break; case 0x06: //当前位置设为零点 break; case 0x07: //此时为返回新设置的编码器旋转方向 break; case 0x0A: //此时为返回角速度值 break; case 0x0B: //此时为返回新设置的编码器角速度采样值 break; case 0x0C: //此时为返回新设置的编码器当前圈数 break; case 0x0D: //此时为返回新设置的编码器当前位置值 break; case 0x0F: //此时为返回新设置的编码器当前圈数值 break; default: break; } } } //来自编码器2的回信 else if (data[1] == 0x02) { if (data[0] == 0x07 && data[2] == 0x01) //此时为查询当前位置的返回值 { encoder2 = data[3] + data[4]*256 + data[5]*65536; printf("编码器2的当前位置为:%d \r\n",encoder2); } else //此时为其他命令的返回数据 { switch (data[2]) { case 0x02: //此时为返回新设置的编码器ID break; case 0x03: //此时为返回新设置的波特率 break; case 0x04: //此时为返回新设置的编码器运行模式 break; case 0x05: //此时为返回新设置的编码器自动回传时间 break; case 0x06: //当前位置设为零点 break; case 0x07: //此时为返回新设置的编码器旋转方向 break; case 0x0A: //此时为返回角速度值 break; case 0x0B: //此时为返回新设置的编码器角速度采样值 break; case 0x0C: //此时为返回新设置的编码器当前圈数 break; case 0x0D: //此时为返回新设置的编码器当前位置值 break; case 0x0F: //此时为返回新设置的编码器当前圈数值 break; default: break; } } } } else if (hcan->Instance == hcan2.Instance)//数据来自上位机 { if (HAL_OK == status) { if (data[0] == 0xba && data[7] == 0xab) { switch (data[2]) { case 0x01://数据来自上位机,得到目标位置值 if (run_in_can == 1) { X_tar = data[3]*128*128*128 + data[4]*128*128 + data[5]*128 + data[6]; printf("目标位置为:%d mm\r\n",X_tar); now_station = 3 ; } break; case 0x02://数据来自上位机,控制输出端口 GPIO_OUT_contral(data[5] , data[6]); break; case 0x03://数据来自上位机,选择CAN作为控制器 now_station = 2 ; printf("已选取CAN上位机为控制器\r\n"); break; case 0x04://数据来自上位机,停止信号 now_station = 0 ; printf("停止信号发起\r\n"); break; case 0x05://数据来自上位机,进行电机正反转测试 if (run_in_can == 1) { now_station = 5 ; printf("进行电机正反转测试\r\n"); } break; default: break; } } } } } /* USER CODE END 1 */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。