完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
由于项目需求要用到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,如下图所示。 紧接着,激活了CAN1之后,可以看到一大堆CAN的配置属性。 这里我们将分频系数配置为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库的配置视频,还有文档教程。 |
|
|
|
只有小组成员才能发言,加入小组>>
3334 浏览 9 评论
3013 浏览 16 评论
3506 浏览 1 评论
9094 浏览 16 评论
4105 浏览 18 评论
1215浏览 3评论
628浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
615浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2358浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1923浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-9 10:19 , Processed in 1.231045 second(s), Total 77, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号