STM32的can总线实验心得

发布者:lcn18560863680最新更新时间:2018-09-02 来源: eefocus关键字:STM32  can总线 手机看文章 扫描二维码
随时随地手机看文章

(一) 工业现场总线 CAN 的基本介绍以及 STM32 的 CAN 模块简介

首先通读手册中关于CAN的文档,必须精读。
STM32F10xxx 参考手册Rev7V3.pdf
http://www.mystm32.com/bbs/redirect.php?tid=255&goto=lastpost#lastpost

需要精读的部分为 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 两种模式。
我们第一步做的就是使用运行在 CAN_Mode_LoopBack 下进行自测试。

在参考手册中 CAN_Mode_LoopBack (环回模式) 的定义如下:
环回模式可用于自测试。为了避免外部的影响,在环回模式下 CAN 内核忽略确认错误 (在数据 / 远程帧的确认位时刻,不检测是否有显性位) 。在环回模式下,bxCAN 在内部把 Tx 输出回馈到 Rx 输入上,而完全忽略 CANRX 引脚的实际状态。发送的报文可以在 CANTX 引脚上检测到。
因此这种模式也特别适合大家做好硬件后自测程序。

2.jpg




(三) CAN 接口端口映射

STM32 中的 CAN 物理引脚脚位可以设置成三种:

默认模式,重定义地址1模式,重定义地址2模式



2.jpg


在我们的 Mini-STM32 上面没有接出 CAN 的接口芯片, 所以我们可以利用

RealView MDK

的 CAN 软件

模拟

模块来做实验.


-------------------------------------------------------------------------


默认模式

   /* Configure CAN pin: RX */


  

GPIO

_InitStructure.GPIO_Pin = GPIO_Pin_11;


   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;


   GPIO_Init(GPIOA, &GPIO_InitStructure);


  


   /* Configure CAN pin: TX */


   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;


   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


   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_Speed = GPIO_Speed_50MHz;


   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;


   //GPIO_Init(GPIOB, &GPIO_InitStructure);


   /* Configure CAN pin: TX */  


   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;


   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;


   //GPIO_Init(GPIOB, &GPIO_InitStructure);


   /* Configure CAN Remap   重影射 */


   //GPIO_PinRemapConfig(GPIO_Remap1_CAN, ENABLE);


-------------------------------------------------------------------------  


重定义地址2模式

   /* Configure CAN pin: RX */


   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;


   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;


   //GPIO_Init(GPIOD, &GPIO_InitStructure);


  


   /* Configure CAN pin: TX */


   //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;


   //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


   //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;


   //GPIO_Init(GPIOD, &GPIO_InitStructure);


  


   /* Configure CAN Remap   重影射 */


   //GPIO_PinRemapConfig(GPIO_Remap2_CAN, ENABLE);


-------------------------------------------------------------------------



设置完 CAN 的引脚之后还需要打开 CAN 的时钟:

/* CAN Periph clock enable */


   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);




(四) CAN 波特率设置

4、我们需要搞明白CAN波特率的设置,这个章节也是使用CAN的最重要的部分之一,因为这实际应用中我们需要根据我们实际的场合来选择 CAN 的波特率。


一般情况下面1M bps 的速率下可以最高可靠传输 40 米以内的距离。


在 50K 以下的波特率中一般可以可靠传输数公里远。


对于波特率的设置需要详细学习参考手册对应部分的解释。我们在调试软件的时候可以使用示波器来测试 CANTX 引脚上的波形的波特率,这样可以得到事半功倍的效果,大大的缩短调试学习的时间。


// ***************************************************************


//       BaudRate = 1 / NominalBitTime


//       NominalBitTime = 1tq + tBS1 + tBS2


//       tq = (BRP[9:0] + 1) x tPCLK


//       tPCLK = CAN's clock = APB1's clock


// ****************************************************************


也就是BaudRate = APB1 / ((BS1 + BS2 + 1) * Prescaler)


这里注意的是采用点的位置,也就时BS1,BS2的设置问题,这里我也找了一些资料,抄录下来给大家,是 CANopen 协议中推荐的设置。


   1Mbps 速率下,采用点的位置在6tq位置处,BS1=5, BS2=2


   500kbps 速率下,采用点的位置在8tq位置处,BS1=7, BS2=3


   250kbps 速率下,采用点的位置在14tq位置处,BS1=13, BS2=2


   125k, 100k, 50k, 20k, 10k 的采用点位置与 250K 相同。


