STM32 CAN 总线调试 经验

发布者:HarmonyJoy最新更新时间:2021-08-17 来源: 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;

[1] [2]
关键字:STM32  CAN  总线调试 引用地址:STM32 CAN 总线调试 经验

上一篇:基于STM32手势控制显示系统的设计
下一篇:stm32之DMA彻底研究

推荐阅读最新更新时间:2024-11-13 11:10

Canalys:2021年Q3手机出货量苹果重回第二,华为荣耀没进前五
根据调研机构Canalys的最新报告,2021年第三季度,由于芯片短缺,供应商难以满足对设备的需求,全球智能手机出货量下降了6%。 三星依旧拿下了第一,其占有23%的份额,苹果份额提升至15%,重回第二,小米排名第三,份额为14%,vivo和OPPO则以10%份额并列第五名。 “芯片荒真的到来了,”Canalys首席分析师Ben Stanton表示。“智能手机行业正在尽最大努力最大限度地提高设备的产量。在供应方面,芯片厂商正在提高价格以抑制过度订购,以试图缩小供需之间的差距。尽管如此,短缺仍要到2022年才会缓解,再加上全球运费的高昂成本,智能手机品牌只能提高设备零售价。” 对比2021年第二季度的数据,可以发现三星的份额
[手机便携]
<font color='red'>Can</font>alys:2021年Q3手机出货量苹果重回第二,华为荣耀没进前五
STM32 USB HID 自定义设备 bulk 传输
ST(意法半导体公司)为STM32系列处理器编写了外设USB的库,并提供了很好的参考例程,本文就是参考ST提供的例程,在STM32F4 discovery板子上实现usb bulk传输。Host端是在linux平台上利用libusb库函数写的读写USB应用。 本次实现在STM32 USB例程中的Device HID 鼠标例程基础上添加bulk传输端点修改而来。 usb_conf.h 文件中添加 bulk传输端点 /* * endpoint 0x80 and 0x00 are used for enumerating device. * endpoint 0x81 and 0x80 are used for cont
[单片机]
STM32 EXTI外部中断小结
本文为野火教程学习笔记。 EXTI原理解释 EXTI 简介   EXTI (External interrupt/event controller) ——外部中断/事件控制器,其用于管理外设中GPIO和一些其他外设的中断。可以实现单独对某一线配置中断触发方式等操作。 EXTI原理框图解释   边沿检测器检测外部的信号,上升沿和下降沿触发选择寄存器具体的配置会决定边沿检测电路检测何种边沿。   检测到对应边沿后,检测电路输出1,软件中断事件寄存器的配置决定是否产生中断或事件,相当于小开关。   若配置响应这个边沿,则小开关输出1。下面由请求挂起寄存器和事件屏蔽寄存器确定产生中断还是事件。这两个相当于选择开关。  
[单片机]
<font color='red'>STM32</font> EXTI外部中断小结
STM32学习----时钟
在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,
[单片机]
stm32 中断嵌套NVIC的理解
1、NVIC_InitStructure结构体在misc.h文件中进行定义,编程时可查看。关于NVIC的函数都在misc.h文件中进行定义。 2、中断服务函数入口名称在startup_stm32f10x_hd.s文件中。 3、 中断结构参数NVIC_InitStructure.NVIC_IRQChannel的值在stm32f10x.h文件中查找。 4、中断服务函数名称必须按照startup_stm32f10x_hd.s文件中中断向量表的名称进行编写,中断服务函数可以放在任意一个文件夹中,与存放位置无关。 NVIC对中断优先级进行管理,并且设置中断线。 NVIC_IRQChannelPreemptionPriority:先占优先
[单片机]
STM32笔记记录2
外部中断控制: STM32的每个IO 都可以作为外部中断的中断输入口,这点也是STM32的强大之处。STM32F103的中断控制器支持19个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F103 的19个外部中断为:     线0~15:对应外部IO 口的输入中断。     线16:连接到PVD输出。     线17:连接到RTC闹钟事件。     线18:连接到USB唤醒事件。 STM32供IO 口使用的中断线只有16个,但是STM32的IO 口却远远不止16个,STM32就这样设计,GPIO的管教GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中
[单片机]
基于STM32数据传输转换接口器的设计与实现
引言 在当今高速实时数字信号处理系统中,涉及的数据对象趋于多样化,这些数据通常采用不同的电气接口,具有不同的传输速率、传输方向。现代机电一体化控制设备中,如工业加注机、设备清洗机控制系统基本是PLC与显示屏加仪表等构成的小型计算机控制系统。但现在工业已经进入了数字化、智能化时代,进入物联网领域,要求信息共享,生产过程信息化、网络化管理,提高生产效率,降低人员劳动强度。所以要满足上述需求,保留原有设备及控制系统,进行新老交替,则需要在原有控制柜基础上增加数据交换接口模块,如图1所示。基于此,我们以数字信号处理器STM32为核心,设计了适于多种标准接口数据传输接口器,以实现系统的数据交互。 图1具有数据传输交换接口器的控制系统框架
[单片机]
基于<font color='red'>STM32</font>数据传输转换接口器的设计与实现
解读STM32高功率激光医疗仪控制电路
简介:本文采用模块化设计,设计了一种基于STM32($20.3400) 的2μm光纤激光器医疗仪控制系统,将水冷单元的参数监控、电源模块的抗干扰设计、输出功率的校准等集成于一体。测试结果表明,系统可靠稳定,操作方便。 2μm 高功率激光医疗仪市场需求越来越大,而目人机交互模块前国内此类设备在控制上缺乏对系统安全和出光精准度的考虑。同时随着YY0505-2012 医用电气电磁兼容标准于2014 年的执行,设计符合YY0505-2012 标准的医用设备已迫在眉睫。因此,本文采用模块化设计,设计了一种基于STM32($20.3400)的2μm光纤激光器医疗仪控制系统,将水冷单元的参数监控、电源模块的抗干扰设计、输出功率的校准等集成于
[单片机]
解读<font color='red'>STM32</font>高功率激光医疗仪控制电路
热门资源推荐
热门放大器推荐
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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