小用stm32f4-CAN控制器(使用库函数)

2019-09-30来源: eefocus关键字:stm32f4  CAN控制器  库函数

目标实验平台:stm32f4-discovery,板载STM32F407VGT6。


写的时候忘记掉可以用“报文”这个词,于是就很愚昧的都使用了一帧信息这样的表达。。意思是一样的!


这里首先说一下CAN总线。


CAN总线时一种工业总线,展开来说就是控制器局域网,Controller Area Network


常常用在汽车和工业控制的通讯中。也就是说,在汽车上,各种控制器常常是通过CAN总线进行通讯的。


具体到他是谁发明的有什么历史就不详述了,百度百科一大堆我自己看了也记不清~


只是这两天在调两个STM32通过CAN总线进行最简单的收发通信,这里就简要介绍一下其通信的建立过程


也就是简单的收发功能,至于其中更复杂的错误检测等功能我也只看过介绍没有具体实验过,也就不说了。


如果能有机会用到,也会来再记录的。




CAN总线和I2c等总线有所不同,各个节点的通信并不是通过确定发送目标机地址来确定收发方向。


他是采取一种广播的方式,也就是说一个节点向总线发送信号,所有节点都能收到。


但是如果这个信号对自己无用怎么办呢?事实上,在CAN总线上传输的信号并不仅仅只有所需要的数据、控制信号等,


更重要的是一帧信号还有一串标识符ID,每个节点可以设置自己想要接收什么样标识符的信息


而将不需要的信息通过节点中的过滤器处理掉,就不用担心无用数据的干扰了。这样比需要地址总线通讯方式的好处就是如果同样信息不需要一个一个地址重复发送,只要一次发送就行了,提高效率。

在一个CAN的节点上,除了CPU以外,还需要一个CAN控制器和一个CAN收发器,CAN控制器可以根据当前总线上的数据传输情况以及现在控制器中发送邮箱及接受缓冲器等的情况来实时调整发送和接收。而CAN总线上的电平并不是TTL电平故需要一个CAN收发器进行电平转换的功能。


使用STM32进行CAN通讯的好处之一就是他自带有CAN控制器,而在外面只需要一个CAN收发器即可。至于其他没有CAN控制器的MCU,就需要配备如SJA1000等额外的CAN控制器了。


我这里使用的CAN收发器选用TJA1050,外部接线非常简单,如下图

其中TXD、RXD引脚连接STM32的CANTXCANRX。电源滤波电容可选取0.1uF。Vref可不接,S(RS)端可接GND或不接。至于CANHCANL之间的120欧姆电阻,在节点为CAN总线终端时接上,否则不接。电路非常简单,可以自己制作,我自己淘宝花了10块钱买了两个TJA1050芯片,其中有6元是运费。如果直接买TJA1050的模块的话,基本上网上都是10元一个,还要运费,加起来都快30了,真是不值呀~


进行双机通信时,两个CAN收发器的CANH、CANL连接即可。


如果没有条件进行双机通信,可以在STM32进行CAN控制器初始化时设置成回环模式,也就是STM32的CAN-TX在芯片内部与CAN-RX进行直接连接,而外部的CAN-RX引脚不影响内部。同时可以在外部TX引脚上通过示波器测得输出信号波形。此种方法可以在一定程度上用于测试程序正确与否(因为他隔绝了外部电路的影响,比如因为电路不正确等,但也同时无法使用其总线错误检测等功能)。建议先通过CAN的回环测试,再进行双机通信。


下面再介绍一下stm32的CAN控制器。分为CAN1(主)和CAN2(从)。每个CAN控制器有3个发送邮箱用于存放需要发送的信息。发送顺序可以由软件设置为根据信息优先级还是根据信息的请求时间。它还有2个用于接收的缓冲器队列FIFO0和FIFO1,每个FIFO可以存放3帧信息,如果存满,新来的信息可能会丢失或者被覆盖(依据软件设置)。


他可以被CAN控制器的过滤器(共28组,也就是可以设置28个标识符ID)关联,通过该过滤器的信息就会被存入相应的FIFO中。


再说一下stm32的CAN过滤器。


他共有28组过滤器,每组过滤器有2个32位的存储器。每组过滤器可以设置为:


1、两个32位完全匹配的过滤器 (用于扩展帧)2、4个16位完全匹配的过滤器 (用于标准帧)3、一个32位有位屏蔽功能的过滤器


这里再提一下,CAN总线的数据帧有两种,一种是11位标识符的,叫标准帧,另一种除了11位以外还有18位共计29位标识符的叫扩展帧。


所谓完全匹配,即总线上一帧信息的标识符必须与28个过滤器中某一个标识符每一位都相同,才会被过滤器接收到FIFO中。所谓位屏蔽,就是只需要与设定的标识符中某几位相同即可被接收进FIFO中。


絮絮叨叨说了这么多,想必对STM32的CAN控制器也有所了解了。下面根据所写的代码进行操作步骤讲解吧:D


