STM32F4之CAN通信CubeMX实现

目录

  • 流程
  • CubeMX配置
    • 常规配置
      • 选择对应的芯片型号
      • 配置debug方式
      • 配置外部高速时钟源
      • 配置时钟树
    • CAN相关配置
      • 配置相关参数
        • 相关参数介绍
  • 代码实现
    • 定义变量接收与发送
    • 初始化过滤器
    • CAN发送函数
    • 接收回调函数

流程

  1. 在cubeMX配置初始化CAN协议相关参数和硬件相关参数:
    设置预分频、位段长度等实现需要的500Kbps波特率;
    CAN时钟使能、GPIO端口时钟使能、引脚重映射、中断优先级等;
  2. 生成代码
  3. 初始化筛选器
  4. 封装CAN发送函数和接收回调函数

CubeMX配置

常规配置

选择对应的芯片型号

STM32F4之CAN通信CubeMX实现_第1张图片

配置debug方式

STM32F4之CAN通信CubeMX实现_第2张图片

配置外部高速时钟源

STM32F4之CAN通信CubeMX实现_第3张图片

配置时钟树

STM32F4之CAN通信CubeMX实现_第4张图片

CAN相关配置

选择对应CAN,勾上Mode里的Activated,启动CAN
STM32F4之CAN通信CubeMX实现_第5张图片

配置相关参数

设置如图即可
STM32F4之CAN通信CubeMX实现_第6张图片
可以全勾上
STM32F4之CAN通信CubeMX实现_第7张图片

相关参数介绍

1. Parameter Settings:
Bit Timing Parameters(位时间参数)

  • Prescaler(for Time Quantum): 分频,可选范围为1-1024。
  • Time Quantum:相当于上图的最小时间单位Tq,单位为ns
  • Time Quanta in Bit Segment 1:PBS1段所占的时间,单位 (Tq)
  • Time Quanta in Bit Segment 2:PBS2段所占的时间,单位(Tq)
  • Time for one Bit:传输一位的时间
  • Baud Rate:波特率
  • ReSynchronization Jump Width:SS段所占的时间,单位(Tq)

Baud Rate(波特率) = APB1 peripheral clocks(时钟树所设置的APB1总线频率) /(Time Quanta in Bit Segment 1 + Time Quanta in Bit Segment 2 + ReSynchronization Jump Width)/ Prescaler(分频值)

Basic Parameters(基本参数,使能or不使能)

  • Time Triggered Communication Mode(时间触发模式)
    在此模式下,CAN使用它内部定时器产生时间戳。内部定时器在每个CAN位时间累加,在接收和改善的帧起始位被采样,并生成时间戳。利用它可以实现标准的分时同步通信功能。
  • Automatic Bus-off Management(自动离线管理)
    当节点检测到它发送错误或接收错误超过一定值时,会自动进入离线状态。在离线状态中,CAN不能接收或发送报文。这时可以软件控制恢复,或者使用自动离线管理功能。使能后,CAN会在适当的时候自动恢复。
  • Automatic Wake-Up Mode(自动唤醒模式)
    使能后,当CAN外设处于低功耗的睡眠模式且检测到总线活动时会自动唤醒。
  • Automatic Retransmission(自动重传)
    使能后,当报文发送失败时会自动重传至成功为止。不使能,则只发送一次。
  • Receive Fifo Locked Mode(接收FIFO锁定模式)
    使能后,当接收FIFO溢出时会丢弃下一个接收报文。不使能,则下一个接收报文会覆盖原报文。
  • Transmit Fifo Priority(发送FIFO优先级)
    使能后,根据报文ID优先级发送。不使能,则根据报文存进邮箱的顺序发送。

Advanced Parameters (高级参数)

  • Operationg Mode
    Normal(正常模式):可向总线发送或接收数据。
    Loopback(回环模式):把数据发送给总线和自己,不能从总线接收数据。
    Silent(静默模式):只可向总线发送数据1和接收数据,不能发送数据0。
    Loopback combined with Silent(回环静默模式):把数据发送给自己,不能从总线接收也不能发送给总线数据。

2. NVIC Settings:

  • CAN1 TX interrupts:发送中断(需使能)
  • CAN1 RX0 interrupts:FIFO0接收中断
  • CAN1 RX1 interrupt:FIFO1接收中断
  • CAN1 SCE interrupt:故障监测中断

3. User Constants:设置常量
4. GPIO Settings:引脚配置(不可修改)

最后设置工程名生成即可

代码实现

定义变量接收与发送

CAN_TxHeaderTypeDef Tx1Message;/*can1发送帧相关信息*/
CAN_RxHeaderTypeDef Rx1Message;/*can1接收帧相关信息*/
uint8_t CAN1_Rx_data[8];/*can1发送帧数据*/
uint8_t CAN1_Tx_data[8];/*can1接收帧数据*/

初始化过滤器

