目的:熟悉MM32 CAN的实现方式,通过loopback模式演示收发是否符合预期。
实验基于以下面例程为模板修改完成:
LibSamples_MM32F5370_V0.10.3\Samples\LibSamples\FlexCAN\FlexCAN_Interrupt
还是以loopback模式进行CAN实验,loopback的好处是自发自收可以方便的验证CAN模块的可用性。
一、CAN引脚的修改
例程中的CAN收发引脚为:PD8(CAN1_RX),PD9(CAN1_TX)
而Mini-F5375-OB原理图上可以看到,开发板上引脚为PI1(CAN1_RX),PI0(CAN1_TX)
复用为FA9
因此FlexCAN_Configure函数中引脚初始化部分改为:
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOI, ENABLE);
GPIO_PinAFConfig(GPIOI, GPIO_PinSource0, GPIO_AF_9);
GPIO_PinAFConfig(GPIOI, GPIO_PinSource1, GPIO_AF_9);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_FLOATING;
GPIO_Init(GPIOI, &GPIO_InitStruct);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOI, &GPIO_InitStruct);
二、loopback模式修改
继续FlexCAN_Configure函数中修改:
FLEXCAN_GetDefaultConfig(&FlexCAN_ConfigStruct);
FlexCAN_ConfigStruct.baudRate = 250000; /* 250kbps */
FlexCAN_ConfigStruct.clkSrc = Enum_Flexcan_ClkSrc1;
FlexCAN_ConfigStruct.enableLoopBack = true;//false;
FlexCAN_ConfigStruct.disableSelfReception = false;//true;
FlexCAN_ConfigStruct.enableIndividMask = false;//tr
使能loopback
三、其他部分说明
1、发送MB定义
例程中定义了3个发送MB:7(发送标准帧)、8(发送扩展帧)、9(发送远程帧)。
FLEXCAN_TxMbConfig(FLEXCAN1, 7, ENABLE);
FLEXCAN_TxMbConfig(FLEXCAN1, 8, ENABLE);
FLEXCAN_TxMbConfig(FLEXCAN1, 9, ENABLE);
FLEXCAN_TransferCreateHandle(FLEXCAN1, &FlexCAN_Handle, FlexCAN_Transfer_Callback, NULL);
2、接收MB定义
接收MB id:
0x111、0x222、0x333、0555对应MB序号:10、11、12、13
FlexCAN_RxMB_ConfigStruct.id = FLEXCAN_ID_STD(0x111);
FlexCAN_RxMB_ConfigStruct.format = Enum_Flexcan_FrameFormatStandard;
FlexCAN_RxMB_ConfigStruct.type = Enum_Flexcan_FrameTypeData;
FLEXCAN_RxMbConfig(FLEXCAN1, 10, &FlexCAN_RxMB_ConfigStruct, ENABLE);
FLEXCAN_SetRxIndividualMask(FLEXCAN1, 10, FLEXCAN_RX_MB_STD_MASK(0xFFF, 0, 0));
FlexCAN_MB10_FrameStruct.length = (uint8_t)(8);
FlexCAN_MB10_FrameStruct.type = (uint8_t)Enum_Flexcan_FrameTypeData;
FlexCAN_MB10_FrameStruct.format = (uint8_t)Enum_Flexcan_FrameFormatStandard;
FlexCAN_MB10_FrameStruct.id = FLEXCAN_ID_STD(0x111);
FlexCAN_MB10_TransferStruct.mbIdx = 10;
FlexCAN_MB10_TransferStruct.frame = &FlexCAN_MB10_FrameStruct;
FLEXCAN_TransferReceiveNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB10_TransferStruct);
/* STD */
FlexCAN_RxMB_ConfigStruct.id = FLEXCAN_ID_STD(0x222);
FlexCAN_RxMB_ConfigStruct.format = Enum_Flexcan_FrameFormatStandard;
FlexCAN_RxMB_ConfigStruct.type = Enum_Flexcan_FrameTypeData;
FLEXCAN_RxMbConfig(FLEXCAN1, 11, &FlexCAN_RxMB_ConfigStruct, ENABLE);
FLEXCAN_SetRxIndividualMask(FLEXCAN1, 11, FLEXCAN_RX_MB_STD_MASK(0xFFF, 0, 0));
FlexCAN_MB11_FrameStruct.length = (uint8_t)(8);
FlexCAN_MB11_FrameStruct.type = (uint8_t)Enum_Flexcan_FrameTypeData;
FlexCAN_MB11_FrameStruct.format = (uint8_t)Enum_Flexcan_FrameFormatStandard;
FlexCAN_MB11_FrameStruct.id = FLEXCAN_ID_STD(0x222);
FlexCAN_MB11_TransferStruct.mbIdx = 11;
FlexCAN_MB11_TransferStruct.frame = &FlexCAN_MB11_FrameStruct;
FLEXCAN_TransferReceiveNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB11_TransferStruct);
/* EXT */
FlexCAN_RxMB_ConfigStruct.id = FLEXCAN_ID_EXT(0x333);
FlexCAN_RxMB_ConfigStruct.format = Enum_Flexcan_FrameFormatExtend;
FlexCAN_RxMB_ConfigStruct.type = Enum_Flexcan_FrameTypeData;
FLEXCAN_RxMbConfig(FLEXCAN1, 12, &FlexCAN_RxMB_ConfigStruct, ENABLE);
FLEXCAN_SetRxIndividualMask(FLEXCAN1, 12, FLEXCAN_RX_MB_EXT_MASK(0xFFF, 0, 1));
FlexCAN_MB12_FrameStruct.length = (uint8_t)(8);
FlexCAN_MB12_FrameStruct.type = (uint8_t)Enum_Flexcan_FrameTypeData;
FlexCAN_MB12_FrameStruct.format = (uint8_t)Enum_Flexcan_FrameFormatExtend;
FlexCAN_MB12_FrameStruct.id = FLEXCAN_ID_EXT(0x333);
FlexCAN_MB12_TransferStruct.mbIdx = 12;
FlexCAN_MB12_TransferStruct.frame = &FlexCAN_MB12_FrameStruct;
FLEXCAN_TransferReceiveNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB12_TransferStruct);
/* RTR */
FlexCAN_RxMB_ConfigStruct.id = FLEXCAN_ID_STD(0x555);
FlexCAN_RxMB_ConfigStruct.format = Enum_Flexcan_FrameFormatStandard;
FlexCAN_RxMB_ConfigStruct.type = Enum_Flexcan_FrameTypeRemote;
FLEXCAN_RxMbConfig(FLEXCAN1, 13, &FlexCAN_RxMB_ConfigStruct, ENABLE);
FLEXCAN_SetRxIndividualMask(FLEXCAN1, 13, FLEXCAN_RX_MB_EXT_MASK(0xFFF, 1, 0));
FlexCAN_MB13_FrameStruct.length = (uint8_t)(8);
FlexCAN_MB13_FrameStruct.type = (uint8_t)Enum_Flexcan_FrameTypeRemote;
FlexCAN_MB13_FrameStruct.format = (uint8_t)Enum_Flexcan_FrameFormatStandard;
FlexCAN_MB13_FrameStruct.id = FLEXCAN_ID_STD(0x555);
FlexCAN_MB13_TransferStruct.mbIdx = 13;
FlexCAN_MB13_TransferStruct.frame = &FlexCAN_MB13_FrameStruct;
FLEXCAN_TransferReceiveNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB13_TransferStruct);
3、标准帧发送报文函数
void FlexCAN_SendStandardFrameMessage(uint32_t ID, uint8_t *Buffer, uint8_t Length)
{
flexcan_frame_t FlexCAN_FrameStruct;
flexcan_mb_transfer_t FlexCAN_MB_TransferStruct;
FlexCAN_FrameStruct.length = (uint8_t)Length;
FlexCAN_FrameStruct.type = (uint8_t)Enum_Flexcan_FrameTypeData;
FlexCAN_FrameStruct.format = (uint8_t)Enum_Flexcan_FrameFormatStandard;
FlexCAN_FrameStruct.id = FLEXCAN_ID_STD(ID);
FlexCAN_FrameStruct.dataByte0 = Buffer[0];
FlexCAN_FrameStruct.dataByte1 = Buffer[1];
FlexCAN_FrameStruct.dataByte2 = Buffer[2];
FlexCAN_FrameStruct.dataByte3 = Buffer[3];
FlexCAN_FrameStruct.dataByte4 = Buffer[4];
FlexCAN_FrameStruct.dataByte5 = Buffer[5];
FlexCAN_FrameStruct.dataByte6 = Buffer[6];
FlexCAN_FrameStruct.dataByte7 = Buffer[7];
FlexCAN_MB_TransferStruct.mbIdx = 7;
FlexCAN_MB_TransferStruct.frame = &FlexCAN_FrameStruct;
FLEXCAN_TransferSendNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB_TransferStruct);
}
4、发送扩展帧报文函数
void FlexCAN_SendExtendFrameMessage(uint32_t ID, uint8_t *Buffer, uint8_t Length)
{
flexcan_frame_t FlexCAN_FrameStruct;
flexcan_mb_transfer_t FlexCAN_MB_TransferStruct;
FlexCAN_FrameStruct.length = (uint8_t)Length;
FlexCAN_FrameStruct.type = (uint8_t)Enum_Flexcan_FrameTypeData;
FlexCAN_FrameStruct.format = (uint8_t)Enum_Flexcan_FrameFormatExtend;
FlexCAN_FrameStruct.id = FLEXCAN_ID_EXT(ID);
FlexCAN_FrameStruct.dataByte0 = Buffer[0];
FlexCAN_FrameStruct.dataByte1 = Buffer[1];
FlexCAN_FrameStruct.dataByte2 = Buffer[2];
FlexCAN_FrameStruct.dataByte3 = Buffer[3];
FlexCAN_FrameStruct.dataByte4 = Buffer[4];
FlexCAN_FrameStruct.dataByte5 = Buffer[5];
FlexCAN_FrameStruct.dataByte6 = Buffer[6];
FlexCAN_FrameStruct.dataByte7 = Buffer[7];
FlexCAN_MB_TransferStruct.mbIdx = 8;
FlexCAN_MB_TransferStruct.frame = &FlexCAN_FrameStruct;
FLEXCAN_TransferSendNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB_TransferStruct);
}
5、发送远程帧报文函数
void FlexCAN_SendRemoteFrameMessage(uint32_t ID, uint8_t *Buffer, uint8_t Length)
{
flexcan_frame_t FlexCAN_FrameStruct;
flexcan_mb_transfer_t FlexCAN_MB_TransferStruct;
FlexCAN_FrameStruct.length = (uint8_t)Length;
FlexCAN_FrameStruct.type = (uint8_t)Enum_Flexcan_FrameTypeRemote;
FlexCAN_FrameStruct.format = (uint8_t)Enum_Flexcan_FrameFormatStandard;
FlexCAN_FrameStruct.id = FLEXCAN_ID_STD(ID);
FlexCAN_FrameStruct.dataByte0 = Buffer[0];
FlexCAN_FrameStruct.dataByte1 = Buffer[1];
FlexCAN_FrameStruct.dataByte2 = Buffer[2];
FlexCAN_FrameStruct.dataByte3 = Buffer[3];
FlexCAN_FrameStruct.dataByte4 = Buffer[4];
FlexCAN_FrameStruct.dataByte5 = Buffer[5];
FlexCAN_FrameStruct.dataByte6 = Buffer[6];
FlexCAN_FrameStruct.dataByte7 = Buffer[7];
FlexCAN_MB_TransferStruct.mbIdx = 9;
FlexCAN_MB_TransferStruct.frame = &FlexCAN_FrameStruct;
FLEXCAN_TransferSendNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB_TransferStruct);
}
6、接收处理
void FlexCAN_RxMB_Handler(void)
{
uint32_t ID = 0;
uint8_t Buffer[8], Length = 0;
int i;
if (FlexCAN_MB10_RxCompleteFlag == 1)
{
FlexCAN_MB10_RxCompleteFlag = 0;
ID = FlexCAN_MB10_FrameStruct.id;
Length = FlexCAN_MB10_FrameStruct.length;
Buffer[0] = FlexCAN_MB10_FrameStruct.dataByte0;
Buffer[1] = FlexCAN_MB10_FrameStruct.dataByte1;
Buffer[2] = FlexCAN_MB10_FrameStruct.dataByte2;
Buffer[3] = FlexCAN_MB10_FrameStruct.dataByte3;
Buffer[4] = FlexCAN_MB10_FrameStruct.dataByte4;
Buffer[5] = FlexCAN_MB10_FrameStruct.dataByte5;
Buffer[6] = FlexCAN_MB10_FrameStruct.dataByte6;
Buffer[7] = FlexCAN_MB10_FrameStruct.dataByte7;
if (FlexCAN_MB10_FrameStruct.format == (uint8_t)Enum_Flexcan_FrameFormatStandard)
{
if (FlexCAN_MB10_FrameStruct.type == (uint8_t)Enum_Flexcan_FrameTypeData)
{
FlexCAN_SendStandardFrameMessage((ID >> FLEXCAN_ID_STD_Pos), Buffer, Length);
}
else
{
FlexCAN_SendRemoteFrameMessage((ID >> FLEXCAN_ID_STD_Pos), Buffer, Length);
}
}
else if (FlexCAN_MB10_FrameStruct.format == (uint8_t)Enum_Flexcan_FrameFormatExtend)
{
FlexCAN_SendExtendFrameMessage((ID >> FLEXCAN_ID_EXT_Pos), Buffer, Length);
}
FLEXCAN_TransferReceiveNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB10_TransferStruct);
}
if (FlexCAN_MB11_RxCompleteFlag == 1)
{
FlexCAN_MB11_RxCompleteFlag = 0;
ID = FlexCAN_MB11_FrameStruct.id;
Length = FlexCAN_MB11_FrameStruct.length;
Buffer[0] = FlexCAN_MB11_FrameStruct.dataByte0;
Buffer[1] = FlexCAN_MB11_FrameStruct.dataByte1;
Buffer[2] = FlexCAN_MB11_FrameStruct.dataByte2;
Buffer[3] = FlexCAN_MB11_FrameStruct.dataByte3;
Buffer[4] = FlexCAN_MB11_FrameStruct.dataByte4;
Buffer[5] = FlexCAN_MB11_FrameStruct.dataByte5;
Buffer[6] = FlexCAN_MB11_FrameStruct.dataByte6;
Buffer[7] = FlexCAN_MB11_FrameStruct.dataByte7;
if (FlexCAN_MB11_FrameStruct.format == (uint8_t)Enum_Flexcan_FrameFormatStandard)
{
if (FlexCAN_MB11_FrameStruct.type == (uint8_t)Enum_Flexcan_FrameTypeData)
{
FlexCAN_SendStandardFrameMessage((ID >> FLEXCAN_ID_STD_Pos), Buffer, Length);
}
else
{
FlexCAN_SendRemoteFrameMessage((ID >> FLEXCAN_ID_STD_Pos), Buffer, Length);
}
}
else if (FlexCAN_MB11_FrameStruct.format == (uint8_t)Enum_Flexcan_FrameFormatExtend)
{
FlexCAN_SendExtendFrameMessage((ID >> FLEXCAN_ID_EXT_Pos), Buffer, Length);
}
FLEXCAN_TransferReceiveNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB11_TransferStruct);
}
if (FlexCAN_MB12_RxCompleteFlag == 1)
{
FlexCAN_MB12_RxCompleteFlag = 0;
ID = FlexCAN_MB12_FrameStruct.id;
Length = FlexCAN_MB12_FrameStruct.length;
Buffer[0] = FlexCAN_MB12_FrameStruct.dataByte0;
Buffer[1] = FlexCAN_MB12_FrameStruct.dataByte1;
Buffer[2] = FlexCAN_MB12_FrameStruct.dataByte2;
Buffer[3] = FlexCAN_MB12_FrameStruct.dataByte3;
Buffer[4] = FlexCAN_MB12_FrameStruct.dataByte4;
Buffer[5] = FlexCAN_MB12_FrameStruct.dataByte5;
Buffer[6] = FlexCAN_MB12_FrameStruct.dataByte6;
Buffer[7] = FlexCAN_MB12_FrameStruct.dataByte7;
if (FlexCAN_MB12_FrameStruct.format == (uint8_t)Enum_Flexcan_FrameFormatStandard)
{
if (FlexCAN_MB12_FrameStruct.type == (uint8_t)Enum_Flexcan_FrameTypeData)
{
FlexCAN_SendStandardFrameMessage((ID >> FLEXCAN_ID_STD_Pos), Buffer, Length);
}
else
{
FlexCAN_SendRemoteFrameMessage((ID >> FLEXCAN_ID_STD_Pos), Buffer, Length);
}
}
else if (FlexCAN_MB12_FrameStruct.format == (uint8_t)Enum_Flexcan_FrameFormatExtend)
{
FlexCAN_SendExtendFrameMessage((ID >> FLEXCAN_ID_EXT_Pos), Buffer, Length);
}
FLEXCAN_TransferReceiveNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB12_TransferStruct);
}
if (FlexCAN_MB13_RxCompleteFlag == 1)
{
FlexCAN_MB13_RxCompleteFlag = 0;
ID = FlexCAN_MB13_FrameStruct.id;
Length = FlexCAN_MB13_FrameStruct.length;
Buffer[0] = FlexCAN_MB13_FrameStruct.dataByte0;
Buffer[1] = FlexCAN_MB13_FrameStruct.dataByte1;
Buffer[2] = FlexCAN_MB13_FrameStruct.dataByte2;
Buffer[3] = FlexCAN_MB13_FrameStruct.dataByte3;
Buffer[4] = FlexCAN_MB13_FrameStruct.dataByte4;
Buffer[5] = FlexCAN_MB13_FrameStruct.dataByte5;
Buffer[6] = FlexCAN_MB13_FrameStruct.dataByte6;
Buffer[7] = FlexCAN_MB13_FrameStruct.dataByte7;
if (FlexCAN_MB13_FrameStruct.format == (uint8_t)Enum_Flexcan_FrameFormatStandard)
{
if (FlexCAN_MB13_FrameStruct.type == (uint8_t)Enum_Flexcan_FrameTypeData)
{
FlexCAN_SendStandardFrameMessage((ID >> FLEXCAN_ID_STD_Pos), Buffer, Length);
}
else
{
FlexCAN_SendRemoteFrameMessage((ID >> FLEXCAN_ID_STD_Pos), Buffer, Length);
}
}
else if (FlexCAN_MB13_FrameStruct.format == (uint8_t)Enum_Flexcan_FrameFormatExtend)
{
FlexCAN_SendExtendFrameMessage((ID >> FLEXCAN_ID_EXT_Pos), Buffer, Length);
}
FLEXCAN_TransferReceiveNonBlocking(FLEXCAN1, &FlexCAN_Handle, &FlexCAN_MB13_TransferStruct);
}
for(i=0;i<8;i++)
{
printf("[%d] 0x%x,",i,Buffer[i]);
}
printf("\r\n");
}
在函数的最后增加了打印收到报文内容的功能。
四、运行
1、向序号为11的MB发送报文
0x222对应11。可以看到MB 11收到报文,符合预期
void FlexCAN_Interrupt_Sample(void)
{
uint8_t Buffer[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
printf("\r\nTest %s", __FUNCTION__);
FlexCAN_Configure();
//FlexCAN_SendStandardFrameMessage(0x214, Buffer, sizeof(Buffer));
while (1)
{
FlexCAN_SendStandardFrameMessage(0x222, Buffer, sizeof(Buffer));
PLATFORM_LED_Toggle(LED1);
PLATFORM_DelayMS(2000);
}
}
2、向非已定义接收MB发送报文
0x888未定义,因此只有TX信息,无接收信息。
void FlexCAN_Interrupt_Sample(void)
{
uint8_t Buffer[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
printf("\r\nTest %s", __FUNCTION__);
FlexCAN_Configure();
//FlexCAN_SendStandardFrameMessage(0x214, Buffer, sizeof(Buffer));
while (1)
{
FlexCAN_SendStandardFrameMessage(0x888, Buffer, sizeof(Buffer));
PLATFORM_LED_Toggle(LED1);
PLATFORM_DelayMS(2000);
}
}