我用的是CAN1,使用FIFO0存放接收到的数据


首先是主函数中,首先先通过CAN_Config和NVIC_Config对CAN控制器及其中断进行初始化配置。其他的CAN_打头的函数来源于STM32的函数库,具体功能见注释。

void main()  

{   

  uint8_t TransmitMailbox = 0;

 

 

  USART1_Config();//初始化串口,与电脑进行通信,方便调试  下面的printf函数被重载到发送信息到串口

  NVIC_Config();

  CAN_Config();

  RxReset();//将接收缓冲区清空

  CAN_FIFORelease(CAN1,CAN_FIFO0 );//清空接收FIFO

  PackTxMessage();//打包要发送的数据到全局结构体变量TxMessage中

  TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);//发送数据,如果发送成功返回存入的邮箱号

  while((CAN_TransmitStatus(CAN1, TransmitMailbox)  !=  CANTXOK))//判断是否成功发送

   {

     printf("nrnrStill transmittingnr");

   }

  printf("nrTransmit OK!nr");

  while(1);

}


下面是CAN_Config函数

首先需要配置使用的GPIO的复用功能,然后配置CAN控制器的收发模式以及过滤器,并打开接收中断。

配置过程可以参照STM32F4的函数库文件stm32f4xx_can.c中前面注释中的介绍“How to use this 。。。”就可以知道要对CAN控制器进行初始化需要用到哪些函数。这也是一个很重要的学习使用STM32外设的方法,就是阅读每一个库文件的源代码及其介绍。


一个经验就是,现在网上STM32的代码和相关资料大部分是针对STM32F10x芯片的,这里使用的F407的寄存器以及库函数与他们有一些不同,如果生搬硬套,首先就可能无法通过编译,提示某些变量或者函数没有定义。即使通过了编译,也很有可能因为某些在F10x中没有的函数没有使用而导致外设无法正常运行。



void CAN_Config()

{

  CAN_GPIO_Init();

  CAN_ModeAndFilterInit();

}

void CAN_GPIO_Init()

{

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//打开CAN外设时钟

  //RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);//

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_CAN1);//配置功能复用

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_CAN1);

  

  GPIO_InitTypeDef CANIO;

  CANIO。GPIO_Pin = GPIO_Pin_8;

  CANIO.GPIO_Mode = GPIO_Mode_AF;

  CANIO.GPIO_PuPd = GPIO_PuPd_UP;

  CANIO。GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOB,&CANIO);

  //Config CANTX

  CANIO.GPIO_Pin = GPIO_Pin_9;

  CANIO.GPIO_Mode = GPIO_Mode_AF;

  CANIO。GPIO_OType = GPIO_OType_PP;

  GPIO_Init(GPIOB,&CANIO);

}

void CAN_ModeAndFilterInit()

{

    CAN_InitTypeDef        CAN_InitStructure;

    CAN_FilterInitTypeDef  CAN_FilterInitStructure;

    CAN_DeInit(CAN1);//首先使用默认配置,减少配置数量

   

  /* CAN cell init */

   CAN_InitStructure.CAN_TTCM = DISABLE;//关闭时间触发通信使能(我也不知道这个干嘛用的。。)

   CAN_InitStructure。CAN_ABOM = ENABLE;//自动离线管理,也就是如果检测到总线上出错,本节点自动离线

  CAN_InitStructure。CAN_AWUM = ENABLE;//设置当需要时自动唤醒,如果DISABLE,则需要软件唤醒

   CAN_InitStructure。CAN_NART = DISABLE;//如果报文发送不成功,就自动重发

   CAN_InitStructure.CAN_RFLM = DISABLE;//在接收的FIFO中如果溢出,自动覆盖原有报文

  CAN_InitStructure.CAN_TXFP = DISABLE;//发送邮箱优先级取决于报文标识符

   CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//正常工作模式,如果是回环模式,这里要更改为CAN_Mode_Loopback

/* CAN Baudrate = 700kbps (CAN clocked at 42 MHz) */

/*以下5行设置CAN传送速率为700kbps,CAN的最高传输速率为1Mbps*/

   CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

CAN_InitStructure。CAN_BS1 = CAN_BS1_6tq; CAN_InitStructure。CAN_BS2 = CAN_BS2_8tq; CAN_InitStructure。CAN_Prescaler = 4; CAN_Init(CAN1, &CAN_InitStructure); /* CAN filter init *///设置CAN过滤器 CAN_FilterInitStructure。CAN_FilterNumber = 1;//使用1号过滤器,(共28组,编号0~27) CAN_FilterInitStructure。CAN_FilterMode = CAN_FilterMode_IdMask;//标识符屏蔽位模式 CAN_FilterInitStructure。CAN_FilterScale = CAN_FilterScale_32bit;//32位标识符

/*以下4句分析见后文,用于设置过滤器的标识符和屏蔽位*/

   CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)0x1314<<3)&0xffff0000)>>16;//0x0000;

