STM32CubMX自学笔记(七)—CAN通信实验

STM32CubMX自学笔记(七)—CAN通信实验

主要介绍

由于项目需求要用到CAN通信协议,因此学习一下CAN通信机理和方法。
CAN 是 ISO 国际标准化的串行通信协议。在当前的汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个 LAN,进行大量数据的高速通信”的需要,1986 年德国电气商博世公司开发出面向汽车的 CAN 通信协议。此后,CAN 通过 ISO11898 及 ISO11519 进行了标准化,现在在欧洲已是汽车网络的标准协议。 现在,CAN 的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。现场总线是当今自动化领域技术发展的热点之一,被誉为自动化领域的计算机局域网。它的出现为分布式控制系统实现各节点之间实时、可靠的数据通信提供了强有力的技术支持。CAN 控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平和隐性电平,二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。
本实验主要通过基本的方式来实现CAN通讯。
CAN 协议具有以下特点:
1) 多主控制。
2) 系统的柔软性。
3) 通信速度较快,通信距离远。
4) 具有错误检测、错误通知和错误恢复功能。
5) 故障封闭功能。
6) 连接节点多。
具体细节参考正点原子的开发手册,这里介绍CAN的CUBMX配置。

工程配置

首先,我们使能CAN1,如果要是用CAN2,也必须使能CAN1的时钟。开发板是探索者F407。CAN1的时钟源来自于APB1,这里我们把时钟拉满,然后APB1的时钟是42MHz,如下图所示。
STM32CubMX自学笔记(七)—CAN通信实验_第1张图片
紧接着,激活了CAN1之后,可以看到一大堆CAN的配置属性。
STM32CubMX自学笔记(七)—CAN通信实验_第2张图片
这里我们将分频系数配置为6,也就是7MHz,然后配置BS1段为5,BS2段为3,重新同步的跳跃宽度配置为2。
然后基本功能下,不需要配置其他功能,仅仅配置了使能自动离线管理功能。
模式选择我们选择了回环模式,就是自己发自己收,不经过CAN的收发器就可以完成实验。
配置完成之后生成工程。
生成工程之后,可以看到自动生成了如下的代码,自动配置了参数,使能了引脚。

void MX_CAN1_Init(void)
{
     
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 6;
  hcan1.Init.Mode = CAN_MODE_LOOPBACK;
  hcan1.Init.SyncJumpWidth = CAN_SJW_2TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_5TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_4TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = ENABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = DISABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
     
    Error_Handler();
  }
}

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{
     
  GPIO_InitTypeDef GPIO_InitStruct = {
     0};
  if(canHandle->Instance==CAN1)
  {
     
    __HAL_RCC_CAN1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

紧接着 添加自己的代码,过滤器,实现需要过滤掉的数据,只查看我们想要看到的数据。代码如下:

void CAN_Filter_Config(void)
{
     
	CAN_FilterTypeDef CAN_FilterConfig;
	CAN_FilterConfig.FilterBank = 0;
	CAN_FilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
	CAN_FilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
	CAN_FilterConfig.FilterIdHigh = ((((uint32_t)0x1314<<3)|
	CAN_ID_EXT|CAN_RTR_DATA)&0XFFFF0000)>>16;
	
	CAN_FilterConfig.FilterIdLow  = ((((uint32_t)0x1314<<3)|
	CAN_ID_EXT|CAN_RTR_DATA)&0XFFFF0000)>>16;
	
	CAN_FilterConfig.FilterMaskIdHigh = 0XFFFF;//设置掩码的高位
	CAN_FilterConfig.FilterMaskIdLow  = 0XFFFF;//设置掩码的低位
	CAN_FilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
	CAN_FilterConfig.FilterActivation = ENABLE;
	HAL_CAN_ConfigFilter(&hcan1,&CAN_FilterConfig);//使能过滤器
	
} 

void CAN_ConfigInit(void)
{
     
	MX_CAN1_Init();
	CAN_Filter_Config();
}
CAN_TxHeaderTypeDef Can_HandleTxMsg;

然后配置CAN发送数据代码,配置发送的数据格式以及数据块。

void CAN_Send(void)
{
     
	uint32_t *pTxMailBox;
	uint8_t temp[8] = {
     1,2,3,4,5,6,7,8};
	Can_HandleTxMsg.StdId = 0x00;
	Can_HandleTxMsg.ExtId = 0x1314;
	Can_HandleTxMsg.IDE		= CAN_ID_EXT;
	Can_HandleTxMsg.RTR   = CAN_RTR_DATA;
	Can_HandleTxMsg.DLC   = 8;
	
	HAL_CAN_AddTxMessage(&hcan1,&Can_HandleTxMsg,temp,pTxMailBox);
}

最后在主函数中实现发送
使能CAN的发送。

HAL_CAN_Start(&hcan1);
CAN_Send();

调用CAN的发送函数,至此,完成CAN的一个送过程。

CAN_Send();

小结

本小结仅仅是对CAN的通信进行了简单表达,里面的很多细节都需要去查看手册,回头再去看看火哥的标准库的视频,还有HAL库的配置视频,还有文档教程。

你可能感兴趣的:(STM32,stm32,单片机,物联网)