STM32F072系列可以同时使用CAN与USB,利用这个功能可以制作一个简单的USB转CAN。
1、管脚配置
2、时钟配置
3、CAN配置,500Kbps
4、USB配置,这里用的是HID模式
5、下面对USB代码部份进行更改:
usbd_custom_hid_if.c文件中更改HID报文描述,发送与接收长度设置为20
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05,0x8C,
0x09,0x01,
0xA1,0x01,
//the input report
0x09,0x03,
0x15,0x00,
0x26,0x00,0xFF,
0x75,0x08,
0x95,CUSTOM_HID_EPIN_SIZE,
0x81,0x02,
//the output report
0x09,0x04,
0x15,0x00,
0x26,0x00,0xFF,
0x75,0x08,
0x95,CUSTOM_HID_EPOUT_SIZE,
0x91,0x02,
0xC0,
};
usbd_conf.h中更改
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 20
/*---------- -----------*/
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 33
usbd_desc.c中更改VID与PID
#define USBD_VID 0x1234
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
#define USBD_PID_FS 0x5678
#define USBD_PRODUCT_STRING_FS "STM32 Custom Human interface"
#define USBD_CONFIGURATION_STRING_FS "Custom HID Config"
#define USBD_INTERFACE_STRING_FS "Custom HID Interface"
usbd_customhid.h更改端点大小
#define CUSTOM_HID_EPIN_ADDR 0x81U
#define CUSTOM_HID_EPIN_SIZE 20U
#define CUSTOM_HID_EPOUT_ADDR 0x01U
#define CUSTOM_HID_EPOUT_SIZE 20U
#define USB_CUSTOM_HID_CONFIG_DESC_SIZ 41U
#define USB_CUSTOM_HID_DESC_SIZ 9U
#ifndef CUSTOM_HID_HS_BINTERVAL
#define CUSTOM_HID_HS_BINTERVAL 0x05U
#endif /* CUSTOM_HID_HS_BINTERVAL */
#ifndef CUSTOM_HID_FS_BINTERVAL
#define CUSTOM_HID_FS_BINTERVAL 0x05U
#endif /* CUSTOM_HID_FS_BINTERVAL */
#ifndef USBD_CUSTOMHID_OUTREPORT_BUF_SIZE
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 0x40U
#endif /* USBD_CUSTOMHID_OUTREPORT_BUF_SIZE */
#ifndef USBD_CUSTOM_HID_REPORT_DESC_SIZE
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 163U
#endif /* USBD_CUSTOM_HID_REPORT_DESC_SIZE */
6、在main函数中启动CAN
CAN_RxHeaderTypeDef RxHeader = {0};
CAN_FilterTypeDef filter;
uint8_t Rxdata[8] = {0};
uint8_t data[64] = {0};
filter.FilterMode = CAN_FILTERMODE_IDMASK;
filter.FilterScale = CAN_FILTERSCALE_32BIT;
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
filter.FilterActivation = CAN_FILTER_ENABLE;
filter.FilterBank = 0;
filter.SlaveStartFilterBank = 0;
if( HAL_CAN_ConfigFilter( &hcan, &filter ) != HAL_OK )
{
Error_Handler();
}
if (HAL_CAN_Start(&hcan) != HAL_OK)
{
Error_Handler();
}
7、在while中把接收到的CAN数据从USB发送出去
if(HAL_CAN_GetRxFifoFillLevel(&hcan, CAN_RX_FIFO0) >= 1)
{
HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &RxHeader, &Rxdata[0]);
HAL_GPIO_TogglePin(RED_GPIO_Port, RED_Pin);
data[0] = RxHeader.Timestamp;
data[1] = RxHeader.Timestamp >> 8;
data[2] = RxHeader.Timestamp >> 16;
data[3] = RxHeader.Timestamp >> 24;
data[4] = RxHeader.IDE;
data[5] = RxHeader.RTR;
if(RxHeader.IDE == CAN_ID_STD)
{
data[6] = RxHeader.StdId;
data[7] = RxHeader.StdId >> 8;
data[8] = RxHeader.StdId >> 16;
data[9] = RxHeader.StdId >> 24;
}
else
{
data[6] = RxHeader.ExtId;
data[7] = RxHeader.ExtId >> 8;
data[8] = RxHeader.ExtId >> 16;
data[9] = RxHeader.ExtId >> 24;
}
data[10] = RxHeader.DLC;
for(i=0;i<8;i++)
{
data[i + 11] = Rxdata[i];
}
USBD_CUSTOM_HID_SendReport_FS(data, CUSTOM_HID_EPIN_SIZE);
}
8、在usbd_custom_hid_if.c中把USB接收到的数据从CAN发出去
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
/* USER CODE BEGIN 6 */
CAN_TxHeaderTypeDef msg;
uint8_t data[8];
uint8_t i;
uint32_t txMailbox = 0;
USBD_CUSTOM_HID_HandleTypeDef *hhid = (void*)hUsbDeviceFS.pClassData;
HAL_GPIO_TogglePin(YEL_GPIO_Port, YEL_Pin);
if(hhid->Report_buf[4] == CAN_ID_STD)
{
msg.IDE = CAN_ID_STD;
msg.StdId = hhid->Report_buf[6];
msg.StdId += ((uint32_t)hhid->Report_buf[7] << 8);
}
else
{
msg.IDE = CAN_ID_EXT;
msg.ExtId = hhid->Report_buf[6];
msg.ExtId += ((uint32_t)hhid->Report_buf[7] << 8);
msg.ExtId += ((uint32_t)hhid->Report_buf[8] << 8);
msg.ExtId += ((uint32_t)hhid->Report_buf[9] << 8);
}
msg.RTR = CAN_RTR_DATA;
msg.DLC = hhid->Report_buf[10];
for(i=0;i<8;i++)
{
data[i] = hhid->Report_buf[11+i];
}
HAL_CAN_AddTxMessage(&hcan, &msg, data, &txMailbox);
return 0;
/* USER CODE END 6 */
}
/* USER CODE BEGIN 7 */
/**
* @brief Send the report to the Host
* @param report: The report to be sent
* @param len: The report length
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t USBD_CUSTOM_HID_SendReport_FS(uint8_t *report, uint16_t len)
{
return USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, report, len);
}
这里用到的是USB的HID模式,优点就是电脑免驱,插入电脑就可以使用,用HID上位机也可以很方便进行调试。
到此USB转CAN的基本收发功能已经实现,现有的CAN的波特率是固定500K,后期可通过USB协议更改波特率。
下一步实现兼容使用周立功上位机
网盘网盘https://pan.baidu.com/s/1nIK4ig2TW4pdCfUxiYL6VA?pwd=1234