STM32的can总线实验心得

合集下载

《STM32开发指南》第三十章 CAN通信实验介绍

《STM32开发指南》第三十章 CAN通信实验介绍
ALIENTEK 战舰STM32开发板
第三十章 CAN 通讯实验
本章我们将向大家介绍如何使用 STM32 自带的 CAN 控制器来实现两个开发板之间的 CAN 通讯,并将结果显示在 TFTLCD 模块上。本章分为如下几个部分: 30.1 CAN 简介 30.2 硬件设计 30.3 软件设计 30.4 下载验证
www.Biblioteka
343
ALIENTEK 战舰STM32开发板
图 30.1.1 ISO11898 物理层特性 从该特性可以看出,显性电平对应逻辑 0,CAN_H 和 CAN_L 之差为 2.5V 左右。而隐性 电平对应逻辑 1,CAN_H 和 CAN_L 之差为 0V。在总线上显性电平具有优先权,只要有一个 单元输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都 输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强) 。另外,在 CAN 总线的起止 端都有一个 120Ω的终端电阻,来做阻抗匹配,以减少回波反射。 CAN 协议是通过以下 5 种类型的帧进行的: 数据帧 要控帧 错误帧 过载帧 帧间隔 另外,数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有 11 个位的标识符 (ID) ,扩展格式有 29 个位的 ID。各种帧的用途如表 30.1.1 所示:

344
ALIENTEK 战舰STM32开发板
(6) ACK 段。表示确认正常接收的段。 (7) 帧结束。表示数据帧结束的段。 数据帧的构成如图 30.1.2 所示:

342
ALIENTEK 战舰STM32开发板
30.1 CAN 简介
CAN 是 Controller Area Network 的缩写(以下称为 CAN) ,是 ISO 国际标准化的串行通信 协议。在当前的汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种 各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求 不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量” 、 “通过多个 LAN,进行大量数据的高速通信”的需要,1986 年德国电气商博世公司开发出面 向汽车的 CAN 通信协议。此后,CAN 通过 ISO11898 及 ISO11519 进行了标准化,现在在欧 洲已是汽车网络的标准协议。 现在,CAN 的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设 备、工业设备等方面。现场总线是当今自动化领域技术发展的热点之一,被誉为自动化领域的 计算机局域网。它的出现为分布式控制系统实现各节点之间实时、可靠的数据通信提供了强有 力的技术支持。 CAN 控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平和隐性电平, 二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。 CAN 协议具有一下特点: 1) 多主控制。在总线空闲时,所有单元都可以发送消息(多主控制) ,而两个以上的单元 同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。ID 并不是 表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始 发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级 最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。 2) 系统的若软性。与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单 元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。 3) 通信速度较快,通信距离远。最高 1Mbps(距离小于 40M) ,最远可达 10KM(速率低 于 5Kbps) 。 4) 具有错误检测、 错误通知和错误恢复功能。 所有单元都可以检测错误 (错误检测功能) , 检测出错误的单元会立即同时通知其他所有单元(错误通知功能) ,正在发送消息的单 元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新 发送此消息直到成功发送为止(错误恢复功能) 。 5) 故障封闭功能。 CAN 可以判断出错误的类型是总线上暂时的数据错误 (如外部噪声等) 还是持续的数据错误(如单元内部故障、驱动器故障、断线等) 。由此功能,当总线上 发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。 6) 连接节点多。CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没 有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通 信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。 正是因为 CAN 协议的这些特点,使得 CAN 特别适合工业过程监控设备的互连,因此,越 来越受到工业界的重视,并已公认为最有前途的现场总线之一。 CAN 协议经过 ISO 标准化后有两个标准: ISO11898 标准和 ISO11519-2 标准。 其中 ISO11898 是针对通信速率为 125Kbps~1Mbps 的高速通信标准, 而 ISO11519-2 是针对通信速率为 125Kbps 以下的低速通信标准。 本章,我们使用的是 450Kbps 的通信速率,使用的是 ISO11898 标准,该标准的物理层特 征如图 30.1.1 所示:

基于STM32的CAN总线通信设计

基于STM32的CAN总线通信设计

基于STM32的CAN总线通信设计近年来,CAN(Controller Area Network)总线通信在汽车电子控制系统和工业领域得到了广泛应用。

作为一种高可靠性、高实时性的通信协议,CAN总线能够实现多节点之间的高效数据传输。

STM32系列微控制器作为嵌入式系统设计领域的重要成员,具备强大的处理能力和丰富的外设资源,被广泛用于CAN总线通信的设计和应用。

本文将介绍,包括硬件设计和软件编程两个方面。

首先,我们将讨论如何选择合适的STM32微控制器和CAN收发器。

其次,我们将详细描述硬件连接和接口电路设计。

最后,我们将介绍CAN总线通信软件的编程方法和实现。

在硬件设计方面,选择合适的STM32微控制器和CAN收发器是至关重要的。

STM32系列微控制器具备不同的处理能力和资源配置,应根据具体应用需求来选择。

CAN收发器是将STM32与CAN总线连接的重要部件,需要根据通信速率和总线特性选择合适的收发器。

在硬件连接和接口电路设计方面,需要参考STM32的引脚分配和电气特性,正确连接CAN收发器和其他外设。

同时,还需要考虑如何提供稳定的电源和适当的信号滤波电路,以保证CAN总线通信的可靠性和稳定性。

在软件编程方面,首先,需要在STM32的开发环境中配置CAN总线通信所需的外设和时钟。

然后,根据具体需求设置CAN总线的通信速率、帧格式和过滤器等参数。

接下来,编写CAN总线发送和接收数据的代码。

在发送数据时,需要将数据打包成CAN帧的格式,并将其发送到CAN总线;在接收数据时,需要监听CAN总线上的数据帧,并将接收到的数据解码处理。

此外,为了提高CAN总线通信的可靠性,还可以加入错误检测和纠错代码。

在实际应用中,广泛应用于汽车电子控制系统和工业自动化领域。

在汽车电子控制系统中,CAN总线通信可以实现各个控制单元之间的数据交换和协调工作,提高整车系统的性能和安全性。

例如,发动机控制单元、制动系统控制单元和防抱死系统控制单元可以通过CAN总线通信实现数据的快速传输和实时响应。

基于STM32的CAN总线通信设计_亢雪琳

基于STM32的CAN总线通信设计_亢雪琳
CAN—Controller Area Network is a multi-master network which created by BOSCH.Cause it satisfied high requirements of the system on the flexibility and reliability,it quickly becomes the most promising bus in public.First CAN was created to solve the data exchange problem between controllers and test instruments.CAN has many masters ,provides the possibility that each node communicate with others as a host .Communication medium can be twisted pair,coaxial cable and optical fiber.
控制器局域网(CAN—Controller Area Network)是由 BOSCH 公司率先推出的一 种多主机局域网,它成功的满足了系统对灵活性和可靠性的高要求,迅速成为公认的 最具前途的现场总线之一。起初,汽车中多个控制器和测试仪器间的数据交换越来越 复杂,引发了对一种多主机数据总线的需求,该总线要能很好的满足控制器间数据交 换的要求,让每个节点都可以作为主机通信,CAN 总线技术因此发展起来。CAN 总线 的通信介质可以是双绞线、同轴电缆或光导纤维[4]。CAN 总线技术摒弃了传统的站地 址编码,通信速率可达 1Mb/s。通过对数据块的编码使网络内节点数理论上不受限。 CAN 协议所具有的 CRC 检验功能保证了数据通信的可靠性。数据段长度最多为 8 个字 节,在保证了控制命令等长度要求又不占用过长的总线时间,系统通信的实时性能提 高。CAN 协议所具有的位仲裁机制可以保证实现总线分配时,避免两个站在同时发送数 据时所形成的冲突碰撞。

stm32地can现场总线实验

stm32地can现场总线实验

STM32的can现场总线实验心得最近在搞stm32实验板的can现场总线实验,之前只是搞过STC51的串口通信,相比之下,发觉can总线都挺复杂的。

开始时,知道自己是新手,只知道can总线跟串行通信,485通信,I2C通信一样都是用来传输数据通信的,对其工作原理一窍不通,还是从基础开始看书看资料,先了解它的基本原理吧。

原来can总线有以下特点:主要特点支持CAN协议2.0A和2.0B主动模式波特率最高可达1兆位/秒支持时间触发通信功能发送3个发送邮箱发送报文的优先级特性可软件配置记录发送SOF时刻的时间戳接收3级深度的2个接收FIFO14个位宽可变的过滤器组-由整个CAN共享标识符列表FIFO溢出处理方式可配置记录接收SOF时刻的时间戳可支持时间触发通信模式禁止自动重传模式16位自由运行定时器定时器分辨率可配置可在最后2个数据字节发送时间戳管理中断可屏蔽邮箱占用单独1块地址空间,便于提高软件效率看完这些特点后,疑问一个一个地出现,1.什么是时间触发功能?2.发送邮箱是什么来的?3.报文是什么来的?4.什么叫时间戳?5.什么叫接收FIFO?6.什么叫过滤器?好了,带着疑问往下看,看完一遍后,报文:报文包含了将要发送的完整的数据信息发送邮箱:共有3个发送邮箱供软件来发送报文。

发送调度器根据优先级决定哪个邮箱的报文先被发送。

接收过滤器:共有14个位宽可变/可配置的标识符过滤器组,软件通过对它们编程,从而在引脚收到的报文中选择它需要的报文,而把其它报文丢弃掉。

接收FIFO共有2个接收FIFO,每个FIFO都可以存放3个完整的报文。

它们完全由硬件来管理工作模式bxCAN有3个主要的工作模式:初始化、正常和睡眠模式。

初始化模式*软件通过对CAN_MCR寄存器的INRQ位置1,来请求bxCAN进入初始化模式,然后等待硬件对CAN_MSR寄存器的INAK位置1来进行确认*软件通过对CAN_MCR寄存器的INRQ位清0,来请求bxCAN退出初始化模式,当硬件对CAN_MSR寄存器的INAK位清0就确认了初始化模式的退出。

STM32的can总线实验心得

STM32的can总线实验心得

STM32的can总线实验心得(一) 工业现场总线 CAN 的基本介绍以及 STM32 的 CAN 模块简介首先通读手册中关于CAN的文档,必须精读。

STM32F10xxx 参考手册Rev7V3.pdf/bbs/redirect.php?tid=255&goto=lastpost#lastpos t需要精读的部分为 RCC 和 CAN 两个章节。

为什么需要精读 RCC 呢?因为我们将学习 CAN 的波特率的设置,将要使用到RCC 部分的设置,因此推荐大家先复习下这部分中的几个时钟。

关于 STM32 的 can 总线简单介绍bxCAN 是基本扩展 CAN (Basic Extended CAN) 的缩写,它支持 CAN 协议 2.0A 和 2.0B 。

它的设计目标是,以最小的 CPU 负荷来高效处理大量收到的报文。

它也支持报文发送的优先级要求(优先级特性可软件配置)。

对于安全紧要的应用,bxCAN 提供所有支持时间触发通信模式所需的硬件功能。

主要特点· 支持 CAN 协议 2.0A 和 2.0B 主动模式· 波特率最高可达 1 兆位 / 秒· 支持时间触发通信功能发送· 3 个发送邮箱· 发送报文的优先级特性可软件配置· 记录发送 SOF 时刻的时间戳接收· 3 级深度的2个接收 FIFO· 14 个位宽可变的过滤器组-由整个 CAN 共享· 标识符列表· FIFO 溢出处理方式可配置· 记录接收 SOF 时刻的时间戳可支持时间触发通信模式· 禁止自动重传模式· 16 位自由运行定时器· 定时器分辨率可配置· 可在最后 2 个数据字节发送时间戳管理· 中断可屏蔽· 邮箱占用单独 1 块地址空间,便于提高软件效率(二) STM32 CAN 模块工作模式STM32 的 can 的工作模式分为:/* CAN operating mode */#define CAN_Mode_Normal ((u8)0x00) /* normal mode */#define CAN_Mode_LoopBack ((u8)0x01) /* loopback mode */#define CAN_Mode_Silent ((u8)0x02) /* silent mode */#define CAN_Mode_Silent_LoopBack ((u8)0x03) /* loopback combined with silent mode */在此章我们的 Mini-STM32 教程中我们将使用到CAN_Mode_LoopBack和CAN_Mode_Normal两种模式。

stm32F4 CAN总线学习

stm32F4 CAN总线学习

STM32F4 CAN学习记录1.C AN协议学习CAN基础1.CAN属于多主机局部网,采用多主竞争式总线结构,具有多主站运行和分散仲裁的串行总线以及广播通信的特点,各节点之间可以实现自由通信。

2.CAN总线以报文为单位进行数据传送,报文的优先级由标识符决定,具有最低二进制数的标识符有最高的优先级。

3.CAN总线采用差分电压传输;在空闲状态下CAN_H和CAN_L均为2.5V左右,此时的状态表示为逻辑“1”,称为“隐性”电平(差值为"0v");当CAN_H比CAN_L高时表示逻辑“0”,称为“显性”电平(差值为"2v")。

显性时,通常电压值为:CAN_H=3.5V,CAN_L=1.5V。

4.CAN总线采用“载波监测,多主掌控/冲突避免”(CSMA/CA)的通信模式。

该模式工作流程大致如下:●当总线处于空闲状态时(呈隐性电平),任何节点都可以向总线发送显性电平作为帧开始。

●当网络中存在2个及以上节点同时要求发送时就会产生竞争。

CAN总线按位对标识符进行仲裁;各节点在发送电平的同时也在监听总线,如果总线电平与发送电平不同,则表明总线上存在更高优先级的节点在发送,则节点停止发送退出竞争。

其他节点继续上述过程直到剩余1个节点,则最终优先级最高节点获得总线控制权并发送数据。

●参与总线仲裁的只有仲裁段;基础ID相同的标准can报文比扩展can报文优先级更高;相同ID的数据帧与远程帧,数据帧优先级更高。

CAN报文结构CAN分为标准格式(CAN2.0A)和扩展格式(CAN2.0B);标准帧采用11位标识符ID,共可表示2047条报文;扩展帧采用29位标识符ID,共可表示5亿多条报文。

CAN总线上传输的数据帧共有4种类型:数据帧、远程帧、错误帧、过载帧。

每一帧都由多个场构成,每个场也都由多个位组成。

下面分别描述着几种帧结构。

1)数据帧:用于传输数据数据帧由7个不同的位场组成:帧起始、仲裁场、控制场、数据场、CRC场、应答场、帧结尾。

STM32CAN发送接收的简单测试

STM32CAN发送接收的简单测试

STM32CAN发送接收的简单测试can接⼝相对是⼀种常⽤的串⾏接⼝,但是不像spi、i2c、uart等接⼝都有主从的关系,can可以任何⼀个节点主动发送数据,并且假如出现总线冲突会有硬件来处理。

can和rs485⼜有些类似,都是把ttl信号转换成了差分信号。

所以在stm32 使⽤can的时候会有⼀个can收发器。

STM32 CAN 发送的简单测试从电路上看起来也很简单,stm32也是通过can tx、rx两根线和收发器相连。

所以假如我们要测试can的发送,是不是只接can tx脚就可以了?我最开始也以为这样就可以,但是深究can的总线冲突检测原理就会发现这样⾏不通的。

因为can 在发送数据的时候也会同时接收发送的数据,通过把接收的数据和内部发送寄存器的数据做对⽐,是不是⼀致就知道总线有没有冲突。

所以在正常情况(这⾥意味着⾮正常情况下也可以)下can rx不接就到这发送出去的数据⽆法收到从⽽硬件⾃动判断为发送失败。

所以要保证发送数据成功,can tx脚和can rx脚要都接上,并且确保can收发器供电正常。

硬件上就这些主要注意点,接下来就主要是软件的配置了。

⼀般stm32 配置can有以下⼏⼤步骤:can的初始化(cubemx直接可以⽣成代码)can的启动can滤波器的设置(⽤来接收的,发送的时候可以不⽤配置它)can执⾏发送数据请求我们只测试can的发送,所以就只⽤关系1、2、4步骤就可以了。

第⼀步,配置stm32cubemxSTM32 CAN 发送的简单测试如上图所⽰,最关键主要配置如下三个参数,分频数我这⾥配置48,下⾯的time Quantum值就会⾃动计算出来。

因为can时钟是48mhz经过48分频后,⼀个单位时间就是1us=1000ns。

因为我想要100k波特率,然后填写下⾯的Time segment1(简称 Tbs1 )和Time segment2 (简称 Tbs2) 为5和4。

那么具体波特率该怎么计算还是要看看官⽅⼿册的描述:STM32 CAN 发送的简单测试根据如上描述,能决定波特率的也就是三个参数:分频值、Tbs1、Tbs2。

STM32_CAN_Bus调试心得

STM32_CAN_Bus调试心得

睡眠模式(低功耗)
*软件通过对CAN_MCR 寄存器的SLEEP位置 1,来请求进入这一模式。在该 模式下,bxCAN 的时钟停止了,但软件仍然可以访问邮箱寄存器。 *当bxCAN 处于睡眠模式,软件想通过对CAN_MCR 寄存器的INRQ位置 1, 来进入初始化式, 那么软件必须同时对SLEEP位清 0才行 *有2种方式可以唤醒(退出睡眠模式)bxCAN :通过软件对SLEEP位清0,
第 4 页 共 11 页
GZHU
Electronic Association
或硬件检测 CAN 总线的活动。 工作流程 那么究竟can是怎样发送报文的呢? 发送报文的流程为: 应用程序选择1个空发送邮箱;设置标识符,数据长度和待发送数据; 然后对CAN_TIxR 寄存器的 TXRQ位置 1,来请求发送。TXRQ位置 1后,邮箱 就不再是空邮箱;而一旦邮箱不再为空,软件对邮箱寄存器就不再有写的权 限。 TXRQ位置 1后, 邮箱马上进入挂号状态, 并等待成为最高优先级的邮箱, 参见发送优先级。一旦邮箱成为最高优先级的邮箱,其状态就变为预定发送 状态。 一旦 CAN总线进入空闲状态, 预定发送邮箱中的报文就马上被发送 (进 入发送状态)。一旦邮箱中的报文被成功发送后,它马上变为空邮箱;硬件 相应地对CAN_TSR 寄存器的RQCP和 TXOK位置1,来表明一次成功发送。 如果发送失败,由于仲裁引起的就对CAN_TSR 寄存器的ALST位置1,由于 发送错误引起的 就对 TERR位置 1。 原来发送的优先级可以由标识符和发送请求次序决定: 由标识符决定 当有超过1个发送邮箱在挂号时,发送顺序由邮箱中报文的标识符决定。根 据CAN 协议,标 识符数值最低的报文具有最高的优先级。如果标识符的值相等,那么邮箱号 小的报文先被发 送。 由发送请求次序决定 通过对CAN_MCR 寄存器的TXFP位置 1,可以把发送邮箱配置为发送 FIFO 。 在该模式下,发送的优先级由发送请求次序决定。 该模式对分段发送很有用。 时间触发通信模式 在该模式下,CAN 硬件的内部定时器被激活,并且被用于产生时间戳,分别 存储在 CAN_RDTxR/CAN_TDTxR 寄存器中。内部定时器在接收和发送的帧起始位 的采样点位置被采样,并生成时间戳(标有时间的数据)。 接着又是怎样接收报文的呢? 接收管理 接收到的报文,被存储在 3级邮箱深度的FIFO 中。 FIFO 完全由硬件来管理, 从而节省了 CPU 的处理负荷,简化了软件并保证了数据的一致性。应用程序只能通过读取 FIFO 输出邮箱,来读取 FIFO中最先收到的报文。 有效报文 根据 CAN协议,当报文被正确接收(直到 EOF域的最后 1位都没有错误), 且通过了标识符 过滤,那么该报文被认为是有效报文。

基于STM32的CAN总线接口设计与实现

基于STM32的CAN总线接口设计与实现

图1 系统总体框图是一款带隔离的高速CAN收发器芯片,该芯片内部集成了所有必需的CAN隔离及CAN收发器件。

芯片的主要功能是将CAN控制器的逻辑电平转换为CAN总线的差分电平,并且具有DC 2500V的隔离功能及ESD保护作用,其是CAN收发器的理想选择[2]。

2 CAN总线收发模块的硬件设计CAN总线收发模块的硬件结构如图2所示。

CAN总线(1978-),男,江西宜春人,研究生,工程师。

研究方向:汽车电子项目管理。

公飞(1989-),男,山东临沂人,本科,助理工程师。

研究方向:汽车电子硬件设计。

收发模块的主要功能是控制开关和与RS232进行数据通信,开关可以用来控制现场设备的运行,后者可以方便与外界进行通信,提供通讯接口。

其硬件结构节点可以划分为最小系统模块、功能模块。

电源STM32的工作电压(VDD)为2.0~3.6V[3]。

通过内置的电压调节器提供所需的1.8V电源。

当主电源VDD掉电后,通过VBAT脚为实时时钟(RTC)和备份寄存器提供电源。

使用电池或其他电源连接到VBAT脚上,当VDD断电时,可以保存备份寄存器的内容和维持RTC的功能。

VBAT脚也图3 设置时钟流程图2.2 开关和RS232功能模块该节点具有两个功能,控制开关状态和与RS232通讯,开关选用八个TX2-5V继电器,两片MC1413作为驱动芯片,MC1413可以实现单片机端口电压到12V电平的转换。

与RS232通讯部分选用MAX232做为电平转换芯片。

2.3 CAN收发模块CAN收发模块主要是CAN收发器,CAN收发器的常用型号有CTM1050,CTM1050是一款带隔离的高速CAN收发器芯片,该芯片内部集成了所有必需的CAN隔离及CAN发器件。

芯片的主要功能是将CAN控制器的逻辑电平转换为CAN总线的差分电平,并且具有DC 2500V的隔离功能及ESD保护作用。

该芯片符合ISO 11898标准,因此,它可以和图2 节点硬件结构图图4 CAN初始化流程图选用的测试模式是环回模式,该模式下数据是自发自收的,即在发送成功的同时就接收到数据了。

基于STM32的CAN总线上下位机通信实验设计

基于STM32的CAN总线上下位机通信实验设计

基于STM32的CAN总线上下位机通信实验设计作者:刘泰廷李新建来源:《电脑知识与技术》2017年第05期摘要:随着技术的成熟和设备的完善,CAN总线在数据的实时传输和自动控制中展现出良好的灵活性与可靠性。

笔者以STM32为主控芯片搭建硬件电路,利用软件对其进行初始化设置,上位机与电路的连接使用USB—CAN转换器,并采用Visual C++的MFC编写的CAN 调试界面实现数据的实时收发,使上下位机完成通信。

本实验对于CAN总线的使用有一定的指导作用。

关键词:STM32;CAN总线;MFC;通信中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)05-0199-02CAN简称为控制器局域网络(Controller Area Network),它是由研发和生产汽车电子产品著称的德国BOSCH公司开发的,是国际上应用最广泛的现场总线之一,并最终成为国际标准(ISO11519)。

近年来,由于它的高可靠性和良好的错误检测能力受到人们的关注,CAN 总线协议逐渐成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,被广泛应用于汽车控制系统和环境温度恶劣、电磁辐射强的工业环境。

1 实验系统结构组成利用CAN总线可以将传统分布式控制系统的功能分散到不同的现场节点中,本实验只选用一个节点作为下位机的收发模块。

实验的系统框图如图1所示,系统主要分为三个部分:上位机(PC机)、CAN转换器、下位机(CAN收发模块电路)。

一般调试员的PC机(多为笔记本电脑)接入CAN总线往往没有串行接口,为此我们采用USB—CAN协议的转换器接入CAN总线,实现数据之间的转发。

