16.3.STM32F407ZGT6-CAN波特率配置

参考:

https://blog.csdn.net/sunlight_vip/article/details/128639144

前言:

学习总结CAN的知识点:

1.can是什么,历史由来和背景

2.can的物理层,链路层

3.初始化的流程和关键点

4.波特率怎么设置

5.can id怎么过滤

6.can的发送和接收原理

7.can的发送和接收API

3. CAN Cubemx配置

我们通过问题来熟悉下cubemx配置,你熟悉了这些问题基本就知道怎么配置了!

问题1:Parameter Settings分别都是设置什么的?

答案:如图

问题2:怎么配置波特率呢?

答案:用我上面贴的工具(CAN波特率计算 f103AHP1_36M f407AHP1_42M 采样点软件有说明.rar)直接配置,举两个个例子

例子1:我们要配置成500KHz,那么我们这样配置

我们用采集点为80%,所以BS1为4tq, BS2为2tq, 分频系数为12,代进公式

Fpclk1 / ((CAN_BS1+CAN_BS2+1)*CAN_Prescaler) = 42M / (4+2+1) / 12=500kHz

例子2:我们要配置成1M Hz,那么我们这样配置

我们用采集点为75%,所以BS1为3tq, BS2为2tq, 分频系数为7,代进公式

Fpclk1/((CAN_BS1+CAN_BS2+1)*CAN_Prescaler)=42M/(3+2+1)/7=1MHz

问题3:Basic Parameter分别是啥意思呢?

Timer Triggered Communication Mode:是否使用时间触发功能 (ENABLE/DISABLE),时间触发功能在某些CAN 标准中会使用到。

Automatic Bus-Off Management:用于设置是否使用自动离线管理功能 (ENABLE/DISABLE),使用自动离线管理可以在出错时离线后适时自动恢复,不需要软件干预。

Automatic Wake-Up Mode:用于设置是否使用自动唤醒功能 (ENABLE/DISABLE),使能自动唤醒功能后它会在监测到总线活动后自动唤醒。

Automatic Retransmission:用于设置是否使用自动重传功能 (ENABLE/DISABLE),使用自动重传功能时,会一直发送报文直到成功为止。

Receive Fifo Locked Mode:用于设置是否使用锁定接收 FIFO(ENABLE/DISABLE),锁定接收 FIFO 后,若FIFO 溢出时会丢弃新数据,否则在 FIFO 溢出时以新数据覆盖旧数据。

Transmit Fifo Priority:用于设置发送报文的优先级判定方法 (ENABLE/DISABLE),使能时,以报文存入发送邮箱的先后顺序来发送,否则按照报文 ID 的优先级来发送。配置完这些结构体成员后,我们调用库函数 HAL_CAN_Init 即可把这些参数写入到 CAN 控制寄存器中,实现 CAN 的初始化

问题4:为啥CAN分为RX0,RX1中断呢?

答案:STM32有2个3级深度的接收缓冲区:FIFO0和FIFO1,每个FIFO都可以存放3个完整的报文,它们完全由硬件来管理。如果是来自FIFO0的接收中断,则用CAN1_RX0_IRQn中断来处理。如果是来自FIFO1的接收中断,则用CAN1_RX1_IRQn中断来处理,如图:

问题5:CAN SCE中断是什么?

答案:status chanege error,错误和状态变化中断!

4. 实验

4.1.Normal模式测试500K 波特率(定时发送,轮询接收)

4.1.1 CubeMx配置


4.1.2 设置Filter过滤,我们只使能FIFO0,并且不过滤任何消息

c 复制代码
CAN_FilterTypeDef filter = {0};
filter.FilterActivation = ENABLE;
filter.FilterMode = CAN_FILTERMODE_IDMASK;
filter.FilterScale = CAN_FILTERSCALE_32BIT;
filter.FilterBank = 0;
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
filter.FilterIdLow = 0;
filter.FilterIdHigh = 0;
filter.FilterMaskIdLow = 0;
filter.FilterMaskIdHigh = 0;
HAL_CAN_ConfigFilter(&hcan1, &filter);

4.1.3 开启CAN(注意,默认Cubemx生成的代码并没有can start)

HAL_CAN_Start(&hcan1);

4.1.4 编写发送函数

c 复制代码
uint8_t xl_can1_send_msg(uint32_t id, uint8_t *data, uint32_t data_len)
{
    uint8_t index = 0;
    uint32_t *msg_box;
    uint8_t send_buf[8] = {0};
    
    CAN_TxHeaderTypeDef send_msg_hdr;

    if (id < 0x7FF)
    {
        send_msg_hdr.StdId = id;
        send_msg_hdr.ExtId = id;
        send_msg_hdr.IDE = CAN_ID_STD;
    }
    else
    {
        send_msg_hdr.StdId = id;
        send_msg_hdr.ExtId = id;
        send_msg_hdr.IDE = CAN_ID_EXT;
    }

    send_msg_hdr.RTR = CAN_RTR_DATA;
    send_msg_hdr.DLC = data_len;
    send_msg_hdr.TransmitGlobalTime = DISABLE;
    
    for(index = 0; index < data_len; index++)
          send_buf[index] = data[index];

    HAL_CAN_AddTxMessage(&hcan1, &send_msg_hdr, send_buf, msg_box);

    return 0;
}

