使用STM32 CubeMX配置CAN通信

一、CAN通信简介

        CAN 是控制器局域网络(Controller Area Network) 的简称,它是由研发和生产汽车电子产品著称的 德国BOSCH 公司开发的,并最终成为国际标准(ISO11519), 是国际上应用最广泛的现场总线之一。

        CAN 总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。 近年来,它具有的高可靠性和良好的错误检测能力受到重视,被广泛应用于汽车计算机控制系统和环境温度恶劣、电磁辐射强及振动大的工业环境。

二、物理连接模型

        CAN物理层的形式主要有两种,下图中的CAN通讯网络是一种遵循ISO11898标准的高速、短距离“闭环网络”, 它的总线最大长度为40m,通信速度最高为1Mbps,总线的两端各要求有一个“120欧”的电阻。由于电阻并联,最终CAN_H和CAN_L之间的电阻为60欧。

三、差分信号

        CAN总线使用差分信号,差分信号又称差模信号,与传统使用单根信号线电压表示逻辑的方式有区别,使用差分信号传输时,需要两根信号线, 这两个信号线的振幅相等,相位相反,通过两根信号线的电压差值来表示逻辑0 和逻辑1。

相较于单线传输,差分信号传输的优点如下:

1、抗干扰能力强。当存在干扰时,大部分干扰几乎都会被同时叠加在CAN_H和CAN_L两条信号线上,而由于采用差分信号,接收端只关注CAN_H和CAN_L的差值,所以大部分干扰都可以被完全抵消。

2、时许定位精确。

在CAN协议中,对CAN_H,CAN_L表示的差分信号做了一些规定,如下图。其中逻辑1为隐形电平,逻辑0为显性电平(可以理解为逻辑0的优先级高于逻辑1,当线路上两设备同时发送逻辑0和1时,线路上表现为逻辑0,这是由物理层面决定的。CAN通信仲裁帧的优先级判断就是基于此)。

 举例:

        CAN_H为2.5V、CAN_L为2.5V,求该位最后的逻辑值?

        电位差=CAN_H-CAN_L = 2.5 – 2.5 = 0v;

        所以逻辑值为1.

四、CubeMX配置

        本案例使用的开发板为Robomaster B型开发板,单片机型号为STM32F105R8T6。

 1、配置时钟

        查阅开发板手册可知该开发板外置晶振频率为12Mhz。

        首先配置外置晶振源,如下图所示。

         然后配置时钟树,将12MHz的外置晶振频率填入1处,之后在2处直接输入72MHz(最高频率),CubeMX将会自动配置其他时钟,如下图:

        CAN被分配在APB1总线上,所以在CAN通信中,我们只需关注APB1设备时钟值(APB1 peripheral clocks),即36MHz。

2、配置CAN波特率

        查阅2006配套电调C610手册可知通信波特率为1M,即1000000bit/s。配置公式如下:

        波特率=APB1设备时钟➗分频系数➗(BS1+BS2+同步时间段)

        1000000 = 36000000➗4➗(4+4+1)

        Prescaler为分频系数、Time Quanta in Bit Segment 1为BS1、Time Quanta in Bit Segment 2为BS2、ReSynchronization Jump Width为同步时间段。

        灰色Baud Rate为根据配置计算出的波特率,此处最终必须为1000000。

        所以配置为下图:

        配置完成后生成代码。

3、代码编写 

CAN通信启动函数,放在main里CAN初始化的后面即可:

HAL_CAN_Start(&hcan1);

电机发送函数编写(让我看看还有谁把函数定义丢main函数里,别看别人,说的就是你):

static CAN_TxHeaderTypeDef  chassis_tx_message;//发送数据的数据头
static uint8_t              chassis_can_send_data[8];//要发送的数据数组
void CAN_cmd_motor(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4)
{
    uint32_t send_mail_box;
    chassis_tx_message.StdId = 0x200;//查阅C610手册,ID为1-4时发送标识为0x200
    chassis_tx_message.IDE = CAN_ID_STD;
    chassis_tx_message.RTR = CAN_RTR_DATA;
    chassis_tx_message.DLC = 0x08;
    chassis_can_send_data[0] = motor1 >> 8; //id1电机 设置电流值高8位
    chassis_can_send_data[1] = motor1;      //id1电机 设置电流值低8位
    chassis_can_send_data[2] = motor2 >> 8; //id2电机 设置电流值高8位
    chassis_can_send_data[3] = motor2;      //id2电机 设置电流值低8位
    chassis_can_send_data[4] = motor3 >> 8;
    chassis_can_send_data[5] = motor3;
    chassis_can_send_data[6] = motor4 >> 8;
    chassis_can_send_data[7] = motor4;

    HAL_CAN_AddTxMessage(&hcan1, &chassis_tx_message, chassis_can_send_data, &send_mail_box);
}

此处假设C610的ID被设置为1(绿灯闪烁一次)。

在main函数调用该函数即可。

main函数while循环:

  while (1)
  {
		CAN_cmd_motor(200, 0, 0, 0);//向id1的电机发送电流值为200
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

编译烧录,正确配置电机id即可旋转。

4、小坑

        至此你可能(大概率)会发现,电机毫无反应。。。。

        是因为Robomaster B开发板的CAN1 IO口并不是默认值,而是使用了PB9、PB8端口,需要先在Pinout view里将PB9、PB8分别设置为CAN1_TX和CAN1_RX之后,再激活CAN通信设置波特率。

你学会了吗??? 

物联沃分享整理
物联沃-IOTWORD物联网 » 使用STM32 CubeMX配置CAN通信

发表评论