因此我们需要重视的有软件中的这么几个部分:


// 设置 AHB 时钟(HCLK)


// RCC_SYSCLK_Div1   AHB 时钟 =   系统时钟


RCC_HCLKConfig(RCC_SYSCLK_Div8);


// 设置低速 AHB 时钟(PCLK1)


// RCC_HCLK_Div2   APB1 时钟   = HCLK / 2


RCC_PCLK1Config(RCC_HCLK_Div2);


// PLLCLK = 8MHz * 8 = 64 MHz


// 设置 PLL 时钟源及倍频系数


RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_8);


CAN 波特率设置中需要的就是PCLK1 的时钟。


   CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;


   CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;


   CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;


   CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;


   CAN_InitStructure.CAN_Prescaler=5;


通过上面部分的时钟设置我们已经可以算出我们的波特率了


CAN_bps = PCLK1 / ((1 + 7 + 8) * 5) = 25K bps


大家也可以实际测试中修改时钟值来通过示波器测试我们需要的波特率是否正确例如将PLLCLK 设置降低一半:


// PLLCLK = 8MHz * 4 = 32 MHz


// 设置 PLL 时钟源及倍频系数


RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_4);


那么我们得到的CAN_bps也会降低一半。


接下来还可以修改 HCLK 和 PCLK1 ,其实最终这几个分频和倍频值最终影响的都是 PCLK1。


通过几次试验,相信大家应该很容易掌握波特率的设置了。


设置完波特率我们直接测试函数:


   /* CAN transmit at 100Kb/s and receive by polling in loopback mode*/


   TestRx = CAN_Polling();


   if (TestRx == FAILED)


   {


/* Turn on led connected to PA.00 pin (LD1) */


GPIO_SetBits(GPIOA, GPIO_Pin_0);


   }


   else


   {


/* Turn off led connected to PA.00 pin (LD1) */


GPIO_ResetBits(GPIOA, GPIO_Pin_0);


   }


   /* CAN transmit at 500Kb/s and receive by interrupt in loopback mode*/


   TestRx = CAN_Interrupt();


   if (TestRx == FAILED)


   {


/* Turn on led connected to PA.01 pin (LD2) */


GPIO_SetBits(GPIOA, GPIO_Pin_1);


   }


   else


   {


/* Turn off led connected to PA.01 pin (LD2) */


GPIO_ResetBits(GPIOA, GPIO_Pin_1);


   }


CAN 软件仿真模拟器

调用出来.




4.JPG


大家可以仿真程序,当程序中 Test 等于 Passed 那么说明 Loopback 模式测试通过了。


并且在 CAN 通讯框中我们可以看到发送和接收到的数据:



5.jpg



回循模式下的源代码, 基于 MDK3.5:
 Example7.1-CAN LoopBack Mode.rar

(493.79 KB)


到此时说明如果大家只有一块CAN模块的时候学习可以告一个段落了,不过这个并不代表大家就已经掌握了 CAN 了,正真要掌握它,大家还是需要看大量的 CAN 部分的资料,参考手册部分的也是不够的,市面上有几本专门介绍现场总线和CAN总线的书,推荐大家买来经常翻翻看看,这样到需要实际应用的时候才可以做到 如鱼得水。




(五) 正常模式

完成了 loopback 模式的测试之后接下来我们需要学习的就是多机通讯了,当然由于我们的 Mini-STM32 没有将 CAN 接口引出来, 所以我们没有办法在板子上面做这部分的试验了,只能在 RealView MDK 的软件中进行模拟。


如果您拥有两块带 CAN 硬件的 STM32 的板子,您需要自己构建硬件的物理层的连接, 使用三根线将 CANH,CANL,GND 三根线直连,当然你要接好终端电阻才能保证通讯的正常通讯,当两块板子都跳好后我们使用万用表测量下 CANH和CANL之间的电阻是否为 60 欧姆。多块板子多机通讯的是否你只需要在总线的主机端和最后一端接上终端电阻就可以了.



3.jpg


   在初始化完成后,软件应该让硬件进入正常模式,以便正常接收和发送报文。软件可以通过对 CAN_MCR 寄存器的INRQ位清 '0',来请求从初始化模式进入正常模式,然后要等待硬件对 CAN_MSR 寄存器的 INAK 位置 '1' 的确认。在跟 CAN 总线取得同步,即在 CANRX 引脚上监测到 11 个连续的隐性位 (等效于总线空闲) 后,bxCAN 才能正常接收和发送报文。


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


