STM32的can总线实验心得要点.docx
《STM32的can总线实验心得要点.docx》由会员分享,可在线阅读,更多相关《STM32的can总线实验心得要点.docx(15页珍藏版)》请在冰豆网上搜索。
STM32的can总线实验心得要点
STM32的can总线实验心得
(一)工业现场总线CAN的基本介绍以及STM32的CAN模块简介
首先通读手册中关于CAN的文档,必须精读。
STM32F10xxx参考手册Rev7V3.pdf
需要精读的部分为RCC和CAN两个章节。
为什么需要精读RCC呢?
因为我们将学习CAN的波特率的设置,将要使用到RCC部分的设置,因此推荐大家先复习下这部分中的几个时钟。
关于STM32的can总线简单介绍
bxCAN是基本扩展CAN(BasicExtendedCAN)的缩写,它支持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块地址空间,便于提高软件效率
(二)STM32CAN模块工作模式
STM32的can的工作模式分为:
/*CANoperatingmode*/
#defineCAN_Mode_Normal((u8)0x00)/*normalmode*/
#defineCAN_Mode_LoopBack((u8)0x01)/*loopbackmode*/
#defineCAN_Mode_Silent((u8)0x02)/*silentmode*/
#defineCAN_Mode_Silent_LoopBack((u8)0x03)/*loopbackcombinedwithsilentmode*/
在此章我们的Mini-STM32教程中我们将使用到CAN_Mode_LoopBack和CAN_Mode_Normal两种模式。
我们第一步做的就是使用运行在CAN_Mode_LoopBack下进行自测试。
在参考手册中CAN_Mode_LoopBack(环回模式)的定义如下:
环回模式可用于自测试。
为了避免外部的影响,在环回模式下CAN内核忽略确认错误(在数据/远程帧的确认位时刻,不检测是否有显性位)。
在环回模式下,bxCAN在内部把Tx输出回馈到Rx输入上,而完全忽略CANRX引脚的实际状态。
发送的报文可以在CANTX引脚上检测到。
因此这种模式也特别适合大家做好硬件后自测程序。
下载(37.38KB)
2009-8-1611:
46
(三)CAN接口端口映射
STM32中的CAN物理引脚脚位可以设置成三种:
默认模式,重定义地址1模式,重定义地址2模式
。
下载(28.94KB)
2009-8-1611:
51
在我们的Mini-STM32上面没有接出CAN的接口芯片,所以我们可以利用
RealViewMDK
的CAN软件
模拟
模块来做实验.
-------------------------------------------------------------------------
默认模式
/*ConfigureCANpin:
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);
/*ConfigureCANpin:
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模式
/*ConfigureCANpin:
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);
/*ConfigureCANpin:
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);
/*ConfigureCANRemap重影射*/
//GPIO_PinRemapConfig(GPIO_Remap1_CAN,ENABLE);
-------------------------------------------------------------------------
重定义地址2模式
/*ConfigureCANpin:
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);
/*ConfigureCANpin:
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);
/*ConfigureCANRemap重影射*/
//GPIO_PinRemapConfig(GPIO_Remap2_CAN,ENABLE);
-------------------------------------------------------------------------
设置完CAN的引脚之后还需要打开CAN的时钟:
/*CANPeriphclockenable*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN,ENABLE);
(四)CAN波特率设置
4、我们需要搞明白CAN波特率的设置,这个章节也是使用CAN的最重要的部分之一,因为这实际应用中我们需要根据我们实际的场合来选择CAN的波特率。
一般情况下面1Mbps的速率下可以最高可靠传输40米以内的距离。
在50K以下的波特率中一般可以可靠传输数公里远。
对于波特率的设置需要详细学习参考手册对应部分的解释。
我们在调试软件的时候可以使用示波器来测试CANTX引脚上的波形的波特率,这样可以得到事半功倍的效果,大大的缩短调试学习的时间。
//***************************************************************
//BaudRate=1/NominalBitTime
//NominalBitTime=1tq+tBS1+tBS2
//tq=(BRP[9:
0]+1)xtPCLK
//tPCLK=CAN'sclock=APB1'sclock
//****************************************************************
也就是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_Div1AHB时钟=系统时钟
RCC_HCLKConfig(RCC_SYSCLK_Div8);
//设置低速AHB时钟(PCLK1)
//RCC_HCLK_Div2APB1时钟=HCLK/2
RCC_PCLK1Config(RCC_HCLK_Div2);
//PLLCLK=8MHz*8=64MHz
//设置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)=25Kbps
大家也可以实际测试中修改时钟值来通过示波器测试我们需要的波特率是否正确例如将PLLCLK设置降低一半:
//PLLCLK=8MHz*4=32MHz
//设置PLL时钟源及倍频系数
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_4);
那么我们得到的CAN_bps也会降低一半。
接下来还可以修改HCLK和PCLK1,其实最终这几个分频和倍频值最终影响的都是PCLK1。
通过几次试验,相信大家应该很容易掌握波特率的设置了。
设置完波特率我们直接测试函数:
/*CANtransmitat100Kb/sandreceivebypollinginloopbackmode*/
TestRx=CAN_Polling();
if(TestRx==FAILED)
{
/*TurnonledconnectedtoPA.00pin(LD1)*/
GPIO_SetBits(GPIOA,GPIO_Pin_0);
}
else
{
/*TurnoffledconnectedtoPA.00pin(LD1)*/
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
/*CANtransmitat500Kb/sandreceivebyinterruptinloopbackmode*/
TestRx=CAN_Interrupt();
if(TestRx==FAILED)
{
/*TurnonledconnectedtoPA.01pin(LD2)*/
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
else
{
/*TurnoffledconnectedtoPA.01pin(LD2)*/
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
将
CAN软件仿真模拟器
调用出来.
下载(61.84KB)
2009-8-1600:
27
大家可以仿真程序,当程序中Test等于Passed那么说明Loopback模式测试通过了。
并且在CAN通讯框中我们可以看到发送和接收到的数据:
下载(51.48KB)
2009-8-1612:
27
回循模式下的源代码,基于MDK3.5:
Example7.1-CANLoopBackMode.rar
(493.79KB)
下载次数:
83
阅读权限:
10
2009-8-1612:
35
到此时说明如果大家只有一块CAN模块的时候学习可以告一个段落了,不过这个并不代表大家就已经掌握了CAN了,正真要掌握它,大家还是需要看大量的CAN部分的资料,参考手册部分的也是不够的,市面上有几本专门介绍现场总线和CAN总线的书,推荐大家买来经常翻翻看看,这样到需要实际应用的时候才可以做到如鱼得水。
(五)正常模式
完成了loopback模式的测试之后接下来我们需要学习的就是多机通讯了,当然由于我们的Mini-STM32没有将CAN接口引出来,所以我们没有办法在板子上面做这部分的试验了,只能在RealViewMDK的软件中进行模拟。
如果您拥有两块带CAN硬件的STM32的板子,您需要自己构建硬件的物理层的连接,使用三根线将CANH,CANL,GND三根线直连,当然你要接好终端电阻才能保证通讯的正常通讯,当两块板子都跳好后我们使用万用表测量下CANH和CANL之间的电阻是否为60欧姆。
多块板子多机通讯的是否你只需要在总线的主机端和最后一端接上终端电阻就可以了.
下载(24.18KB)
2009-8-1523:
11
在初始化完成后,软件应该让硬件进入正常模式,以便正常接收和发送报文。
软件可以通过对CAN_MCR寄存器的INRQ位清'0',来请求从初始化模式进入正常模式,然后要等待硬件对CAN_MSR寄存器的INAK位置'1'的确认。
在跟CAN总线取得同步,即在CANRX引脚上监测到11个连续的隐性位(等效于总线空闲)后,bxCAN才能正常接收和发送报文。
不需要在初始化模式下进行过滤器初值的设置,但必须在它处在非激活状态下完成(相应的FACT位为'0')。
而过滤器的位宽和模式的设置,则必须在初始化模式中进入正常模式前完成。
准备工作做完我们需要设置CAN通讯部份软件。
我们把TestStatusCAN_Polling(void)函数和TestStatusCAN_Interrupt(void)函数中的LoopBack模式修改为Normal模式.
//CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
接下来我们就可以做实验了.但是由于RealViewMDK的CAN模块没有办法接收,所以我们只做发送的例子.
我们的例子中分别发送两帧数据:
(1)TestStatusCAN_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)TestStatusCAN_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);
在主函数中初始化之后加上这两句发送函数:
/*CANtransmitat100Kb/sandreceivebypollinginNormalmode*/
CAN_Polling();
while(i++<1000);
/*CANtransmitat500Kb/sandreceivebyinterruptinNormalmode*/
CAN_Interrupt();
程序改完了,我们需要编译通过后,点软件仿真.
将
CAN软件仿真模拟器
调用出来.
接下来我们全速运行到while
(1)就可以看到结果了.
下载(87.37KB)
2009-8-1600:
24