STM32F407之CAN控制器的使用

CAN控制器局域网络 (Controller Area Network),是目前广泛应用的可靠串行总线通信之一,其国际标准号为ISO 11898。CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线。
CAN总线上的节点既可以发送数据也可以接收数据,没有主从之分,但属于半双工通信,同一时刻只能由一个节点发送数据,其他节点只能接收。发送数据具有自动竞争机制,优先级高的竞争成功,优先级通过数据帧ID逐位判断,显性电平胜出。通信过程不需要时钟信号,而采用约定波特率的方式实现同步。

一、总线结构

分为闭环和开环两种结构形式,两种形式适用于不同的通信速率和通信距离:

  • 闭环:高速、短距离,通信速率一般为125kbit/s到1Mbit/s,1Mbit/s时可达40m
  • 开环:低速、短距离,通信速率一般低于125kbit/s,40kbit/s时可达1km,5kbit/s时可达10km

总线典型电压却不同,但都采用2根差分信号线(CAN_High和CAN_Low)进行信号传输。所以,在设计方案时,要根据实际需要选择对应的结构形式,并选择对应的CAN收发器芯片
CAN总线电压有两种:

  • 隐形电平,即逻辑1
    ——闭环结构中为2.5V,开环结构中为1.75V
  • 显性电平,即逻辑0
    ——闭环结构中为3.5V,开环结构中为4.0V

注意
CAN控制器和CAN收发器之间通过CAN_RX和CAN_TX进行通信,类似于TTL。默认下,CAN收发器上电后会自动将CAN_RX和CAN_TX拉高,以表示准备就绪。当我们在调试时,如果板子没有接收发器,就需要人为将CAN_RX和CAN_TX信号线上拉,不然CAN控制器会因检测不到收发器而超时报错,无法启动。

在这里插入图片描述

在这里插入图片描述

二、传输协议

2.1帧

CAN一共有5种类型的帧:

  1. 数据帧:数据帧携带ID和数据从发送器至接收器。

  2. 远程帧/遥控帧:节点向总线网络发出只带有ID的帧,用以进行数据请求,具有该ID的节点接收到远程帧后发送相应ID的数据帧。

  3. 错误帧:任何节点检测到总线错误时就发送错误帧。

  4. 过载帧:接收节点未做好接收准备时发出的帧,发送节点收到过载帧时可暂缓发送数据帧。

  5. 帧间空间:用来将数据帧、远程帧与前后的帧分割开提供附加的延时。

2.2标准格式数据帧和远程帧

在这里插入图片描述

  1. SOF(Start Of Frame)帧起始位,显性电平0;
  2. RTR(Remote Transmit Request)远程帧标志位,显性电平0表示数据帧,优先级高于远程帧;
  3. IDE(Identifier Extension)ID扩展格式标志位,隐形电平1表示该帧为扩展格式;
  4. R0 保留位,默认显性电平0;
  5. DLC(Data Length Code)4位数据长度码,有效值为0-8,表示数据段字节数;远程帧始终为0;
  6. CRC 即15位CRC校验值;
  7. DEL0(Delimiter)界定位,默认为隐性电平1,在该位时间内,接收端完成对接收数据的校验检查,以确保在ACK时刻给出结果;
  8. ACK(Acknowledge)响应位,发送端在该时刻置隐性电平并读取总线电平,接收端在此时可将数据检查结果反馈在总线上,若数据正常置显性电平0,若数据异常置隐性电平1,这样发送端就可以知道数据传输的结果;
  9. DEL1(Delimiter)界定位,默认为隐性电平1;
  10. EOF(End Of Frame)帧结束,共7位隐性电平1,表示帧结束。

2.3扩展格式数据帧和远程帧

在这里插入图片描述
相较标准格式,除了增加了18位扩展标识符外,还增加了SRR(Substitute Remote Request替代远程请求位)和R1(保留位1),这两个位均相当于占位符,默认隐性电平1。

2.4优先级

  1. 最先开始发送消息的节点获得发送权;
  2. 多节点同时开始发送时,逐位仲裁,当发生电平互异时输出显性电平的节点获得优先发送权继续发送,隐性电平的节点退出本次发送;
  3. 数据帧优先级>远程帧优先级
  4. 标准格式帧优先级>扩展格式帧优先级

2.5位时序

标准CAN协议中,每一个位细分为四个阶段,每个阶段又由不同个数的时间片tq组成,每个时间片长度由CAN控制器的时钟频率决定,四个阶段分别为:

  1. SYNC_SEG:同步段,1 个时间片。它用于同步各种总线节点;
  2. PTS_SEG:传播段,1~8 时间片。它用于补偿网络上的信号延迟。
  3. PBS_SEG_1:相位缓冲段1,1~8 时间片。它用于补偿边缘相位误差,在重新同步期间可能会延长。
  4. PBS_SEG_2:相位缓冲段2,2~8 时间片。它用于补偿边缘相位误差。
    在这里插入图片描述
    那么 波特率 = 1/(1+PROP+PHASE1+PHASE2)

