匿名
未登录
登录
丢石头百科
搜索
查看“STM32CubeMX系列教程12:控制器局域网络(CAN)”的源代码
来自丢石头百科
名字空间
页面
讨论
更多
更多
页面选项
查看
查看源代码
历史
←
STM32CubeMX系列教程12:控制器局域网络(CAN)
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
<b style="line-height: 16.8px; widows: auto; font-size: 14px; background-color: inherit;">一.CAN简介</b> CAN是控制器局域网络(Controller Area Network, CAN)的简称,是由以研发和生产汽车电子产品著称的德国BOSCH公司开发的,是国际上应用最广泛的现场总线之一。 CAN控制器通过组成总线的2根线(CAN-H和CAN-L)的电位差来确定总线的电平,信号是以两线之间的“差分”电压形式出现,总线电平分为显性电平和隐性电平。 CAN总线采用两种互补的逻辑数值"显性"和"隐性"。"显性"数值表示逻辑"0",而"隐性"表示逻辑"1"。当总线上同时出现“显性”位和“隐性”位时,最终呈现在总线上的是“显性”位。 [[File:160307kix7kee75yhjxkmn.png]] 在“隐性”状态下,VCAN_H和VCAN_L被固定与平均电压电平,Vdiff近似为零,此时VCAN_H和VCAN_L的标称值为2.5V。 “显性”位以大于最小阀值的差分电压表示,此时VCAN_H的标称值为3.5V,VCAN_L的标称值为1.5V。 [[File:160307sgiz69t46i9b6vnq.png]] 本实验采用SN65HVD230芯片作为CAN收发器,其逻辑电路图以及管脚图如下。D为CAN发送,R为CAN 接收。CAN-H,CAN-L为CAN总线。CAN收发器即将TTL电平转换为CAN总线电平。 [[File:160307ftxtth15dizdadui.png]] [[File:160308k27kk4700b46kk17.png]] [[File:160308wjxbrbwq9owqz4mq.png]] 在总线空闲时,所有的单元都可开始发送消息(多主控制)。所有的消息都以固定的格式发送。 <b style="background-color: inherit;">二.CAN帧结构</b> <b style="background-color: inherit;"> </b> 报文传输由以下4个不同的帧类型所表示和控制: * 数据帧:数据帧携带数据从发送器至接收器。 * 远程帧:总线单元发出远程帧,请求发送具有同一识别符的数据帧。 * 错误帧:任何单元检测到一总线错误就发出错误帧。 * 帧间空 : 数据帧(或远程帧)通过帧间空间与前述的各帧分开。* 过载帧:过载帧用以在先行的和后续的数据帧(或远程帧)之间提供一附加的延时。 [[File:160308qgb9sg27m3xvlsz9.png]] <b style="background-color: inherit;">1.数据帧</b> 数据帧由7个不同的域组成。 <b style="background-color: inherit;">(1)帧开始(Start of Frame)</b> 这个域表示数据帧的开始。仅由一个“显性”位组成. <b style="background-color: inherit;">(2)仲裁域(Arbitration Frame)</b> 这个域表示一个帧的优先级,仲裁场由标识符和远程发送请求位(RTR位)组成。RTR位在数据帧中为显性,在远程帧中为隐性。 IDE的全称是“识别符扩展位(Identifier Extension Bit)”,对于扩展格式,IDE位属于仲裁场;对于标准格式,IDE位属于控制场。标准格式的IDE位为“显性”,而扩展格式的IDE位为“隐性”。 <b style="background-color: inherit;">(3)控制域(Control Frame</b><b style="background-color: inherit;">)</b>: 这个域表示保留位和数据帧长度代码(DLC),控制场由6个位组成,标准格式和扩展格式的控制场格式不同。标准格式里的帧包括数据长度代码、IDE位及保留位r0。扩展格式里的帧包括数据长度代码和两个保留位:r1和r0。 <b style="background-color: inherit;">(4)数据域(Data Frame</b><b style="background-color: inherit;">)</b>: 这是数据内容,0~8个字节的数据能被发送,首先发送最高有效位。 <b style="background-color: inherit;">(5)CRC域(CRC Frame</b><b style="background-color: inherit;">)</b>: 这个域用于检查帧的传输错误。 <b style="background-color: inherit;">(6)ACK域(CRC Frame</b><b style="background-color: inherit;">)</b>: 是对帧已经被正常接收的一个证实。应答场长度为2个位,包含应答间隙(ACK Slot)和应答界定符(ACK Delimiter) <b style="background-color: inherit;">(7)帧结束(End of Frame</b><b style="background-color: inherit;">)</b>: 指示数据帧结束,这个标志序列由7个“隐性”位组成 [[File:160309cm5wk5kmb02b425w.png]] [[File:160310wlu2std35y2ttsjh.png]] <b style="background-color: inherit;">2.远程帧</b> <b style="background-color: inherit;"> </b> 作为接收器的节点,可以通过向相应的数据源节点发送远程帧激活该源节点,让该源节点把数据发送给接收器。而且都由6个不同的位场组成:帧起始、仲裁场、控制场、CRC场、应答场、帧结尾。与数据帧相反,远程帧的远程发送请求位(RTR)是“隐性”的。它没有数据场,数据长度代码DLC的数值可以是任意值。 [[File:160310v992yp526t6b8t8t.png]] <b style="background-color: inherit;">3.错误帧</b> <b style="background-color: inherit;"> </b> 错误帧由两个不同的场组成, (1) 错误标志 主动(Active)错误标志。它由6个连续显性位组成。 被动(Passive)错误标志。它由6个连续隐性位组成。 (2)错误界定:错误界定符由8个隐性位组成。 [[File:160311xypzmi9j6ss1ymop.png]] <b style="background-color: inherit;">4.帧间空间</b> <b style="background-color: inherit;"> </b> 帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。 过载帧和错误帧前不能插入帧间隔。 [[File:160311i0dg0t8jgjrtplp0.png]] <b style="background-color: inherit;">5.过载帧</b> <b style="background-color: inherit;"> </b> 过载帧是用于接收单元通知其尚未完成接收准备的帧。过载帧由过载标志和过载界定符构成。 (1) 过载标志 6个位的显性位。 过载标志的构成与主动错误标志的构成相同。 (2) 过载界定符 8个位的隐性位。 过载界定符的构成与错误界定符的构成相同。 [[File:160312s5va41unu3jidvuu.png]] <b style="background-color: inherit;">三. 波特率</b> <b style="background-color: inherit;"> </b> CAN控制器只需进行少量设置就可以进行通信,其中较难设置部分就是波特率计算。CAN总线的波特率是一个范围。假如波特率为250KB/s,实际波特率可能为200~300KB/s.这样使得CAN总线有很强大容错性。 CAN的底层协议里将CAN数据的每一位时间(TBit)分为许多时间段(Tscl),这些时间段包括: A. 同步段(SYNC_SEG):位变化应该在此时间段内发生。只有一个时间片的固定长度(1 x tq) B. 位段1(BS1):定义采样点的位置。其持续长度可以在 1 到 16 个时间片之间调整 C. 位段2(BS2):定义发送点的位置。其持续长度可以在 1 到 8 个时间片之间调整 D. 同步跳转宽度(SJW):定义位段加长或缩短的上限。它可以在 1 到 4 个时间片之间调整 [[File:160312l5kynr7yhdwprdym.png]] 这个结合STM32cubeMX软件设置讲解一下CAN的波特率设置。 [[File:160312bvvva2yypcyrryzp.png]] 上面设置分频为Prescaler=9, BS1=5, BS2=6, SJW=1 CAN外接是接到APB1上面,设置系统时钟为216MHz时,APB1外设时钟为54MHz. [[File:160313l3ak6of5orffjo3u.png]] 经过分频后的频率为54MHz / 9 =6MHz = ~ 166.666ns CAN波特率为 54MHz / 9 / (SJW+BS1 +BS2 ) = 54MHz /9 /12 = 500KHz = 2000ns <b style="background-color: inherit;">四. 标识符筛选</b> <b style="background-color: inherit;"> </b> 在CAN通信中接收到信息时,接收器节点会根据标识符的值来判断信息是否需要,若不需要则丢弃信息。 <b style="background-color: inherit;">五<b>. </b>新建工程</b> <b style="background-color: inherit;"> </b> 复制串口printf的工程,修改文件夹名。击STM32F746I.ioc打开STM32cubeMX的工程文件重新配置,开启CAN1,CAN2,管脚配置如下。 [[File:160313o2eseijsazoodera.png]] [[File:160313wvnanua0v6s9vnwg.png]] [[File:160314m5rx6ea2q2e884r5.png]] CAN1,CNA2只需配置时间参数,波特率为500KHz,其他为默认不作修改。 [[File:160314tbp7z5x56omeo5b6.png]] 生成报告以及代码,编译程序。在can.c文件中可以看到CAN初始化函数。在stm327xx_hal_can.h文件后面可以看到CAN操作函数。 在main.c文件前面添加变量,sFilterConfig为CAN滤波器结构体变量,TxMessage,RxMessage分别存储CAN发送和接收的消息。 <syntaxhighlight lang="python"> /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ CAN_FilterConfTypeDef sFilterConfig; static CanTxMsgTypeDef TxMessage; static CanRxMsgTypeDef RxMessage; /* USER CODE END PV */</syntaxhighlight> 在main函数中,初始化发送消息邮箱,设置为标准数据帧,数据长度为8个字节,数据为“CAN Test"。设置滤波器。 <syntaxhighlight lang="python"> /* USER CODE BEGIN 2 */ hcan2.pTxMsg = &TxMessage; hcan1.pRxMsg = &RxMessage; printf("**** This is CAN test program ****\r\n\r\n"); /*##-1- Configure CAN2 Transmission Massage #####################################*/ hcan2.pTxMsg->StdId = 0x123; hcan2.pTxMsg->RTR = CAN_RTR_DATA; hcan2.pTxMsg->IDE = CAN_ID_STD; hcan2.pTxMsg->DLC = 8; hcan2.pTxMsg->Data[0] = 'C'; hcan2.pTxMsg->Data[1] = 'A'; hcan2.pTxMsg->Data[2] = 'N'; hcan2.pTxMsg->Data[3] = ' '; hcan2.pTxMsg->Data[4] = 'T'; hcan2.pTxMsg->Data[5] = 'e'; hcan2.pTxMsg->Data[6] = 's'; hcan2.pTxMsg->Data[7] = 't'; /*##-2- Configure the CAN1 Filter ###########################################*/ sFilterConfig.FilterNumber = 0; sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterIdHigh = 0x0000; sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000; sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterFIFOAssignment = 0; sFilterConfig.FilterActivation = ENABLE; sFilterConfig.BankNumber = 14; HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig); /* USER CODE END 2 */</syntaxhighlight> <syntaxhighlight lang="python"> </syntaxhighlight> 在while循环中添加应用程序,CAN2发送信息给CAN1接收,正确接收到信息后打印输出。 <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ /*##-3- Start the CAN2 Transmission process #####################################*/ if(HAL_CAN_Transmit(&hcan2, 10) != HAL_OK) { /* Transmition Error */ Error_Handler(); } if(HAL_CAN_GetState(&hcan2) != HAL_CAN_STATE_READY) { Error_Handler(); } /*##-4- Start the CAN1 Reception process ########################################*/ if(HAL_CAN_Receive(&hcan1, CAN_FIFO0,10) != HAL_OK) { /* Reception Error */ Error_Handler(); } if(HAL_CAN_GetState(&hcan1) != HAL_CAN_STATE_READY) { Error_Handler(); } printf("StdId : %x\r\n",hcan1.pRxMsg->StdId); printf("RxMsg : %s",hcan1.pRxMsg->Data); printf("\r\n\r\n"); HAL_Delay(1000); } /* USER CODE END 3 */</syntaxhighlight> </syntaxhighlight> <syntaxhighlight lang="python"> </syntaxhighlight> 编译程序并下载到开发板。将两个 SN65HVD230 CAN Board模块分别连接到板上的 CAN1 和 CAN2 接口。 用杜邦线连接两个 CAN 模块(CANL -> CANL, CANH -> CANH)。打开串口调试助手,设置波特率为115200,按下复位串口助手上面会显示如下信息。 [[File:160314kwwhq5whxxqnqm2u.png]]
返回至
STM32CubeMX系列教程12:控制器局域网络(CAN)
。
导航
导航
首页
最近更改
随机页面
MediaWiki帮助
首页
首页
树莓派
主机
配件包
外壳
键鼠
电源
扩展板
显示屏
墨水屏
摄像模块
通信模块
继电器
电机驱动板
游戏机
产品分类
树莓派
Arduino
micro:bit
STM32
Espressif
WiFi模块
蓝牙模块
无线模块
LoRa模块
4G模块
GSM
GPRS
以太网
导航模块
北斗卫星
GPS
LCD
墨水屏
OLED
摄像头
USB模块
串口模块
RS232
RS485
CAN
传感器
温度模块
湿度模块
气压模块
继电器
电机模块
指纹模块
电平转换
音频模块
编程器
Wiki工具
Wiki工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志