准备工作做完我们需要设置 CAN 通讯部份软件。




我们把 TestStatus CAN_Polling(void) 函数和 TestStatus CAN_Interrupt(void) 函数中的 LoopBack 模式修改为 Normal 模式.


//CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;


   CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;


   接下来我们就可以做实验了. 但是由于 RealView MDK 的 CAN 模块没有办法接收, 所以我们只做发送的例子.


我们的例子中分别发送两帧数据:


(1) TestStatus CAN_Polling(void) 查询发送

第一帧数据为:   ID 为 0x11, 数据为 8 个字节的一个数据包.


   TxMessage.StdId=0x11;


   TxMessage.RTR=CAN_RTR_DATA;


   TxMessage.IDE=CAN_ID_STD;


   TxMessage.DLC=8;


   TxMessage.Data[0]=0x01;


   TxMessage.Data[1]=0x02;


   TxMessage.Data[2]=0x03;


   TxMessage.Data[3]=0x04;


   TxMessage.Data[4]=0x05;


   TxMessage.Data[5]=0x06;


   TxMessage.Data[6]=0x07;


   TxMessage.Data[7]=0x08;



(2) TestStatus CAN_Interrupt(void) 中断发送

第二帧数据为:ID 为 0x1234, 数据为 8 个字节的一个数据包.


   TxMessage.StdId=0x12;


   TxMessage.ExtId=0x34;


   TxMessage.IDE=CAN_ID_EXT;


   TxMessage.RTR=CAN_RTR_DATA;


   TxMessage.DLC=8;


   TxMessage.Data[0]=0x11;


   TxMessage.Data[1]=0x22;


   TxMessage.Data[2]=0x33;


   TxMessage.Data[3]=0x44;


   TxMessage.Data[4]=0x55;


   TxMessage.Data[5]=0x66;


   TxMessage.Data[6]=0x77;


   TxMessage.Data[7]=0x88;


   CAN_Transmit(&TxMessage);


在主函数中初始化之后加上这两句发送函数:


   /* CAN transmit at 100Kb/s and receive by polling in Normal mode*/


   CAN_Polling();


   while(i++ < 1000);


   /* CAN transmit at 500Kb/s and receive by interrupt in Normal mode*/


   CAN_Interrupt();


程序改完了, 我们需要编译通过后, 点软件仿真.


CAN 软件仿真模拟器

调用出来.


接下来我们全速运行到 while(1) 就可以看到结果了.




1.jpg


关键字:STM32  can总线 引用地址:STM32的can总线实验心得

上一篇:STM32F042替换STM32F103
下一篇:STM32 CAN总线调试的一点心得总结

推荐阅读最新更新时间:2024-03-16 16:12