----------------------------------------------分割线-------------------------------------------------------------------------
但是,STM32自带的CAN控制器的位时序和上面的标准位时序有一些区别,只有三个阶段:同步段(SYNC_SEG)、 时间段 1(BS1)、 时间段 2(BS2)。其中,BS1段是 CAN 标准协议中的 PTS 段和 PBS1 段的结合, 而 BS2 段就相当于 PBS2 段。
在这里插入图片描述

2.6控制器配置

在这里插入图片描述

2.7收发功能

STM32F407自带2个CAN控制器,CAN1为带有512字节SRAM的主CAN控制器,CAN2是从控制器,和CAN1共享512字节SRAM,但CAN2要访问SRAM必须保证CAN1正常工作以提供SRAM读写时钟,也就是说CAN2不能独立工作。同时筛选器的配置也需要在CAN1中完成,CAN2无法配置。

  • 每个CAN控制器有1个发送FIFO,其包含3个发送邮箱,每个发送邮箱可存放1条帧信息
  • 每个CAN控制器有2个接收FIFO,每个接收FIFO有3个接收邮箱,每个接收邮箱可存放1条帧信息
  • 具有16位定时器,可实现定时触发通信,并可在最后两个数据字节发送时间戳
  • 两个CAN控制器共用28个筛选器,筛选器用于配置可接收ID列表或掩码,只有通过筛选的帧才会进入接收邮箱;在CAN1筛选器配置中通过SlaveStartFilterBank完成CAN2筛选器的配置。
  • 一个筛选器只能配置给一个接收FIFO,但一个接收FIFO可以同时关联多个筛选器。
  • 通过筛选器进入接收FIFO的帧数据会自动分配到空闲的邮箱中。

CAN有4种收发模式,除正常模式外的3种都叫做测试模式:

  • 正常模式Normal:可发送到总线,也可从总线接收数据;
  • 静默模式Silent:可向自身接收端发送显性电平,只能向总线发送隐性电平,即无法向外发送数据;可以接收总线数据和自身发送的数据;
  • 回环模式Loopback:可向总线和自身接收端发送数据,但不能正常接收总线数据,只能接收自身发送的数据;
  • 回环静默模式:只能自发自收,不能向总线正常发送数据或从总线接收数据。

2.8工作流程

  • 模块初始化

void MX_CAN1_Init(void) >>> HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan)

  • 配置筛选器
HAL_StatusTypeDef CAN_SetFilters()
{
	CAN_FilterTypeDef canfilter;
	canfilter.FilterBank = 0;//筛选器编号
	canfilter.FilterMode = CAN_FILTERMODE_IDMASK;//筛选器模式:掩码模式mask or 表单模式list
	canfilter.FilterScale = CAN_FILTERSCALE_32BIT;//32BIT表示为1个32位过滤值,16BIT表示为2个16位过滤值
	canfilter.FilterIdHigh = 0x0020;//和FilterMaskIdHigh配合使用,接收到的ID & 掩码ID == 过滤器ID & 掩码ID
	canfilter.FilterIdLow = 0x0000;
	canfilter.FilterMaskIdHigh = 0x0020;//对于标准码,前11位为ID
	canfilter.FilterMaskIdLow = 0x0000;
	canfilter.FilterFIFOAssignment = CAN_RX_FIFO0;//过滤器应用于FIFO0
	canfilter.FilterActivation = ENABLE;//使能过滤器
	canfilter.SlaveStartFilterBank = 14;//过滤器0-13为CAN1使用;过滤器14-28号为CAN2使用
	HAL_StatusTypeDef result = HAL_CAN_ConfigFilter(&hcan1, &canfilter);
	return result;
}
  • 启动控制器

HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)

  • 收发读取
//例程:发送帧
void CAN_SendMsg(uint8_t msgID,uint8_t frameType)
{
	uint8_t TxData[8];
	TxData[0]=0x56;
	TxData[1]=0x57;
	CAN_TxHeaderTypeDef TxHeader;
	TxHeader.StdId= msgID;
	TxHeader.RTR=frameType;//数据帧or遥控帧设定
	TxHeader.IDE=CAN_ID_STD;
	TxHeader.DLC=2;//数据字节数
	TxHeader.TransmitGlobalTime=DISABLE;//禁用时间戳
	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)<1)	{}//等待有可用的发送邮箱
	uint32_t TxMailbox;
	if(HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox)!=HAL_OK)//向发送邮箱加载帧
	{
		  uint8_t	sendbytes[] = "CAN sendmsg err.\r\n";
		  HAL_Delay(10);
		  HAL_UART_Transmit(&huart1, sendbytes, sizeof sendbytes, 150);
		  return;
	}
	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)!=3){}//等待3个发送邮箱均发送完毕
}
//例程:循环查询方式接收
void CAN_GetPoll()
{
	CAN_RxHeaderTypeDef RxHeader;
	uint8_t RxData[8];
	HAL_Delay(1);
	uint8_t fifolevel = HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0);
	if(fifolevel == 0)//检测是否有数据到达接受邮箱
	{
		  uint8_t	sendbytes[] = "CAN not getmsg.\r\n";
		  HAL_Delay(10);
		  HAL_UART_Transmit(&huart1, sendbytes, sizeof sendbytes, 150);
		  return;
	}

	if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData)==HAL_OK)//若有数据到达则从FIFO中非空邮箱里按序提取帧
	{
		  uint8_t	sendbytes[] = "\r\nCAN getmsg:stid=";
		  HAL_Delay(10);
		  HAL_UART_Transmit(&huart1, sendbytes, sizeof(sendbytes)-1, 150);

		  uint8_t stid[4];
		  stid[0]	= RxHeader.StdId>>24;
		  stid[1]	= RxHeader.StdId>>16;
		  stid[2]	= RxHeader.StdId>>8;
		  stid[3]	= RxHeader.StdId;
		  HAL_Delay(10);
		  HAL_UART_Transmit(&huart1, stid, sizeof stid, 150);

		  if(RxHeader.RTR==CAN_RTR_DATA)//如果是数据帧则读取数据
		  {
			  uint8_t	sendbytes[] = "\r\nCAN getmsg:data=";
			  HAL_Delay(10);
			  HAL_UART_Transmit(&huart1, sendbytes, sizeof(sendbytes)-1, 150);
			  HAL_Delay(10);
			  HAL_UART_Transmit(&huart1, RxData, sizeof RxData, 150);
		  }
	}
}