下位机是以STM32F103RCT6单片机作为主控芯片的CAN 收发电路,主要完成数据采集和处理的任务,并实现与CAN总线的数据互传。

上位机利用MFC编写的控制界面,对CAN总线上收到的数据进行显示,同时也可以完成向CAN总线发送数据的指令。

stm32实训总结

stm32实训总结

实践形式: √校内实践基地实践□校外实践基地□导师联系校外实践□自行联系校外实践□ 其他______________起止日期:2015.12.14-2015.12.25实践总结(要求写明实践地点、实践时间、指导教师、实践目的、实践内容和完成情况,字数及其它具体要求由各学院根据学科情况自行制定。

)实践地点实践目的1. 利用所学过的基础知识,通过本次电子实习培养独立解决实际问题的能力。

2. 巩固本课程所学习的理论知识和实验技能。

3. 了解循迹小车构成的设计方法。

4. 掌握常用电子电路的一般设计方法,提高设计能力和实验、动手能力,为今后从事电子电路的设计、研制电子产品打下基础。

5. 培养团队的协作和沟通能力。

实践内容:一、智能小车配置本次实训中所用到的智能小车如图1所示,其主要配置包括:图1 智能小车1、小车底盘小车底盘是机器人最重要的载体,相当于人体的驱干,ZK-4WD小车平台采用差速转弯非常灵活可以实现原地打转。

小车平台大小刚好可以承载一些如驱动器控制器、控制器、电池、传感器等。

图2 小车底盘2、驱动器小车直流电机工作电流一般是200-400MA,有些更大,如果一个小车是二个轮子,那么总的电流在400-800MA左右,这些电机轮子都是要接受单片机指令执行相应的动作,而市面有的单片机IO 口一般只能提供5MA到10MA的电流,直接驱动不了电机,所以需要一个驱动模块,放大电流。

驱动采用专业的L298N驱动芯片。

图3 L298N驱动芯片3、控制器图4为控制器STM32核心板,STM32平台采用核心板+外围板方式。

核心板主要包括STM32F103VET6最小系统、按键、LED灯、TF卡、串口和JTAG电路。

可以完成STM32内部资源的大部分开发应用。

外围板包括数码管电路、存储器电路、红外、光敏电阻、温度传感器、ULN2003电路、步进电机、蜂鸣器、DS1302时钟电路和CAN总线等电路设计,基本包括了STM32的所有资源、同时又对IIC、单总线、SPI 总线、CAN总线等协议进行了硬件设计。

stm32实训心得体会

stm32实训心得体会

stm32实训心得体会篇一:STM32 实验2报告实验2MINI STM32按键控制LED灯实验一、实验目的1、掌握嵌入式程序设计流程。

2、熟悉STM32固件库的基本使用。

二、实验内容1、编程使用I/O口作为输入,控制板载的两个LED 灯。

2、使用固件库编程。

三、实验设备硬件: PC机一台MINI STM32开发板一套软件: RVMDK 一套Windows XP 一套四、实验步骤1、设计工程,使用固件库来编程设置。

、在这里我们建立一个文件夹为: STM32-Projects.点击Keil 的菜单:Project –>New Uvision Project ,然后将目录定位到刚才建立的文件夹STM32-Projecst 之下,在这个目录下面建立子文件夹shiyan1, 然后定位到 shiyan1目录下面,我们的工程文件就都保存到shiyan1 文件夹下面。

工程命名为shiyan1, 点击保存.是这个型号。

、这里我们定位到STMicroelectronics 下面的STM32F103RB ,然后点击Add ,然后Close.、用同样的方法,将 Groups 定位到CORE 和USER 下面,添加需要的文件。

这里我们的CORE 下面需要添加的文件为core_ ,startup_stm32f10x_ ,USER 目录下面需要添加的文件为,stm32f10x_,system_ 这样我们需要添加的文件已经添加到我们的工程中去了,最后点击 OK,回到工程主界面、下面我们要告诉 MDK,在哪些路径之下搜索相应的文件。

回到工程主菜单,点击魔术棒,出来一个菜单,然后点击 c/c++ 选项. 然后点击 Include Paths 右边的按钮。

弹出一个添加path 的对话框,然后我们将图上面的 3 个目录添加进去。

记住,keil 只会在一级目录查找,所以如果你的目录下面还有子目录,记得path 一定要定位到最后一级子目录。

STM32系列单片机CAN现场总线调试笔记

STM32系列单片机CAN现场总线调试笔记

STM32的can现场总线实验心得最近在搞stm32实验板的can现场总线实验,之前只是搞过STC51的串口通信,相比之下,发觉can总线都挺复杂的。

开始时,知道自己是新手,只知道can总线跟串行通信,485通信,I2C通信一样都是用来传输数据通信的,对其工作原理一窍不通,还是从基础开始看书看资料,先了解它的基本原理吧。

原来can总线有以下特点:主要特点支持CAN协议2.0A和2.0B主动模式波特率最高可达1兆位/秒支持时间触发通信功能发送3个发送邮箱发送报文的优先级特性可软件配置记录发送SOF时刻的时间戳接收3级深度的2个接收FIFO14个位宽可变的过滤器组-由整个CAN共享标识符列表FIFO溢出处理方式可配置记录接收SOF时刻的时间戳可支持时间触发通信模式禁止自动重传模式16位自由运行定时器定时器分辨率可配置可在最后2个数据字节发送时间戳管理中断可屏蔽邮箱占用单独1块地址空间,便于提高软件效率看完这些特点后,疑问一个一个地出现,1.什么是时间触发功能?2.发送邮箱是什么来的?3.报文是什么来的?4.什么叫时间戳?5.什么叫接收FIFO?6.什么叫过滤器?好了,带着疑问往下看,看完一遍后,报文:报文包含了将要发送的完整的数据信息发送邮箱:共有3个发送邮箱供软件来发送报文。

发送调度器根据优先级决定哪个邮箱的报文先被发送。

接收过滤器:共有14个位宽可变/可配置的标识符过滤器组,软件通过对它们编程,从而在引脚收到的报文中选择它需要的报文,而把其它报文丢弃掉。

接收FIFO共有2个接收FIFO,每个FIFO都可以存放3个完整的报文。

它们完全由硬件来管理工作模式bxCAN有3个主要的工作模式:初始化、正常和睡眠模式。

初始化模式*软件通过对CAN_MCR寄存器的INRQ位置1,来请求bxCAN进入初始化模式,然后等待硬件对CAN_MSR寄存器的INAK位置1来进行确认*软件通过对CAN_MCR寄存器的INRQ位清0,来请求bxCAN退出初始化模式,当硬件对CAN_MSR寄存器的INAK位清0就确认了初始化模式的退出。

基于STM32的CAN通讯,已在实际项目中应用

基于STM32的CAN通讯,已在实际项目中应用

与本程序代码相关部分的原理图及PCB,基于STM32F103VET6,已在项目中应用。

开头篇:STM32的CAN波特率计算STM32里的CAN 支持2.0A,2.0B, 带有FIFO,中断等, 这里主要提一下内部的时钟应用。

bxCAN挂接在APB1总线上,采用总线时钟,所以我们需要知道APB1的总线时钟是多少。