4.1.5 编写轮询接收函数

c 复制代码
uint8_t xl_can1_polling_recv_msg(uint32_t* id, uint8_t* data, uint32_t* data_len)
{
    uint8_t index = 0;
    uint8_t recv_data[8];
    CAN_RxHeaderTypeDef header;

    while (HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0) != 0)
    {
        if (__HAL_CAN_GET_FLAG(&hcan1, CAN_FLAG_FOV0) != RESET)
            printf("[CAN] FIFO0 overrun!\n");

        HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &header, recv_data);

        if(header.IDE == CAN_ID_STD)
        {
            printf("StdId ID:%d\r\n",header.StdId);
        }
        else
        {
            printf("ExtId ID:%d\r\n",header.ExtId);
        }
        printf("CAN IDE:0x%x\r\n",header.IDE);
        printf("CAN RTR:0x%x\r\n",header.RTR);
        printf("CAN DLC:0x%x\r\n",header.DLC);
        printf("RECV DATA:");

        for(index = 0; index < header.DLC; index++)
        {
            printf("0x%x ",recv_data[index]);
        }

        printf("\r\n");
    }
}

备注:

1.STM32CubeMX默认生成的代码没有调用HAL_CAN_Start(&hcan1);,需要手动添加该函数使能CAN。

2...STM32CubeMX默认生成的代码没有编写关于Filter部分,需要手动添加过滤ID报文部分。 若是不添加过滤部分,硬件不知道过滤什么报文,过滤的报文放在哪个FIFO中。

4.1.6 现象:

通过串口输出命令"cmd_can"调用can发送函数,can设备上位机,收到can报文:

上位机发送can数据,开发板能接收解析:

4.2.Normal模式测试500K 波特率(定时发送,中断接收)

4.2.1 CubeMx配置


步骤2,3,4跟polling完全一致,我们来直接说下中断怎么用(主要是使能notifity就行了)

c 复制代码
void MX_CAN1_Init(void)
{
  /* USER CODE BEGIN CAN1_Init 0 */
  /* USER CODE END CAN1_Init 0 */
  /* USER CODE BEGIN CAN1_Init 1 */
  /* USER CODE END CAN1_Init 1 */
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 12;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_4TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = ENABLE;
  hcan1.Init.AutoWakeUp = ENABLE;
  hcan1.Init.AutoRetransmission = DISABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN1_Init 2 */

  CAN_FilterTypeDef filter = {0};
  filter.FilterActivation = ENABLE;
  filter.FilterMode = CAN_FILTERMODE_IDMASK;
  filter.FilterScale = CAN_FILTERSCALE_32BIT;
  filter.FilterBank = 0;
  filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
  filter.FilterIdLow = 0;
  filter.FilterIdHigh = 0;
  filter.FilterMaskIdLow = 0;
  filter.FilterMaskIdHigh = 0;
  HAL_CAN_ConfigFilter(&hcan1, &filter);

  HAL_CAN_Start(&hcan1);

  HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
  /* USER CODE END CAN1_Init 2 */

}

下面我们来编写下中断函数

c 复制代码
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    uint8_t index = 0;
    uint8_t recv_data[8];
    CAN_RxHeaderTypeDef header;

    HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &header, recv_data);
    if(header.IDE == CAN_ID_STD)
    {
        printf("StdId ID:%d\r\n", header.StdId);
    }
    else
    {
        printf("ExtId ID:%d\r\n", header.ExtId);
    }

    printf("CAN IDE:0x%x\n", header.IDE);
    printf("CAN RTR:0x%x\n", header.RTR);
    printf("CAN DLC:0x%x\n", header.DLC);
    printf("interrupt RECV DATA:");
    for(index = 0; index < header.DLC; index++)
    {
        printf("0x%x ",recv_data[index]);
    }
    
    printf("\r\n");
}

4.2.2 现象

通过串口输出命令"cmd_can"调用can发送函数,can设备上位机,收到can报文:

上位机发送can数据,开发板能接收解析:

4.3 源码

git clone git@gitee.com:xiaoliangliangcong/stm32.git

STM32F407ZGT6/16.CAN

相关推荐
2401_843785233 小时前
STM32 DMA+AD多通道
stm32·单片机·嵌入式硬件
cherry_rainyyy6 小时前
51单片机 01 LED
stm32·单片机·嵌入式硬件
宣宣猪的小花园.8 小时前
STM32单片机学习记录(2.2)
stm32·单片机·嵌入式硬件·无人机·空气动力学
Ching·1 天前
物联网 STM32【源代码形式-ESP8266透传】连接OneNet IOT从云产品开发到底层MQTT实现,APP控制 【保姆级零基础搭建】
stm32·嵌入式硬件·物联网
荆楚闲人1 天前
stm32小白成长为高手的学习步骤和方法
stm32·嵌入式硬件·学习
WU-有点东1 天前
Clion开发STM32时使用stlink下载程序与Debug调试
stm32·单片机·嵌入式硬件
charlie1145141911 天前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(绘图设备封装)
c语言·stm32·单片机·学习·oled·嵌入式软件
2401_843785232 天前
STM32 DMA数据转运
stm32·单片机·嵌入式硬件
云山工作室2 天前
基于单片机的盲人智能水杯系统(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设