如果开启了中断接收,可以在函数 void CAN1_RX0_IRQHandler(void) 中调用接收处理函数,
或重写回调函数void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)

  • 停止控制器

HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan)

  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 要使用STM32F407控制3508电机,需要进行以下步骤: 1. 首先,需要了解3508电机的通信协议。通常情况下,3508电机使用CAN总线进行通信。因此,需要在STM32F407上配置CAN总线。 2. 配置CAN总线后,需要编写代码来控制3508电机。可以使用STM32F407的CAN库来发送CAN消息到3508电机,以控制其速度和方向。 3. 在编写代码时,需要注意3508电机的控制方式。通常情况下,可以使用PID控制器来控制电机的速度和位置。 4. 最后,需要将STM32F407和3508电机连接起来。可以使用CAN总线连接它们,也可以使用其他通信方式,如UART或SPI。 总之,要控制3508电机,需要了解其通信协议和控制方式,并编写相应的代码来实现控制。同时,需要将STM32F407和3508电机连接起来,以便它们可以进行通信。 ### 回答2: 要控制3508电机,首先需要了解STM32F407的CAN总线模块和3508电机的控制方式。 STM32F407的CAN总线模块支持CAN2.0A和CAN2.0B协议。通过CAN总线,可以进行多个设备之间的通信。要控制3508电机,可以通过CAN总线发送控制指令。 而3508电机是一种智能型直流无刷电机,可以通过CAN总线进行控制。在3508电机中,使用STM32F407类似的MCU控制器,可以通过CAN通信接收外部的指令并执行相应的动作。控制器还会检测电机的状态,如电机转速、电机温度等,并将它们反馈给主控制器。 具体控制过程如下: 1. 编写STM32F407的CAN总线发送程序,将控制指令打包成CAN帧,通过CAN总线发送到3508电机。 2. 在3508电机中,使用MCU控制器接收CAN帧,解析出控制指令,并执行相应的动作。例如,如果接收到的控制指令为电机转速值,则控制器会将电机转速设定为指定值。 3. 控制器会通过CAN总线发送状态反馈信息,例如电机转速、电机温度等,反馈给STM32F407STM32F407通过CAN总线接收反馈信息,可以进行相应的处理,例如根据反馈信息调整控制指令,以达到更精确的控制效果。 需要注意的是,在确定3508电机的控制方式及其CAN通信协议之前,需要先了解具体的硬件和软件架构和技术要求,以确保控制器能够正确控制电机。 总的来说,STM32F407通过CAN总线与3508电机进行通信,可以实现精准的控制。相信在应用场景中,这种控制方法必将会具有广泛的应用前景。 ### 回答3: 首先,stm32f407可以通过CAN总线控制3508电机。CAN总线是一种高速、可靠的通信协议,广泛应用于工业领域,特别适合各种高速控制场合。 其次,为了控制3508电机,需要了解它的工作原理。3508电机是一种直流无刷电机,具有高转速和高功率的特点,需要使用PWM信号来控制转速。同时,需要使用差分驱动方式,即需要使用四个PWM信号来分别控制电机的四个线圈。 最后,通过stm32f407和3508电机进行连接,需要在硬件上实现CAN模块与3508电机的连接,并在软件上通过编程实现CAN总线的控制和PWM信号的产生。 在程序开发过程中,可以使用STM32CubeMX作为开发工具,在其生成的初始化代码基础上进行修改和调试。在代码中需要包括CAN总线的初始化、CAN报文的发送和接收、PWM的产生和差分驱动方式的实现等功能。需要注意的是,CAN总线的帧格式和3508电机的控制协议需要根据具体情况而定,并进行相应的配置。 总之,通过合理的硬件和软件设计,stm32f407可以成功控制3508电机,实现高速、高精度的控制应用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值