我们先看看下图,看看APB1总线时钟:APB1时钟取自AHB的分频, 而AHB又取自系统时钟的分频, 系统时钟可选HSI,HSE, PLLCLK, 这个在例程的RC设置里都有的,然后再看看有了APB1的时钟后,如何算CAN的总线速率, 先看下图:有了上边的这个图,基本就清楚了:总线时钟MHz (3+TS1+TS2)*(BRP+1)======================================================================下面是我的计算:CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;注意//#define CAN_BS1_3tq ((uint8_t)0x02) /*!< 3 time quantum */ CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;CAN_InitStructure.CAN_Prescaler = 4;//2nominal bit time(3+5+1)tq=9tq关于分频系数,查看 system_stm32f10x.c下面的static void SetSysClockTo72(void) 函数:/* HCLK = SYSCLK *//* PCLK2 = HCLK *//* PCLK1 = HCLK/2 */所以can时钟 72MHZ/2/4=9 Mhz,tq=1/36Mhz波特率为 1/nominal bit time= 9/9=1MHZ=====================================================================void CAN_Configuration(void){CAN_InitTypeDef CAN_InitStructure;CAN_FilterInitTypeDef CAN_FilterInitStructure;/* CAN register init */CAN_DeInit();CAN_StructInit(&CAN_InitStructure);/* CAN cell init */CAN_InitStructure.CAN_TTCM=DISABLE;CAN_InitStructure.CAN_ABOM=DISABLE;CAN_InitStructure.CAN_AWUM=DISABLE;CAN_InitStructure.CAN_NART=DISABLE;CAN_InitStructure.CAN_RFLM=DISABLE;CAN_InitStructure.CAN_TXFP=DISABLE;CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;CAN_InitStructure.CAN_BS1=CAN_BS1_9tq;CAN_InitStructure.CAN_BS2=CAN_BS2_8tq;CAN_InitStructure.CAN_Prescaler=200;CAN_Init(&CAN_InitStructure);/* CAN filter init */CAN_FilterInitStructure.CAN_FilterNumber=0;CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;CAN_FilterInit(&CAN_FilterInitStructure);}注意//#define CAN_BS1_3tq ((uint8_t)0x02) /*!< 3 time quantum */波特率10K,公式:72MHZ/2/200/(1+9+8)=0.01,即10Kbps正文篇:程序代码/* Includes ---------------------------------- --------------------------------*/#include "stm32f10x.h"#include "platform_config.h"#include "stm32f10x_rcc.h"#include "stm32f10x_flash.h"#include "stm32f10x_usart.h"#include "stm32f10x_gpio.h"#include "stm32f10x_tim.h"#include "stdio.h"ErrorStatus HSEStartUpStatus;void Uart1_PutChar(u8 ch);unsigned int j; //j=2-8/* Private typedef -----------------------------------------------------------*/ typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus; //状态量__IO uint32_t ret = 0; //用于中断返回的传递变量volatile TestStatus TestRx;CanTxMsg TxMessage;CanRxMsg RxMessage;unsigned char read_temp;unsigned char open_temp,stop_temp,top_temp;uint16_t CCR1_Val=0 ;#define start 50#define accelerate 10#define Period 999#define Prescaler 9//double percent=0.9;vu32 counter=0;vu32 compare ;uint16_t High_fre=900;unsigned int Tulun_i=0; //500次作为一个脉冲GPIO_InitTypeDef GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;//Private functions 函数---------------------------------------------------------*/void UART_Init(void);ErrorStatus HSEStartUpStatus;void RCC_Configuration(void); //申明时钟初始化函数void GPIO_Configuration(void); //申明IO初始化函数void NVIC_Configuration(void); //申明中断管理器初始化函数void CAN_Configuration(void); //申明CAN初始化函数void CAN_TX(unsigned char add,unsigned char data1,unsigned char data2);//申明CAN发送函数TestStatus CAN_RX(void); //申明带返回参数的CAN接收函数void LED_RESET(void);void PWM_startN(void);void PWM_start(void);/****** Main program ***********/int main(void){u32 n;/* 系统时钟初始化 */RCC_Configuration();/* 中断管理器初始化 */NVIC_Configuration();/* IO初始化*/GPIO_Configuration();UART_Init(); //初始化串口函数/* CAN初始化*/CAN_Configuration();TIM_TimeBaseStructure.TIM_Period = Period;TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;TIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);GPIO_ResetBits(GPIOA, GPIO_Pin_4);while (1){CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //开接收中断for(n=0;n<10000;n++); //延时if(ret == 1){for(j=0;j<8;j++) //发送8组数据到串口 {Uart1_PutChar(RxMessage.Data[j]);}open_temp=RxMessage.Data[0];top_temp=RxMessage.Data[1];stop_temp= RxMessage.Data[2];switch(open_temp){case 01:PWM_start(); break;case 02:PWM_startN();break;default: GPIO_ResetBits(GPIOA, GPIO_Pin_2);GPIO_ResetBits(GPIOA, GPIO_Pin_1); break;}ret = 0;}}}/* 开始输出PWM */void PWM_start(void){TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 1000-CCR1_Val;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC3Init(TIM2, &TIM_OCInitStructure);TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; TIM_OCInitStructure.TIM_Pulse = 1000-CCR1_Val;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC2Init(TIM2, &TIM_OCInitStructure);TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);/* PWM1 Mode configuration: Channel2 */GPIO_ResetBits(GPIOA, GPIO_Pin_1);TIM_ARRPreloadConfig(TIM2, ENABLE);switch(top_temp){case 01: High_fre=100; break;case 02:High_fre=500 ;break;case 03:High_fre=900 ;break;default:break;}switch(stop_temp){case 01:compare=100000; break;case 02:compare=200000 ;break;case 03:compare=50000 ;break;default:break;}TIM_Cmd(TIM2, ENABLE);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/* TIM2 enable counter */}/* 停止输出PWM */void PWM_startN(void){TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1000-CCR1_Val;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC2Init(TIM2, &TIM_OCInitStructure);TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;TIM_OC3Init(TIM2, &TIM_OCInitStructure);TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);/* PWM1 Mode configuration: Channel2 */GPIO_ResetBits(GPIOA, GPIO_Pin_2);TIM_ARRPreloadConfig(TIM2, ENABLE);switch(top_temp){case 01: High_fre=100; break;case 02:High_fre=500 ;break;case 03:High_fre=900 ;break;default:break;}switch(stop_temp){case 01:compare=100000; break;case 02:compare=200000 ;break;case 03:compare=50000 ;break;default:break;}TIM_Cmd(TIM2, ENABLE);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/* TIM2 enable counter */}void TIM2_IRQHandler(void){static unsigned int i=0;static unsigned int j=0;if (TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET){if(counter<compare){if(i<(High_fre-start)/accelerate){TIM2->CCR2=1000-(start+i*accelerate);TIM2->CCR3=1000-(start+i*accelerate);Tulun_i++;counter++;if( Tulun_i==500){i++;Tulun_i=0;}}else{TIM2->CCR2=1000-High_fre;TIM2->CCR3=1000-High_fre;counter++;}}if(counter==compare){TIM2->CCR2=1000-(start+i*accelerate-j*accelerate);TIM2->CCR3=1000-(start+i*accelerate-j*accelerate);Tulun_i++;if( Tulun_i==500){j++;Tulun_i=0;}if(j==i){TIM2->CCR2=1000;TIM2->CCR3=1000;if(Tulun_i==0){TIM_Cmd(TIM2, DISABLE);TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE);i=0;j=0;counter=0;}}}TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}}/* 关LED */void LED_RESET(void){GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)0x00); //关LED GPIO_WriteBit(GPIOB, GPIO_Pin_1, (BitAction)0x00);}/*******************************************************************************Configures the different system clocks.*******************************************************************************/void RCC_Configuration(void){ErrorStatus HSEStartUpStatus;/* RCC system reset(for debug purpose) */RCC_DeInit(); //时钟控制寄存器全部恢复默认值/* Enable HSE */RCC_HSEConfig(RCC_HSE_ON); //外部高速时钟源开启(8M晶振)/* Wait till HSE is ready */HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部时钟就绪if(HSEStartUpStatus == SUCCESS) //如果时钟启动成功{/* HCLK = SYSCLK */RCC_HCLKConfig(RCC_SYSCLK_Div1); //定义AHB设备时钟为系统时钟1分频/* PCLK2 = HCLK */RCC_PCLK2Config(RCC_HCLK_Div1); //定义AHB2设备时钟为HCLK时钟1分频/* PCLK1 = HCLK/2 */RCC_PCLK1Config(RCC_HCLK_Div2); //定义AHB1设备时钟为HCLK时钟2分频/* Flash 2 wait state */FLASH_SetLatency(FLASH_Latency_2); //设定内部FLASH的的延时周期为2周期 /* Enable Prefetch Buffer */FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //使能FLASH预存取缓冲区/* PLLCLK = 8MHz * 9 = 72 MHz */RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //配置PLL时钟为外部高速时钟的9倍频/* Enable PLL */RCC_PLLCmd(ENABLE); //使能PLL时钟/* Wait till PLL is ready */while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待PLL时钟设置完成准备就绪 {}/* Select PLL as system clock source */RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //使用PLL时钟作为系统时钟源 /* Wait till PLL is used as system clock source *//* Wait till PLL is used as system clock source */while(RCC_GetSYSCLKSource() != 0x08) //返回系统所用时钟源确认为外部高速晶振,8M晶振。