CAN_FilterInitStructure。CAN_FilterIdLow = ((

[1] [2]
关键字:stm32f4  CAN控制器  库函数 编辑:什么鱼 引用地址:http://news.2689mr.com/mcu/ic476229.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32的CAN总线的接收双FIFO使用方法
下一篇:stm32与伺服驱动器进行can通信

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

stm32F4+lcd1602实现采集两路adc并显示
以STM32F403为控制核心,设计一种基于STM32的智能照明控制系统,使用光敏电阻作为光照信息来源,使用GP2D12作为人物信息来源,当光照强度改变时,光敏电阻的阻值改变,从而改变STM32的采样电压。当人物移动时,红外传感器的电压改变从而改变采样电压。当光照强度小于一定值,且感应到有人时,LED亮。通过光敏电阻和GP2D12传感器获取光照和红外信息,作为模拟量,传入STM32F4的采集端口。STM32F4进行模数转换后,在LCD1602上进行显示。采用了HAL库进行配置STM32F4,一直有个问题就是proteus仿真DS18B20和DHT11这种带有时序要求的传感器,同STM32通信时出现时序错误,有经验的师兄可以告知一下
发表于 2020-07-22
<font color='red'>stm32F4</font>+lcd1602实现采集两路adc并显示
stm32F4之使用I2C读写24C02
一.24C02简单介绍1.串行E2PROM是基于I2C-BUS 的存储器件,2.可以支持100万次擦除,数据可以保存100年,3.支持每次读写1字节4.写周期最大5ms(即最好保证在5ms后进行读写,否则可以数据将会读取错误)二.24C02的读写时序图从手册中可以找到以下两个读写图,我也将以以下两个图为例进行函数编写,其他读写图请查手册 三.用模拟的I2C协议封装24C02的读与写该设备为IIC设备,因此我们要先确定其设备地址,STM32F4探索者的开发板上为2K的E2PROM,A2=A1=A0  因此设备地址为(0XA0/0xA1)根据下图进行编程:字节写:使用封装好的I2C函数,进行函数24C02的写函数
发表于 2020-07-03
<font color='red'>stm32F4</font>之使用I2C读写24C02
STM32F4硬件IIC+DMA使用
1.STM32硬件IIC一直被大家说存在问题,实际测试发现确实是有这种情况,借助网上很多人的经验,终于把硬件IIC写完了。2.使用DMA时,发现发送数据(写寄存器)时序和实际不符,比如发送4字节数据时,如果DMA缓冲区单字节长度配置为4,则实际时序发现只有三个,需要将DMA缓冲区单字节长度配置为5,才可以正常使用3.当然,如果使用STM32的HAL库,这些问题其实都可以避免,因为底层ST已经做了超时及错误的处理。4.使用的IIC为自定义的格式,写寄存器操作为:START+ACK(从机的ACK信号)+IIC设备地址+(从机的ACK信号)+START+ACK(从机的ACK信号)+IIC写寄存器地址+ACK(从机的ACK信号)+IIC写
发表于 2020-07-03
STM32F4学习笔记之GPIO(使用固件库)
1.使能GPIO的AHB时钟,使用函数:    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);2.配置GPIO工作模式用GPIO_Init()函数数据类型说明typedef struct{  uint32_t GPIO_Pin;              //引脚配置GPIOMode_TypeDef GPIO_Mode;  //GPIO_Mode_IN(输入),GPIO_Mode_OUT(输出),GPIO_Mode_AF(备用),GPIO_Mode_AN(模拟
发表于 2020-06-14
调用STM32F4 库函数FLASH_ProgramWord() 出错问题
最近操作STM32F4的内部flash,吓了一跳。以前的STM32F107的时候还是4k一页,现在只分了12个Sector,后面几个128K这么大。从官网下了Flash programming manual,擦除之前得清除flash flag/* Clear All pending flags */FLASH_ClearFlag( FLASH_FLAG_EOP |  FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);同时查看擦除函数,看着函数说明,正确的传参数就OK了/**  * @brief 
发表于 2020-06-09
stm32f4启动代码分析(一)
因为使用的开发板是stm32f407discovery,所以启动代码为st公司的官方库文件里的startup_stm32f40_41xxx.s,至于如何去找官方库文件,不在本节讨论的范围内,本节只是初步的分析startup_stm32f40_41xxx.s,其中更深入的东西需要在以后的章节中分析。在startup_stm32f40_41xxx.s中,有一段注释:;* File Name : startup_stm32f40_41xxx.s;* Author : MCD Application Team;* @version : V1.7.0;* @date : 22-April-2016;* Description
发表于 2020-05-08
小广播
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 2689mr.com, Inc. All rights reserved
送彩金500的网站大白菜不看id 彩票大赢家走势图 澳客彩票 2019年无需申请送彩金 娱乐平台充值送彩金 赛车网站首存送彩金 买彩票充值送彩金 博彩送彩金全讯网 博彩送彩金38元 新会员充值送彩金平台