- void CAN_Mode_Init( u8 tsjw, u8 tbs2, u8 tbs1, u16 brp, u8 mode )
- {
- GPIO_InitTypeDef GPIO_InitSturcture={0};
- CAN_InitTypeDef CAN_InitSturcture={0};
- CAN_FilterInitTypeDef CAN_FilterInitSturcture={0};
-
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE );
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_CAN1, ENABLE );
-
- GPIO_PinRemapConfig( GPIO_Remap1_CAN1, ENABLE);
-
- GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init( GPIOB, &GPIO_InitSturcture);
-
- GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_8;
- GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_Init( GPIOB, &GPIO_InitSturcture);
-
- CAN_InitSturcture.CAN_TTCM = DISABLE;
- CAN_InitSturcture.CAN_ABOM = DISABLE;
- CAN_InitSturcture.CAN_AWUM = DISABLE;
- CAN_InitSturcture.CAN_NART = ENABLE;
- CAN_InitSturcture.CAN_RFLM = DISABLE;
- CAN_InitSturcture.CAN_TXFP = DISABLE;
- CAN_InitSturcture.CAN_Mode = mode;
- CAN_InitSturcture.CAN_SJW = tsjw;
- CAN_InitSturcture.CAN_BS1 = tbs1;
- CAN_InitSturcture.CAN_BS2 = tbs2;
- CAN_InitSturcture.CAN_Prescaler = brp;
- CAN_Init( CAN1, &CAN_InitSturcture );
-
- CAN_FilterInitSturcture.CAN_FilterNumber = 0;
-
- #if (Frame_Format == Standard_Frame)
- /* identifier/mask mode, One 32-bit filter, StdId: 0x317 */
- CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask;
- CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit;
- CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x62E0;
- CAN_FilterInitSturcture.CAN_FilterIdLow = 0;
- CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0xFFE0;
- CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0x0006;
2、配置过滤
- /*********************************************************************
- * @fn CAN_SoftFilterInit
- *
- * [url=home.php?mod=space&uid=247401]@brief[/url] Initializes the CAN peripheral according to the specified
- * parameters in the CAN_FilterInitStruct.
- *
- * @param CAN_FilterInitStruct - pointer to a CAN_FilterInitTypeDef
- * structure that contains the configuration information.
- *
- * [url=home.php?mod=space&uid=266161]@return[/url] none
- */
- void CAN_SoftFilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct)
- {
- if(CAN_FilterInitStruct->CAN_FilterNumber > CANSOFTFILTER_MAX_GROUP_NUM){
- return;
- }
- if(CAN_FilterInitStruct->CAN_FilterActivation)
- {
- CANFilterStruct[CAN_FilterInitStruct->CAN_FilterNumber].en = 1;
- }else
- {
- CANFilterStruct[CAN_FilterInitStruct->CAN_FilterNumber].en = 0;
- }
- CANFilterStruct[CAN_FilterInitStruct->CAN_FilterNumber].FR[0].FR_16_H = CAN_FilterInitStruct->CAN_FilterIdHigh;
- CANFilterStruct[CAN_FilterInitStruct->CAN_FilterNumber].FR[0].FR_16_L = CAN_FilterInitStruct->CAN_FilterIdLow;
- CANFilterStruct[CAN_FilterInitStruct->CAN_FilterNumber].FR[1].FR_16_H = CAN_FilterInitStruct->CAN_FilterMaskIdHigh;
- CANFilterStruct[CAN_FilterInitStruct->CAN_FilterNumber].FR[1].FR_16_L = CAN_FilterInitStruct->CAN_FilterMaskIdLow;
- CANFilterStruct[CAN_FilterInitStruct->CAN_FilterNumber].mode = CAN_FilterInitStruct->CAN_FilterMode;
- CANFilterStruct[CAN_FilterInitStruct->CAN_FilterNumber].scale = CAN_FilterInitStruct->CAN_FilterScale;
- }
3、配置接收中断
- void USB_LP_CAN1_RX0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- void USB_LP_CAN1_RX0_IRQHandler()
- {
- int i;
- uint8_t px,pbuf[8];
- if (CAN_GetITStatus(CAN1,CAN_IT_FMP0))
- {
- px = CAN_Receive_Msg(pbuf);
- for ( i = 0; i < px; i++)
- {
- canexbuf_interrupt[i] = pbuf[i];
- }
- if(px)
- {
- interrupt_rx_flag = 1;
- }
- CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
- }
- }
4、配置发送和接收函数
- /*********************************************************************
- * @fn CAN_Send_Msg
- *
- * @brief CAN Transmit function.
- *
- * @param msg - Transmit data buffer.
- * len - Data length.
- *
- * @return 0 - Send successful.
- * 1 - Send failed.
- */
- u8 CAN_Send_Msg( u8 *msg, u8 len )
- {
- u8 mbox;
- u16 i = 0;
-
- CanTxMsg CanTxStructure;
-
- #if (Frame_Format == Standard_Frame)
- CanTxStructure.StdId = 0x317;
- CanTxStructure.IDE = CAN_Id_Standard;
-
- #elif (Frame_Format == Extended_Frame)
- CanTxStructure.ExtId = 0x12124567;
- CanTxStructure.IDE = CAN_Id_Extended;
-
- #endif
-
- CanTxStructure.RTR = CAN_RTR_Data;
- CanTxStructure.DLC = len;
-
- for( i=0; i<len; i++ )
- {
- CanTxStructure.Data[i] = msg[i];
- }
-
- mbox = CAN_Transmit( CAN1, &CanTxStructure);
- i = 0;
-
- while( ( CAN_TransmitStatus( CAN1, mbox ) != CAN_TxStatus_Ok ) && (i < 0xFFF) )
- {
- i++;
- }
-
- if( i == 0xFFF )
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- /*********************************************************************
- * @fn CAN_Receive_Msg
- *
- * @brief CAN Receive function.
- *
- * @param buf - Receive data buffer.
- * len - Data length.
- *
- * @return CanRxStructure.DLC - Receive data length.
- */
- u8 CAN_Receive_Msg( u8 *buf )
- {
- u8 i;
-
- CanRxMsg CanRxStructure;
-
- if( CAN_MessagePending( CAN1, CAN_FIFO0 ) == 0)
- {
- return 0;
- }
-
- #ifdef USE_SOFT_FILTER
- CAN_ReceiveViaSoftFilter( CAN1, CAN_FIFO0, &CanRxStructure );
- #else
- CAN_Receive( CAN1, CAN_FIFO0, &CanRxStructure );
- #endif // USE_SOFT_FILTER
-
- for( i=0; i<8; i++ )
- {
- buf[i] = CanRxStructure.Data[i];
- }
-
- return CanRxStructure.DLC;
- }
5、下载验证
1)发送数据
250K波特率
1M波特率接收
统计发送成功的次数,按1M的波特率去发送,没有出错;发送58055次数据。
2)接收数据
使用USB-CAN软件向开发板发送数据,如图,设备成功接收到
总结:根据测试和数据手册说明,CH32V307VCY6的can最大速率为1M,且稳定性是很不错的,具体还需要根据现场实际情况进行测试。