(stm32f103学习总结)—can总线

(stm32f103学习总结)—can总线

(stm32f103学习总结)—can总线参考: 1 CAN总线介绍 CAN 是Controller Area Network 的缩写,中⽂意思是控制器局域⽹ 络,是ISO国际标准化的串⾏通信协议。

它是德国电⽓商博世公司于1986 年⾯向汽车⽽开发的CAN 通信协议。

此后,CAN 通过ISO11898 及 ISO11519 进⾏了标准化。

CAN是国际上应⽤最⼴泛的现场总线之⼀,在 欧洲已是汽车⽹络的标准协议。

CAN 的⾼性能和可靠性已被认同,并被 ⼴泛地应⽤于⼯业⾃动化、船舶、医疗设备、⼯业设备等⽅⾯。

CAN通信只具有两根信号线,分别是CAN_H和CAN_L,CAN 控制器根据 这两根线上的电位差来判断总线电平。

总线电平分为显性电平和隐性电 平,⼆者必居其⼀。

发送⽅通过使总线电平发⽣变化,将消息发送给接 收⽅。

2 CAN物理层 与I2C、SPI等具有时钟信号的同步通讯⽅式不同,CAN通讯并不是以时钟信号来进⾏同步的,它是⼀种异步通讯,只具有CAN_High和CAN_Low两条信号线,共同构成⼀组差分信号线,以差分信号的形式进⾏通讯。

CAN物理层的形式主要分为闭环总线及开环总线⽹络两种,⼀个适合于⾼速通讯,⼀个适合于远距离通讯。

2.1 闭环can总线⽹络CAN闭环通讯⽹络是⼀种遵循ISO11898标准的⾼速、短距离⽹络,它的总线最⼤长度为40m,通信速度最⾼为1Mbps,总线的两端各要求有⼀个“120欧”的电阻2.2 开环can总线⽹络CAN开环总线⽹络是遵循ISO11519-2标准的低速、远距离⽹络,它的最⼤传输距离为1km,最⾼通讯速率为125kbps,两根总线是独⽴的、不形成闭环,要求每根总线上各串联有⼀个“2.2千欧”的电阻2.3通讯节点 CAN总线上可以挂载多个通讯节点,节点之间的信号经过总线传输,实现节点间通讯。

由于CAN通讯协议不对节点进⾏地址编码,⽽是对数据内容进⾏编码,所以⽹络中的节点个数理论上不受限制,只要总线的负载⾜够即可,可以通过中继器增强负载。

stm32学习心得体会

stm32学习心得体会

stm32学习⼼得体会 stm32作为现在嵌⼊式物联⽹单⽚机⾏业中经常要⽤多的技术,相信⼤家都有所接触,今天这篇就给⼤家详细的分析下有关于stm32的出⼝,还不是很清楚的朋友要注意看看了哦,在最后还会为⼤家分享有些关于stm32的视频资料便于学习参考。

什么是串⼝ UART : Universal Asynchronous Receiver/Transmitter 通⽤异步收发器 USART : Universal Synchronous Asynchronous Receiver/Transmitter 通⽤同步/异步收发器 ⼀种是常⽤也是最简单的串⾏数据传输协议。

数据线只需要两根就可以实现全双⼯。

Tx: 发送数据线 Rx: 接收数据线 A B TX -----------> Rx Rx <------------Tx 全双⼯: 两个设备可以同时发送和接收 串⾏数据: 发送只⼀根线,⼀次只能发送⼀bit. ⼀bit接着⼀bit发送和接收。

模块通信: 上位机 下位机 通信⼀般需要两个设备,我们把这两个设备,⼈为叫做上位机, 下位机。

上位机: 把处理性能强的机⼦,上位机。

数据⼤部分处理都在上位机完成。

下位机: 把数据采集的终端,处理性能单⼀的机⼦,下位机。

串⼝只有⼀根发送数据线,假如 A要发送⼀个字符数据 10101010 给B A -------- --------- -------- ------- ... ⾼电平周期是多长?即使是不发送数据Tx线上也有⼀个电平状态,接收⽅ 它怎么知道你是在发送呢?.... UART数据如何传输? UART protocol 串⼝协议。

串⼝发送和接收数据是以帧为单位. Frame 1帧(Frame)= 1 start bit(起始位) + 5-9bits数据位 + 0/1bit 校验位 + stop bits(0.5, 1,1,5,2) 起始位: ⼀个周期的低电平 数据位: 5-9bits数据位,具体是多少bits,需要双⽅协商。

对基于STM32的CAN总线通信节点设计分析

对基于STM32的CAN总线通信节点设计分析

对基于STM32的CAN总线通信节点设计分析作者:王烁来源:《中国新通信》 2018年第18期【摘要】伴随着现代通讯技术的快速发展,各行各业对于通信技术的需求也在不断增强,所以必须要加强对于CAN 总线通讯技术进行分析。

基于STM32 的CAN 总线通讯节点既能够保证硬件电路的设计更加的高效简洁,又可以提高数据传输的可靠性与稳定性。

由于CAN 总线具有实时传输的稳定性特点,在各行各业中的应用非常普遍。

本文通过基于STM32 的CAN 总线通信节点设计进行分析,能够针对不同的工业场景,针对数据传输总线和微控制器的性能进行合理化分析。

【关键词】 STM32 CAN 总线通信节点设计随着现代工业技术水平不断提高,人们对于现场总线技术数据传输的要求也越来越高,为了能够更好的满足工业控制领域的需求,必须要加强对于现场总线通讯技术的水平提升。

通过基于STM32 的CAN 总线通讯方式能够利用控制去进行数据显示和报警等模块控制,最终实现吸引物理总线与在点与点之间的数据传输。

一、CAN 节点总线通信节点设计方案1、CAN 总体硬件结构设计。

在通讯的过程中,CAN 总线能够根据不同格式的帧,产生特定的数据结构,从而保证数据在传输过程中避免错误,或者终端在接收数据的过程中,能够识别错误发生的类型,甚至能将错误类型进行还原。

CAN 总线协议在传输的过程中,能够提供CRC冗余算法,进一步增强了数据传输的可靠性与稳定性[1]。

首先要利用STM32 作为主控制芯片,并且利用CAN 总线传输技术所以整个硬件系统要包括供电系统、微控制系统、气敏传感器、液晶显示器以及报警系统。

CAN 总线通讯接口电路具体设计方案可以分为两种,首先是MCU 的直接连接,另一种则是内嵌了MCU 的CAN 控制器。

直接连接的方法比较灵活,而且也可以在复杂电路中进行应用,但是第二种内嵌的方式则能够保证整体的电路更加的紧凑与简洁。

微控制器作为CAN总线通讯节点控制的重要核心,微控制器的质量直接决定着系统性能。

STM32的CAN现场总线应用经验总结

STM32的CAN现场总线应用经验总结

STM32的CAN现场总线应用经验总结CAN现场总线的应用最重要的就是其接口端口映射、初始化及数据的发送、接收。

1.接口映射STM32中的CAN物理引脚可以设置成三种:默认模式、重定义地址1模式、重定义地址2模式。

CAN信号可以被映射到端口A、端口B或端口D上,如下表所示,对于端口D,在36、48和64脚的封装上没有重映射功能。

表1:CAN复用功能重映射复用功能CAN_REMAP[1:0]="00"CAN_REMAP[1:0]="10"CAN_REMAP[1:0]="11" CAN_RX PA11PB8 PD0CAN_TX PA12 PB9 PD1重映射不适用于36脚的封装当PD0和PD1没有被重映射到OSC_IN和OSC_OUT时,重映射功能只适用于100脚和144脚的封装上---------------------------------------------------------------------------------------------------------------------- 默认模式/* Configure CAN pin: RX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/* Configure CAN pin: TX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);---------------------------------------------------------------------------------------------------------------------- 重定义地址1模式/* Configure CAN pin: RX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/* Configure CAN pin: TX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/*Configure CAN Remap 重映射*/GPIO_PinRemapConfig(GPIO_Remap1_CAN,ENABLE);---------------------------------------------------------------------------------------------------------------------- /* Configure CAN pin: RX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/* Configure CAN pin: TX */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIO_CAN_Key, &GPIO_InitStructure);/*Configure CAN Remap 重映射 */GPIO_PinRemapConfig(GPIO_Remap2_CAN,ENABLE);---------------------------------------------------------------------------------------------------------------------- 设置完CAN 的引脚之后还需要打开CAN 的时钟: /* CAN Periph clock enable */RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN,ENABLE); 2. 初始化2.1.1 CAN 单元初始化CAN 单元初始化最重要的就是波特率的设置,原理如下:位时间同步段 时间段1(BS1)时间段2(BS2) 1×t q t BS1=(TS1[3:0]+1)×t qt BS2= (TS2[2:0]+1)×t q波特率=1/位时间位时间 = (1 + t BS1 + t BS2)× t q t q = (BRP[9:0] + 1)× t PCLKt PCLK = APB1例如现有一STM32系统时钟为72MHz ,关于CAN 波特率有以下设置: CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; //重新同步跳跃宽度1个时间单位 CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq; //时间段1为8个时间单位 CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq; //时间段2为7个时间单位 CAN_InitStructure.CAN_Prescaler = 45; //设定了一个时间单位的长度为45即:CAN_InitStructure.CAN_Prescaler即:CAN_InitStructure.CAN_BS1即:CAN_InitStructure.CAN_BS则其CAN 的波特率为1÷[(1+8+7)×45÷(36×106)]=50KHzCAN 单元的初始化,除了波特率的设置以外还包括以下设置:CAN_InitTypeDef CAN_InitStructure; //定义一个CAN 单元CAN_InitStructure.CAN_TTCM = DISABLE; //设置时间触发通信模式(失能) CAN_InitStructure.CAN_ABOM = DISABLE;// 使/失能自动离线管理(失能) CAN_InitStructure.CAN_AWUM = DISABLE;// 使/失能自动唤醒模式(失能) CAN_InitStructure.CAN_NART = DISABLE; //使/失能非自动重传输模式(失能) CAN_InitStructure.CAN_RFLM = DISABLE;// 使/失能接收FIFO 锁定模式(失能) CAN_InitStructure.CAN_TXFP = DISABLE; //使/失能发送FIFO 优先级(失能)CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//设置CAN 工作模式(正常模式) 2.1.2 CAN 报文过滤器初始化STM32共有14组过滤器,每组过滤器包括了2个可配置的32位寄存器:CAN_FxR0和CAN_FxR1。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

STM32的can总线实验心得标签: 总线心得实验2010-09-01 21:08/my/space.php?uid=2 29870&do=blog&id=37832工作模式bxCAN有3个主要的工作模式:初始化、正常和睡眠模式。

初始化模式*软件通过对CAN_MCR寄存器的INRQ位置1,来请求bxCAN进入初始化模式,然后等待硬件对CAN_MSR寄存器的INAK位置1来进行确认。

*软件通过对CAN_MCR寄存器的INRQ位清0,来请求bxCAN退出初始化模式,当硬件对CAN_MSR 寄存器的INAK位清0就确认了初始化模式的退出。

*当bxCAN处于初始化模式时,报文的接收和发送都被禁止,并且CANTX引脚输出隐性位(高电平)。

初始化CAN控制器,软件必须设置CAN_BTR和CAN_MCR寄存器。

正常模式在初始化完成后,软件应该让硬件进入正常模式,同步CAN总线,以便正常接收和发送报文。

软件通过对INRQ位清0来请求从初始化模式进入正常模式,然后要等待硬件对INAK位清0来确认。

在跟CAN总线取得同步,即在CANRX引脚上监测到11个连续的隐性位(等效于总线空闲)后,bxCAN才能正常接收和发送报文。

过滤器初值的设置不需要在初始化模式下进行,但必须在它处在非激活状态下完成(相应的FACT 位为0)。

而过滤器的位宽和模式的设置,则必须在进入正常模式之前,即初始化模式下完成。

睡眠模式(低功耗)*软件通过对CAN_MCR寄存器的SLEEP位置1,来请求进入这一模式。

在该模式下,bxCAN的时钟停止了,但软件仍然可以访问邮箱寄存器。

*当bxCAN处于睡眠模式,软件想通过对CAN_MCR 寄存器的INRQ位置1,来进入初始化式,那么软件必须同时对SLEEP位清0才行。

*有2种方式可以唤醒(退出睡眠模式)bxCAN:通过软件对SLEEP位清0,或硬件检测CAN总线的活动。

工作流程那么究竟can是怎样发送报文的呢?发送报文的流程为:应用程序选择1个空发送邮箱;设置标识符、数据长度和待发送数据;然后CAN_TIxR 寄存器的TXRQ位置1,来请求发送。

TXRQ位置1后,邮箱就不再是空邮箱;而一旦邮箱不再为空,软件对邮箱寄存器就不再有写的权限。

TXRQ位置1后,邮箱马上进入挂号状态,并等待成为最高优先级的邮箱,参见发送优先级。

一旦邮箱成为最高优先级的邮箱,其状态就变为预定发送状态。

当CAN总线进入空闲状态,预定发送邮箱中的报文就马上被发送(进入发送状态)。

邮箱中的报文被成功发送后,它马上变为空邮箱,硬件相应地对CAN_TSR寄存器的RQCP和TXOK位置1,来表明一次成功发送。

如果发送失败,由于仲裁引起的就对CAN_TSR寄存器的ALST位置1,由于发送错误引起的就对TERR 位置1。

发送的优先级可以由标识符或发送请求次序决定:由标识符决定。

当有超过1个发送邮箱在挂号时,发送顺序由邮箱中报文的标识符决定。

根据CAN协议,标识符数值最低的报文具有最高的优先级。

如果标识符的值相等,那么邮箱号小的报文先被发送。

由发送请求次序决定。

通过对CAN_MCR寄存器的TXFP位置1,可以把发送邮箱配置为发送FIFO。

在该模式下,发送的优先级由发送请求次序决定。

该模式对分段发送很有用。

时间触发通信模式:在该模式下,CAN硬件的内部定时器被激活,并且被用于产生时间戳,分别存储在CAN_RDTxR/CAN_TDTxR寄存器中。

内部定时器在接收和发送的帧起始位的采样点位置被采样,并生成时间戳。

接着又是怎样接收报文的呢?接收管理接收到的报文,被存储在3级邮箱深度的FIFO中。

FIFO完全由硬件来管理,从而节省了CPU的处理负荷,简化了软件并保证了数据的一致性。

应用程序只能通过读取FIFO输出邮箱,来读取FIFO中最先收到的报文。

根据CAN协议,当报文被正确接收(直到EOF域的最后1位都没有错误),且通过了标识符过滤,那么该报文被认为是有效报文。

接收相关的中断条件* 一旦往FIFO存入1个报文,硬件就会更新FMP[1:0]位,并且如果CAN_IER寄存器的FMPIE位为1,那么就会产生一个中断请求。

* 当FIFO变满时(即第3个报文被存入),CAN_RFxR 寄存器的FULL位就被置1,并且如果CAN_IER寄存器的FFIE位为1,那么就会产生一个满中断请求。

* 在溢出的情况下,FOVR位被置1,并且如果CAN_IER寄存器的FOVIE位为1,那么就会产生一个溢出中断请求。

标识符过滤在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。

因此,发送者以广播的形式将报文发送给所有的接受者。

节点在接收报文时根据标识符的值决定是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。

为满足这一需求,bxCAN为应用程序提供了14个位宽可变的、可配置的过滤器组(13~0),以便只接收那些软件需要的报文。

硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。

每个过滤器组x由2个32位寄存器CAN_FxR0和CAN_FxR1组成。

过滤器的模式的设置:通过设置CAN_FM0R的FBMx位,可以配置过滤器组为标识符列表模式或屏蔽位模式。

为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。

为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。

应用程序不用的过滤器组,应该保持在禁用状态。

过滤器优先级规则:位宽为32位的过滤器,优先级高于位宽为16位的过滤器;对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式;位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高。

接收邮箱(FIFO)在接收到一个报文后,软件就可以访问接收FIFO的输出邮箱来读取它。

一旦软件处理了报文(如把它读出来),软件就应该对CAN_RFxR寄存器的RFOM 位进行置1,来释放该报文,以便为后面收到的报文留出存储空间。

中断bxCAN占用4个专用的中断向量。

通过设置CAN中断允许寄存器CAN_IER ,每个中断源都可以单独允许和禁用。

(1) 发送中断可由下列事件产生:─ 发送邮箱0变为空,CAN_TSR寄存器的RQCP0位被置1。

─ 发送邮箱1变为空,CAN_TSR寄存器的RQCP1位被置1。

─ 发送邮箱2变为空,CAN_TSR寄存器的RQCP2位被置1。

(2) FIFO0中断可由下列事件产生:─ FIFO0接收到一个新报文,CAN_RF0R寄存器的FMP0位不再是‘00’。

─ FIFO0变为满的情况,CAN_RF0R寄存器的FULL0位被置1。

─ FIFO0发生溢出的情况,CAN_RF0R寄存器的FOVR0位被置1。

(3) FIFO1中断可由下列事件产生:─ FIFO1接收到一个新报文,CAN_RF1R寄存器的FMP1位不再是‘00’。

─ FIFO1变为满的情况,CAN_RF1R寄存器的FULL1位被置1。

─ FIFO1发生溢出的情况,CAN_RF1R寄存器的FOVR1位被置1。

(4) 错误和状态变化中断可由下列事件产生:─ 出错情况,关于出错情况的详细信息请参考CAN 错误状态寄存器(CAN_ESR)。

─ 唤醒情况,在CAN接收引脚上监视到帧起始位(SOF)。

─ CAN进入睡眠模式。

工作流程大概就是这个样子,接着就是一大堆烦人的can寄存器,看了一遍总算有了大概的了解,况且这么多的寄存器要一下子把他们都记住是不可能的。

根据以往的经验,只要用多几次,对寄存器的功能就能记住。

好了,到读具体实验程序的时候了,这时候当然要打开“STM32库函数”的资料,因为它里面有STM32打包好的库函数的解释,对读程序很有帮助。

下面是主程序:int main(void){// int press_count = 0;char data = '0';int sent = FALSE;#ifdef DEBUGdebug();#endifRCC_Configuration();NVIC_Configuration();GPIO_Configuration();USART_Configuration();CAN_Configuration();Serial_PutString("\r\n伟研科技 \r\n");Serial_PutString("CAN test\r\n");while(1){if(GPIO_Keypress(GPIO_KEY, BUT_RIGHT)) {GPIO_SetBits(GPIO_LED, GPIO_LD1); //检测到按键按下 if(sent == TRUE)continue;sent = TRUE;data ++;if(data > 'z')data = '0';CAN_TxData(data);}else//按键放开{GPIO_ResetBits(GPIO_LED, GPIO_LD1); sent = FALSE;}}}前面的RCC、NVIC、GPIO、USART配置和之前的实验大同小异,关键是分析CAN_Configuration()函数如下:void CAN_Configuration(void)//CAN配置函数{CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDefCAN_FilterInitStructure;/* CAN register init */CAN_DeInit();// CAN_StructInit(&CAN_InitStructure);/* CAN cell init */CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式CAN_InitStructure.CAN_ABOM=DISABLE;//软件对CAN_MCR寄存器的INRQ位进行置1随后清0后,一旦硬件检测 //到128次11位连续的隐性位,就退出离线状态。

CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过清除CAN_MCR寄存器的SLEEP位,由软件唤醒CAN_InitStructure.CAN_NART=ENABLE;//DISABLE;CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)CAN_InitStructure.CAN_RFLM=DISABLE;//在接收溢出时FIFO未被锁定,当接收FIFO的报文未被读出,下一个收到的报文会覆盖原有的报文CAN_InitStructure.CAN_TXFP=DISABLE;//发送FIFO优先级由报文的标识符来决定//CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack; CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //CAN硬件工作在正常模式CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;//重新同步跳跃宽度1个时间单位CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;//时间段1为8个时间单位CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;//时间段2为7个时间单位CAN_InitStructure.CAN_Prescaler =9;//(pclk1/((1+8+7)*9))=36Mhz/16/9 =bits设定了一个时间单位的长度9 CAN_Init(&CAN_InitStructure);/* CAN filter init 过滤器初始化*/CAN_FilterInitStructure.CAN_FilterNumber=0;//指定了待初始化的过滤器0CAN_FilterInitStructure.Filt erMo de=C AN_F ilte rMod e_Id Mask ;//指定了过滤器将被初始化到的模式标识符屏蔽位模式CAN_ Filt erIn itSt ructCAN_ Filt erId High =0x0 000; //用来设定过滤器标识符(32位位宽时为其高段位,16位位宽时为个)CAN_FilterInitStrucu r e . C A N _ F i l t e r I d L o w = 00 0 0 0 ; / /用来设定过滤器标识符(3 2位宽时为其低段位,16位位宽时为第二个CAN_FilterInitStructure.CAN _FilterMaskIdHigh=0x0000;//用来设定过滤器屏蔽标识符或者过滤器标识符(32位位宽时为其高段位,16位位宽时为第一个)CAN_FilterInitStructure.CAN _FilterMaskIdLow=0x0000;//用来设定过滤器屏蔽标识符或者过滤器标识符(32位位宽时为其低段位,16位位宽时为第二个CAN_FilterInitStructure.CAN_FilterActivation=E NABLE;//使能过滤器CAN_FilterInit(&CAN_FilterInitStructure);/* CAN FIFO0 message pending interrupt enable */CAN_ITConfig(CAN_IT_FMP0, ENABLE);//使能指定的CAN中断}再看看发送程序:TestStatus CAN_TxData(char data){CanTxMsg TxMessage;u32 i = 0;u8 TransmitMailbox = 0;/*u32 dataLen;dataLen = strlen(data);if(dataLen > 8)dataLen = 8;*//* transmit 1 message生成一个信息 */ TxMessage.StdId=0x00;//设定标准标识符TxMessage.ExtId=0x1234;//设定扩展标识符TxMessage.IDE=CAN_ID_EXT;//设定消息标识符的类型TxMessage.RTR=CAN_RTR_DATA;//设定待传输消息的帧类型/* TxMessage.DLC= dataLen;for(i=0;i<dataLen;i++)TxMessage.Data[i] = data[i];*/TxMessage.DLC= 1; //设定待传输消息的帧长度 TxMessage.Data[0] = data;//包含了待传输数据TransmitMailbox =CAN_Transmit(&TxMessage);//开始一个消息的传输i = 0;w h i l e ( ( C A N _ T r a n s m i t S tt u s ( T r a n s m i t M a i l b o x )=< A& &( i! = " 0 x F F ) ) /通过检查C A N T X O K 位来确认发送是否成功{i++;}return (TestStatus)ret;}CAN_Transmit()函数的操作包括:1.[选择一个空的发送邮箱]2.[设置Id]*3.[设置DLC待传输消息的帧长度]4.[请求发送]请求发送语句:CAN->sTxMailBox[TransmitMailbox].TIR |= TMIDxR_TXRQ;//对CAN_TIxR寄存器的TXRQ位置1,来请求发送发送方面搞定了,但接收方面呢?好像在主程序里看不到有接收的语句。

相关文档
最新文档