void can_device_init(void)
{
	CAN_FilterTypeDef  can_filter;/*过滤器设置*/

	can_filter.FilterBank           = 0;
	/*使用的过滤器编号。使用一个CAN,则可选0~13;使用两个CAN可选0~27*/
	can_filter.FilterMode           = CAN_FILTERMODE_IDMASK;
	/*过滤器模式选择。掩码模式填写CAN_FILTERMODE_IDMASK,
					  列表模式填写CAN_FILTERMODE_IDLIST */
	can_filter.FilterScale          = CAN_FILTERSCALE_32BIT;
	/*过滤器位宽,32位是CAN_FILTERSCALE_32BIT,
                  16位是CAN_FILTERSCALE_16BIT */
	can_filter.FilterIdHigh         = 0x0000;
	/*过滤器验证码ID高16位,参数值:0~0xFFFF*/
	can_filter.FilterIdLow          = 0x0000;
	/*过滤器验证码ID低16位,参数值:0~0xFFFF*/
	can_filter.FilterMaskIdHigh     = 0x0000;
	/*过滤器掩码ID高16位,参数值:0~0xFFFF*/
	can_filter.FilterMaskIdLow      = 0x0000;
	/*过滤器掩码ID低16位,参数值:0~0xFFFF*/
	can_filter.FilterFIFOAssignment = CAN_FilterFIFO0;
	/*将通过的报文放入哪个FIFOx中,填写FIFO(x)*/
	can_filter.SlaveStartFilterBank = 0;
	/*can2开始的过滤器*/
	can_filter.FilterActivation     = ENABLE;
	/*是否使能过滤器,DISABLE 或 ENABLE */

	HAL_CAN_ConfigFilter(&hcan1, &can_filter);
	while (HAL_CAN_ConfigFilter(&hcan1, &can_filter) != HAL_OK);
	/*配置can1过滤器并等待至配置完成*/
	
	can_filter.FilterBank           = 14;
	HAL_CAN_ConfigFilter(&hcan2, &can_filter);  
	while (HAL_CAN_ConfigFilter(&hcan2, &can_filter) != HAL_OK);
	/*配置can2过滤器并等待至配置完成*/
	
	HAL_Delay(100);
	HAL_CAN_Start(&hcan1);
	HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
	/*开启can1并使能中断*/
	HAL_CAN_Start(&hcan2);
	HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO0_MSG_PENDING);
	/*开启can2并使能中断*/
}

CAN发送函数

void can1_send_message(int16_t TX_ID, int16_t iq1, int16_t iq2, int16_t iq3, int16_t iq4)
{
	uint8_t FreeTxNum = 0;
	
	Tx2Message.StdId = TX_ID;
	/*标准ID。参数值:0到0x7FF*/
	Tx2Message.ExtId = 0;
	/*扩展ID。参数值:0到0x1FFFFFFF*/
	Tx2Message.IDE 	 = CAN_ID_STD;
	/*标准帧填写CAN_ID_STD,扩展帧填写CAN_ID_EXT */
	Tx2Message.RTR   = CAN_RTR_DATA;
	/*数据帧填写CAN_RTR_DATA,遥控帧填写CAN_RTR_REMOTE */
	Tx2Message.DLC   = 0x08;
	/*数据长度,参数值:0到8*/
	
	CAN1_Tx_data[0] = iq1 >> 8;
	CAN1_Tx_data[1] = iq1;
	CAN1_Tx_data[2] = iq2 >> 8 ;
	CAN1_Tx_data[3] = iq2;
	CAN1_Tx_data[4] = iq3 >> 8;
	CAN1_Tx_data[5] = iq3;
	CAN1_Tx_data[6] = iq4 >> 8;
	CAN1_Tx_data[7] = iq4;
	
	FreeTxNum = HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);  
	while(FreeTxNum == 0)FreeTxNum = HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);  
	/*等待发送邮箱有空*/
	
	HAL_CAN_AddTxMessage(&hcan1, &Tx1Message,CAN1_Tx_data,(uint32_t*)CAN_TX_MAILBOX0);
	/*将数据放入邮箱*/
}

接收回调函数

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan == &hcan1)
	{
		//将fifo0接收到的id等信息赋给Rx1Message,数据赋给CAN1_Rx_data
		HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&Rx1Message,CAN1_Rx_data);
		//根据ID进行不同的操作,也在中断外进行操作
		switch (Rx1Message.StdId)
		{
			
		};
		__HAL_CAN_ENABLE_IT(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
	}
	else if(hcan == &hcan2 )
	{
		HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&Rx2Message, CAN2_Rx_data);
		switch (Rx2Message.StdId)
		{
			
		}
		__HAL_CAN_ENABLE_IT(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);
	}
}

最终接收的数据将通过中断存入CAN1_Rx_data,发送数据则通过can1_send_message函数发送。

你可能感兴趣的:(stm32,单片机,arm)