CAN_bus 总线在门禁系统中的应用
CAN_bus总线简介   CAN-bus(ControllerAreaNetwork)即控制器局域网,是国际上应用最广泛的现场总线之一。起先,CAN-bus被设计作为汽车环境中的微控制器通讯,在车载各电子控制装置ECU之间交换信息,形成汽车电子控制网络。比如:发动机管理系统、变速箱控制器、仪表装备、电子主干系统中,均嵌入CAN控制装置。由于其技术先进、可靠性高、功能完善、成本合理,CAN_busCAN-bus已被广泛应用到各个自动化控制系统中。例如,在汽车电子、自动控制、智能大厦、电力系统、安防监控等各领域。   CAN-bus是一种多主方式的串行通讯总线,具有高的位速率,高抗电磁干扰性,而且能够检测出产生的任何错误。当
[嵌入式]
基于DSPIC30F4011单片机的CAN总线通信设计
0 引言   CAN (CONtroller Area Network) 即控制器局域网络, 属于工业现场总线的范畴。与一般的通信总线相比, CAN总线的数据通信具有突出的可靠性、实时性和灵活性。事实上, 由于其良好的性能及独特的设计, CAN总线越来越受到人们的重视。同时, 由于CAN总线本身的特点, 其应用范围目前已不再局限于汽车行业, 而且向着自动控制、航空航天、航海、过程工业、机械工业、纺织机械、农用机械、机器人、数控机床、医疗器械及传感器等领域发展。为此, 本文给出了利用两片DSPIC30F4011, 并用双绞线将两单片机的CAN模块连接起来组成一个CAN总线, 而两单片机相当于CAN总线上的两个结点, 再编写程序
[单片机]
基于DSPIC30F4011单片机的<font color='red'>CAN总线</font>通信设计
stm32位带操作中对内存的浅显理解
基础知识 进制   计算机以二进制代码储存信息,每个二进制数表示一位 (bit),每8个二进制数表示一个字节 (Byte) , 而再往上的KB,就是210倍的字节,总结有以下进制关系。 1 Byte = 8 bit 1 KB = 1024Byte(210=1024) 1 MB = 1024KB 1 GB = 1024MB 1 GB = 230Byte 内存地址   内存地址使用16进制数表示,内存地址只是一个编号表示,一个内存空间,计算机以字节存储数据,所以一个内存地址对应的应该是一个字节(8 bit)的大小,这个之后会详细解释。 这里用32位机的内存做一个图例。32位机的内存地址用8位16进制数表示。 0x00000
[单片机]
<font color='red'>stm32</font>位带操作中对内存的浅显理解
STM32学习——EXTI外部中断
EXTI简介 EXTI可以实现对外部输入信号的上升沿检测和下降沿的检测。EXTI可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。 可以看到EXTI一共有20条信号线,即可同时检测来自20路的中断请求。 代码实现 (1)首先配置GPIO初始化结构体 GPIO要配置为浮空输入 void Key_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStruc
[单片机]
<font color='red'>STM32</font>学习——EXTI外部中断
关于STM32开发板晶振相关的问题汇总
1、自己做了个STM32的板子,,但是手里没有8M的晶振,所以就用了,12M的,,但是不正常,上电之后PA15和PA14接的是两个led,PA15接的led常亮,PA14接的的led不亮,,而且芯片下载程序又能下载,应该不是芯片坏的问题吧,,而且不管我些什么程序进去,两个脚的状态都不变,,我怀疑是电路有问题,,可是我仔细检查了电路和板子,都没问题,,JTAG正常使用。我用的是12M的晶振,这会有影响吗?感觉不管下什么程序进去感觉芯片好像没有运行。 答:如果使用12M的晶振,那么要修改启动文档中的关于RCC的语句。 因为如果你使用库文件的话,ST的库,默认外部晶振是8M,所以如果你不修改RCC部分的语句,会造成CPU不启动,
[单片机]
STM32SPI读写函数
//SPIx 读写一个字节 //TxData:要写入的字节 //返回值:读取到的字节 u8 SPIx_ReadWriteByte(u8 TxData) { while((SPI1- SR&(1 1))==0); SPI1- DR=TxData; //发送一个byte while((SPI1- SR&(1 0))==0); returnSPI1- DR; //返回收到的数据 } 对于这
[单片机]
基于STM32的多功能γ能谱仪设计
摘要:文中介绍了一种基于STM32微处理器的γ能谱仪的研制。该仪器由主探测器、主控电路,GPS模块,SD卡存储模块,USB接口电路构成。是一种集辐射强度检测、辐射源地理位置定位,数据存储,USB传输等功能于一体的监测系统,大大丰富并提高了能谱仪的性能。 随着对天然辐射场中低能量γ谱学及其应用的深入研究,γ能谱仪不仅在固体矿产勘探、油气普查、水文和工程地质调查等工业生产及科学研究方面,甚至在民用的环境辐射场调查、建材与建筑装饰材料放射性检测方面,都得到广泛的应用,应用场合的复杂多样化对核辐射测量仪器提出新的需求。传统的核辐射测量仪器常采用探头与主控仪器分离的方式,而且主控仪器通常采用32位ARM7处理器甚至8位单片机系统来进行控
[单片机]
基于<font color='red'>STM32</font>的多功能γ能谱仪设计
STM32开发中的位带操作机制
为了像51单片机一样能够对某个管脚单独操作,引入了位带操作这样的操作机制。 如下图,位带(Bit band)区就是就是你想单独操作的IO的区域,比如PA1、PA2。而位带别名区就是你给每一位重新起了个名字的那一片地址区域。可以看下表,M3内核存储器映射表,你能看到1M内存的BitBand区,还有与之对应的32M内存的BitBand别名区,因为你将每一位膨胀成为了一个32位的地址,所以相应的别名区的内存也会是位带区的32倍。 想进行位带操作,应该先去找该位对应的别名区的地址,找到了这个地址,对这个地址进行操作,那么实际上也就是对该位进行操作了。 官方给出了如下相应的计算公式: AliasAddr=0x42000000+((A‐0
[单片机]
<font color='red'>STM32</font>开发中的位带操作机制
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved