STM32F4 CubeMX HAL CAN 使用步骤

2019-09-30来源: eefocus关键字:STM32F4  CubeMX  HAL  CAN  使用步骤

(这仅仅是一个最简单的CAN示例Demo程序,仅作参考。最新的HAL库CAN的部分有所改变,不能直接使用该文方法。)


STM32CubeMX版本:

固件库版本:

第一步分:CubeMX软件配置。


0、工程配置以及芯片选择这里就不再赘述了,最好是勾选为每个外设生成独立的.c源文件。


1、打开CAN外设。

2、配置芯片时钟树。这里我使用了芯片内部HSI RC,主时钟配置为168MHz。

3、CAN配置。

3.1配置波特率为1Mb/s。计算方法:42M/2/(14+6+1)==1M

3.2、使能RX0接收中断。

到这里配置已经完成了,这里我们只配置了部分选项,其余大部分都是采用的默认配置。点击工具栏中齿轮图标,生成代码。


第二部分:代码修改。


1、打开工程,打开can.c文件,在/* USER CODE BEGIN 0 */   和 /* USER CODE END 0 */ 之间添加以下内容。


#include "main.h"

#define F407VET6_BOARD_CAN_ID      0x001

#define SENSOR_BOARD_CAN_ID      0x002

#define ANOTHER_SENSOR_BOARD_CAN_ID       0x003

#define THIRD_SENSOR_BOARD_CAN_ID    0x004

 

//2个3级深度的FIFO

#define   CAN1FIFO   CAN_RX_FIFO0            

#define   CAN2FIFO   CAN_RX_FIFO1  // 

CAN_TxHeaderTypeDef     TxMeg;

CAN_RxHeaderTypeDef     RxMeg;

 

void CAN_User_Init(CAN_HandleTypeDef* hcan )   //用户初始化函数

{

 CAN_FilterTypeDef  sFilterConfig;

 HAL_StatusTypeDef  HAL_Status;

  TxMeg.IDE=CAN_ID_STD;//CAN_ID_EXT;

  TxMeg.RTR=CAN_RTR_DATA;

  sFilterConfig.FilterBank = 0;                       //过滤器0

  sFilterConfig.FilterMode =  CAN_FILTERMODE_IDLIST;  //设为列表模式    

  sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;    

  sFilterConfig.FilterIdHigh = F407VET6_BOARD_CAN_ID<<5;   //基本ID放入到STID中  

  sFilterConfig.FilterIdLow  = SENSOR_BOARD_CAN_ID <<5;    

  sFilterConfig.FilterMaskIdHigh =ANOTHER_SENSOR_BOARD_CAN_ID<<5;

  sFilterConfig.FilterMaskIdLow  =THIRD_SENSOR_BOARD_CAN_ID <<5; 

  sFilterConfig.FilterFIFOAssignment = CAN1FIFO;    //接收到的报文放入到FIFO0中 

 

  sFilterConfig.FilterActivation = ENABLE;  //激活过滤器

  sFilterConfig.SlaveStartFilterBank  = 0; 

 

  HAL_Status=HAL_CAN_ConfigFilter(hcan, &sFilterConfig);

  HAL_Status=HAL_CAN_Start(&hcan1);  //开启CAN

  if(HAL_Status!=HAL_OK){

printf("开启CAN失败rn");

 }

 HAL_Status=HAL_CAN_ActivateNotification(&hcan1,   CAN_IT_RX_FIFO0_MSG_PENDING);

 if(HAL_Status!=HAL_OK){

printf("开启挂起中段允许失败rn");

  }

 }

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)  //接收回调函数

{

uint8_t  Data[8];

HAL_StatusTypeDef HAL_RetVal;

if(hcan ==&hcan1){

  HAL_RetVal=HAL_CAN_GetRxMessage(&hcan1,  CAN1FIFO, &RxMeg,  Data);

  if ( HAL_OK==HAL_RetVal)

  {                             

      //在这里接收数据

   }

}

//发送数据函数

uint8_t CANx_SendNormalData(CAN_HandleTypeDef* hcan,uint16_t ID,uint8_t *pData,uint16_t Len)

{

HAL_StatusTypeDef HAL_RetVal;

        uint16_t SendTimes,SendCNT=0;

uint8_t  FreeTxNum=0;

TxMeg.StdId=ID;

if(!hcan || ! pData ||!Len)  return 1;

SendTimes=Len/8+(Len%8?1:0);

FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);

TxMeg.DLC=8;

while(SendTimes--){

if(0==SendTimes){

if(Len%8)

TxMeg.DLC=Len%8;

}

while(0==FreeTxNum){

FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);

}

HAL_Delay(1);   //没有延时很有可能会发送失败

HAL_RetVal=HAL_CAN_AddTxMessage(&hcan1,&TxMeg,pData+SendCNT,(uint32_t*)CAN_TX_MAILBOX0); 

if(HAL_RetVal!=HAL_OK)

{

return 2;

}

SendCNT+=8;

}

  return 0;

}

2、在main.c中的  /* USER CODE BEGIN 2 */  和 /* USER CODE END 2 */ 之间调用用户初始化CAN函数:CAN_User_Init( &hcan1 ) 。


在主循环中定时调用发送数据函数

uint8_t CANx_SendNormalData(CAN_HandleTypeDef* hcan,uint16_t ID,uint8_t *pData,uint16_t Len)发送数据即可。


需要注意的是CAN的收发必须要有发送者和接收者,否则失败。

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

上一篇:STM32F4 CAN2配置
下一篇:cubemx实现CAN通讯

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

推荐阅读

STM8S003F3使用总结——串口
STM8作为低成本芯片一直受到广大用户青睐,最近一个项目使用了STM8S003F3P6这款芯片,主要实现的功能就是串口接收指令控制PWM输出。这里对这款芯片使用过程中遇到的问题进行总结。编译环境:IAR for STM8 3.10.2库版本:V2.2.01.STM8S003F3与STM8S103F3差异除了以上差异,两款芯片可pin-to-pin兼容,片内外设资源一致。2.串口通信STM8S003F不支持DMA,因此使用中断方式接收。中断向量表如下:typedef enum { UART1_IT_TXE        = (uint16_t)0x0277, /*!< Transmit
发表于 2019-11-30
STM8S003F3使用总结——串口
stm8s003f3使用杂记
转换模式,怎么从缓存区读回各路转换结果?用GETBUFFERVALUE(直接写寄存器组的序号就行)函数。之前要调用相应的配置函数:ADC1_DataBufferCmd(FunctionalState NewState);参考RM0016——page366中关于数据缓存寄存器的介绍。此时要用DMA传送结果。8:为什么已经修改了stm8s.h文件,ADC1部分的定义还是会在编译时提示没有定义呢?甚至把那部分的定义放到主函数里也不行呢。这种无厘头的问题------重新建个工程就行了。>我*?!!!事实再一次证明,新建工程也不管用啊!!!conf没改好吧??(我已经放弃了,包含了iostm8s003f3的源文件然后用寄存器写的
发表于 2019-11-30
STM8S003F3 使用内置的Data EEPROM的操作接口
操作系统:win10 64bit平台:STM8S003F3 IDE: IAR For STM8/* Data EEPROM 操作初始化 */void Init_Flash(void){  FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);} /************************************************函数名称 : EE_FLASH_WriteNByte功    能 : 写EEPROM参    数 : pBuffer ----- 写入数据区首地址   
发表于 2019-11-30
详细分析stm32f10x.h
/**这里是STM32比较重要的头文件   ******************************************************************************  * @file    stm32f10x.h                  ST 标准的头文件  * @author  MCD Application Team 
发表于 2019-11-28
stm8s103f3p6的延时函数
使用stm8s时本来期望能够产生1us精度的脉冲,但是调来调去也没能实现。目前的情况是使用内部16MHz的RC时钟源,然后给到timer4,再经 8分频产生一个25us的中断,我能搞出来的最小中断周期是15us左右,考虑到那不是一个很好的整数,主要是当要延时整数比如100,1000时没办法除尽,所以就只好取25us为一个最小单位了。如果有人能用定时器产生1us的脉冲请指点一下。多谢。 下面上代码吧: 基本的思路就是使用timer4每隔25us计数一次,然后延时函数对timer4的中断次数进行统计。完成指定的延时时间后退出while循环。#include"stm8s.h"uint8_t
发表于 2019-11-28
STM8S103F3P6核心板原理图设计
Encounter problems:1.无法执行DRC检查2.图纸页面无法设置Solution:1.选中.dsn文件,即便可以执行DRC检查2.设置schematic page properties   3.瓷片电容封装RAD是瓷片电容的封装,一般104.103.222.33.这些的封装是RAD0.1,而RAD0.2的就是比较大,可以说是元器件管脚的距离是200mil。。RAD0.1封装是无极性电容,0.1是指这个电容在电路板上的焊盘间距为100mil(1mil=0.0254mm)。RB.1/.2封装是指有极性电容,后面的.1/.2是指这个电容在电路板上两引脚之间的间距是100mil,它的外径是200mil。
发表于 2019-11-27
STM8S103F3P6核心板原理图设计
小广播
何立民专栏 单片机及嵌入式宝典

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

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