STM32CubeMX 配置CAN通信 HAL库

一、CAN总线波特率计算

CAN总线通信的各节点通信时会产生相位差,所以要进行位同步,两个节点保持步调一致。
CAN_SJW:重新同步跳跃宽度(SJW) 。定义了在每位中可以延长或缩短多少个时间单元的上限。其值可以编程为1到4个时间单元。
CAN_BS1:时间段1(BS1):定义采样点的位置。其值可以编程为1到16个时间单元,但也可以被自动延长,以补偿因为网络中不同节点的频率差异所造成的相位的正向漂移。
CAN_BS2:时间段2(BS2):定义发送点的位置。其值可以编程为1到8个时间单元,但也可以被自动缩短以补偿相位的负向漂移。
CAN_Prescaler:直观理解就是分频率。


CAN总线的波特率是取自于总线APB1(PCLK1),通过函数RCC_PCLK1Config给PCLK1配置频率。设置了以上的四个值之后,
CAN总线的波特率=PCLK1/((CAN_SJW +CAN_BS1 + CAN_BS2)*CAN_Prescaler)
假设PCLK1=36MHz、CAN_SJW=1、CAN_BS1=8、CAN_BS2=7、CAN_Prescaler=9
则CAN总线的波特率=PCLK1/((1 + 8 + 7) * 9) = 36MHz / 16 / 9 = 250Kbits

二、查看数据手册(stm32F407ZG),看CAN挂载在哪条总线上面,以及对应的引脚 

三、CAN过滤器介绍

typedef struct
{
  __IO uint32_t FR1;           //标识符屏蔽位模式中标识符寄存器,配置ID
  __IO uint32_t FR2;           //标识符屏蔽位模式中屏蔽寄存器
}CAN_FilterRegister_TypeDef;  //标识符列表模式中为2个标识符寄存器,配置ID

例如:屏蔽位寄存器的bit15=1,标识符寄存器的bit15=0,那么接受的Message里面的标识符的bit15必须为0才可能被硬件接受。如果屏蔽位寄存器的bit15=0,Message里面的标识符的bit15无论为什么值,bit15都能匹配通过。

32位屏蔽位模式下:1个过滤器。FR2指定需要关心哪些位,FR1指定这些位的标准值
32位列表模式下:2个过滤器,FR1指定过滤器0的标准值,FR2指定过滤器1的标准值
16位屏蔽位模式下:2个过滤器。FR1高位配置过滤器0标准值,低位配置给过滤器1的标准值。FR2高位配置过滤器0关心的位,低位配置给过滤器1的关心的位。
16位列表模式下:4个过滤器。FR1低位配置过滤器0,高位配置过滤器1。FR2配置过滤器2和过滤器3

IDE=0为标准ID,IDE=1为扩展ID。
RTR=0代表数据帧,RTR=1代表远程帧。
MASKID设置屏蔽码,ID设置标准值。

四、STM32CubeMX配置CAN通信

(1)通过配置分频值和三个时间的比例,可以得出CAN的波特率

(2)针对CAN基本参数设置,具体含义如下

在这里插入图片描述

这些是配置基本参数用的:

  1. 时间触发模式:会自动为报文生成时间戳,没有研究过,暂时默认关闭。
  2. 自动总线关闭管理:没有研究过,暂时默认关闭。
  3. 自动唤醒模式:使能后,当CAN外设在休眠状态时如果CAN总线有数据,则自动唤醒CAN外设。
  4. 自动重发:使能后,如果因为仲裁失败(总线冲突)或是其他原因导致发送失败,会自动重发。建议使能。
  5. 接收FIFO锁定模式:如果使能,当接收FIFO满时,下一条数据会被丢失。如果不使能,则覆盖前面的数据。
  6. 发送FIFO优先级:当发送邮箱中同时有多个帧,是按照先进先出的顺序发送还是按照ID的优先级发送。如果不使能,则按照ID优先级发送。如果使能,则按照先进先出优先级发送。

使能CAN接收中断

(3)CAN几种模式

Advanced Parameters

在这里插入图片描述

这一项主要是用来调试用的,如果只是正常使用,选择 Normal 模式。

  1. 正常模式:CAN外设正常地向CAN总线发送数据并从CAN总线上接收数据。
  2. 回环模式:CAN外设正常向CAN总线发送数据,同时接收自己发送的数据,但不从CAN总线上接收数据。
  3. 静默模式:CAN外设不向CAN总线发送数据,仅从CAN总线上接收数据,但不会应答。一般用于检测CAN总线的流量。
  4. 静默回环模式:CAN外设不会往CAN总线收发数据,仅给自己发送。一般用于自检。

五、使能CAN通信

HAL_CAN_Start(&hcan1);

六、发送数据

写法一:测试时直接发送

CAN_TxHeaderTypeDef can_Tx;
uint8_t sendBuf[5] = {"hello"};
uint32_t box;

int main(void)
{
  	HAL_Init();
 	SystemClock_Config();
  	MX_GPIO_Init();
  	MX_CAN_Init();

    HAL_CAN_Start(&hcan1);//使能CAN通信
  
    can_Tx.StdId = 0x123;
    can_Tx.ExtId = 0;
    can_Tx.IDE = CAN_ID_STD;
    can_Tx.RTR = CAN_RTR_DATA;
    can_Tx.DLC = 5;
    can_Tx.TransmitGlobalTime = DISABLE;

  	while (1)
  	{
      	HAL_CAN_AddTxMessage(&hcan1, &can_Tx, sendBuf, &box);
      	HAL_Delay(100);
  	}
}

写法二:测试成功后可以封装成发送函数,下面之所以有while循环等待发送完成是为了避免出现发送5条数据,只能接受到一条数据的情况

uint8_t can1_send_msg(uint32_t id, uint8_t *msg, uint8_t len)
{
     uint16_t t = 0;
    uint32_t TxMailbox = CAN_TX_MAILBOX0;
    
    g_canx_txheader.StdId = id;         /* 标准标识符 */
    g_canx_txheader.ExtId = id;         /* 扩展标识符(29位) */
    g_canx_txheader.IDE = CAN_ID_STD;   /* 使用标准帧 */
    g_canx_txheader.RTR = CAN_RTR_DATA; /* 数据帧 */
    g_canx_txheader.DLC = len;

    if (HAL_CAN_AddTxMessage(&hcan1, &g_canx_txheader, msg, &TxMailbox) != HAL_OK) /* 发送消息 */
    {
        return 1;
    }
    
    while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) != 3)   /* 等待发送完成,所有邮箱为空 */
    {
        t++;
        
        if (t > 0xFFF)
        {
            HAL_CAN_AbortTxRequest(&hcan1, TxMailbox);     /* 超时,直接中止邮箱的发送请求 */
            return 1;
        }
    }
    
    return 0;
}

七、配置过滤器接收数据

写法一:直接主函数测试接收是否配置成功

#include <stdio.h>

CAN_RxHeaderTypeDef can_Rx;
uint8_t recvBuf[8];

int main(void)
{
  	HAL_Init();
 	SystemClock_Config();
  	MX_GPIO_Init();
  	MX_CAN_Init();
    MX_USART1_UART_Init()

    CAN_FilterTypeDef can_Filter = {0};
    
    can_Filter.FilterIdHigh = 0;
    can_Filter.FilterIdLow = 0;
    can_Filter.FilterMaskIdHigh = 0;
    can_Filter.FilterMaskIdLow = 0;
    can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
    can_Filter.FilterBank = 0;
    can_Filter.FilterMode = CAN_FILTERMODE_IDMASK;
    can_Filter.FilterScale = CAN_FILTERSCALE_32BIT;
    can_Filter.FilterActivation = CAN_FILTER_ENABLE;
    HAL_CAN_ConfigFilter(&hcan1, &can_Filter);
    
    HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
    
    HAL_CAN_Start(&hcan1);

  	while (1)
  	{

  	}
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &can_Rx, recvBuf);


}

写法二:让CAN接收更加系统化 

(1) 直接加在CAN1初始化的下面即可,配置过滤器,只有配置了过滤器之后才能接收数据

/* 配置CAN过滤器 */
	CAN_FilterTypeDef sFilterConfig;
    sFilterConfig.FilterBank = 0;                             /* 过滤器0 */
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh = 0x0000;                      /* 32位ID */
    sFilterConfig.FilterIdLow = 0x0000;
    sFilterConfig.FilterMaskIdHigh = 0x0000;                  /* 32位MASK */
    sFilterConfig.FilterMaskIdLow = 0x0000;
    sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;       /* 激活滤波器0 */
    sFilterConfig.SlaveStartFilterBank = 14;				//设置CAN2的起始过滤器组(对于单CAN的CPU或从CAN此参数无效;对于双CAN的CPU此参数为从CAN的起始过滤器组编号)
    HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);/* 过滤器配置 */

(2) 除开之前在cubemx配置时使能了CAN接收总中断,还需要打开CAN的FIFO消息挂起中断请求(也就是CAN外设的中断使能位)。

HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);

(3)重写CAN接收中断回调函数 

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &can_Rx, recvBuf);

	/*下面是你用来处理收到数据的代码,
	可以通过串口把内容发送出来,
	也可以用来控制某些外设*/
}

八、CAN调试心得

(1)如果使用CAN盒调试CAN通信时,出现发送或者接收数据失败,将CAN配置为静默回环模式,先排除硬件文件,保证软件无误

(2)发送5帧数据只能接收到一帧数据,说明CAN发送较快,发送完一帧数据之后可以等待发送完成在发送下一帧数据,修改CAN配置

(3)如果静默回环模式配置正确,使用CAN盒通信时只能接收错误帧,检查CAN波特率是否正确。有两种可能性,第一种就是CAN的波特率计算错误,第二种就是系统时钟配置错误,倒是CAN时钟不是默认时钟

九、配置两个CAN通信

如果配置两个CAN通信,他们的过滤器配置需要稍作修改

CAN1

/* 配置CAN过滤器 */
	CAN_FilterTypeDef sFilterConfig;
    sFilterConfig.FilterBank = 0;                             /* 过滤器0 */
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh = 0x0000;                      /* 32位ID */
    sFilterConfig.FilterIdLow = 0x0000;
    sFilterConfig.FilterMaskIdHigh = 0x0000;                  /* 32位MASK */
    sFilterConfig.FilterMaskIdLow = 0x0000;
    sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;       /* 激活滤波器0 */
    sFilterConfig.SlaveStartFilterBank = 14;				 设置CAN2的起始过滤器组(对于单CAN的CPU或从CAN此参数无效;对于双CAN的CPU此参数为从CAN的起始过滤器组编号)
    HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);/* 过滤器配置 */

CAN2 

CAN_FilterTypeDef sFilterConfig;
    sFilterConfig.FilterBank = 14;                             /* 过滤器14 */
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh = 0x0000;                      /* 32位ID */
    sFilterConfig.FilterIdLow = 0x0000;
    sFilterConfig.FilterMaskIdHigh = 0x0000;                  /* 32位MASK */
    sFilterConfig.FilterMaskIdLow = 0x0000;
    sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;       /* 激活滤波器0 */
    sFilterConfig.SlaveStartFilterBank = 28;				    //无效
    HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig);/* 过滤器配置 */

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32CubeMX配置CAN通信,可以按照以下步骤进行操作: 1. 打开STM32CubeMX软件,选择你的目标STM32微控制器型号,并创建一个新的工程。 2. 在"Pinout & Configuration"选项卡中,选择CAN外设。根据你的需求,选择一个可用的CAN控制器,并将其引脚分配给合适的GPIO引脚。 3. 在"Configuration"选项卡中,找到"Peripherals"子选项卡,然后选择CANx (x表示你选择的CAN控制器编号)。 4. 在CAN配置界面中,你可以进行以下配置: - "Mode":选择CAN通信模式,可以是"Normal"、"Loopback"或"Silent"。 - "Baudrate Prescaler":设置CAN总线的波特率预分频系数。 - "Time Quantum in Bit Segment 1"和"Time Quantum in Bit Segment 2":设置CAN帧的时间段长度。 - "Synchronization Jump Width":设置CAN帧同步跳转宽度。 - "Transmitter Delay Compensation":设置发送器延迟补偿。 - "Automatic Bus Off Management":选择是否启用自动总线关闭管理。 - "Automatic Wakeup Mode":选择是否启用自动唤醒模式。 - "Filter Scale"和"Filter Mode":设置CAN过滤器的规模和模式。 - "Filter Identifier List Mode":选择过滤器的标识符列表模式。 - "Filter Identifier Mask Mode":选择过滤器的标识符掩码模式。 5. 配置完成后,点击"OK"按钮,然后生成代码。 6. 在生成的代码中,你可以使用HAL库提供的函数来初始化和配置CAN外设,并实现CAN通信的发送和接收操作。 以上是使用STM32CubeMX配置CAN通信的基本步骤。根据你的具体需求,你还可以进一步定制CAN外设的其他参数和功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值