[STM32F4] 最新CUBEMX的HAL的CAN总线配置接受发送(STM32F412)

[复制链接]
 楼主| 焊丝滚成球 发表于 2018-4-11 15:59 | 显示全部楼层 |阅读模式
STM32F412 精简版本 功能完整。来说一下CAN外设的配置以及收发。
   HAL库发展到现在BUG越来越少,大大减少了用户的开发量,但是缺点明显,代码量庞大。效率不高。

配置CAN总线首先要明确APB1的外设时钟,通过APB1的时钟来选择CAN的波特率。
BaudRate = APBCLK/BRP*(1+BS1+BS2);
BaudRate为CAN总线上的波特率。

配置CAN总线有以下几个注意事项:
1.CAN_HandleTypeDef中的AutoBusOff 参数为自动离线管理。
当错误帧超过255的时候就会离线,设置此参数ENABLE 就可以在总线挂起时清零重新ongoing。
2. CAN_FilterTypeDef 中的SlaveStartFilterBank 为从过滤器配置,用来选择从过滤器的寄存器号
当选择双CAN模式的时候,这个参数要跟CAN2的filternumber 一致。

CAN启动过程需要如下几个函数
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);

HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs);

CAN发送的时候需要如下函数:
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);

注意一下最后一个参数  uint32_t *pTxMailbox ,这个pTxMailbox  在头文件中为32位的无符号整型,需要强制转换为指针。
CAN接收的时候需要如下函数:
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);

特别的一点最新的HAL库跟以前的CAN的配置不同,ST将接收发送的数据帧的数据部分分离出来,需要用户自己定义。
定义一个DLC长度的数组就可以,如下:
typedef struct
{
        uint8_t Data[8];
}CAN_RecvMsg;



完整的启动过程:
初始化完毕之后
开启CAN:HAL_CAN_Start(&hcan1);
开启挂起中段允许:HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
发送数据:
void CAN_TRANSMIT(void)

  TxMessage1.DLC=8;
  TxMessage1.StdId=0x018;
  TxMessage1.ExtId=0x00002018;
  TxMessage1.IDE=CAN_ID_EXT;
  TxMessage1.RTR=CAN_RTR_DATA;
   uint8_t TR_BUF[8]="20180411";

   if(HAL_CAN_AddTxMessage(&hcan1,&TxMessage1,TR_BUF,(uint32_t*)CAN_TX_MAILBOX0)!=HAL_OK)
  {
     printf("發送失敗");
  }
  }

接收数据:(双CAN,两个接收邮箱)

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  if(hcan->Instance==CAN1)
  {
     HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&RxMessage1,can_recvmsg.Data);
     printf("\r\n%s",can_recvmsg.Data);
  }
}



void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  if(hcan->Instance==CAN2)
  {
     HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO1,&RxMessage1,can_recvmsg.Data);
     printf("\r\n%s",can_recvmsg.Data);
  }
}



 楼主| 焊丝滚成球 发表于 2018-4-11 16:07 | 显示全部楼层
分享一下CAN总线测试需要注意的几点:
1. 回环模式下通讯正常,但正常模式无反应,检查CAN收发器是否正常工作。
2.正常模式下,can总线上一定要有两个节点正常工作,否则示波器检测不到正常信号。

评论

可以看一下can2的配置吗  发表于 2019-11-29 16:11
mmuuss586 发表于 2018-4-11 23:22 | 显示全部楼层
感谢楼主分享经验;
 楼主| 焊丝滚成球 发表于 2018-4-12 12:16 | 显示全部楼层
补充一点:CAN1  hal库初始化失败有以下原因:
1.while ((hcan->Instance->MSR & CAN_MSR_SLAK) != RESET)  {
    if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
    {
      /* Update error code */
      hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;

      /* Change CAN state */
      hcan->State = HAL_CAN_STATE_ERROR;

      return HAL_ERROR;
    }
  }

程序卡在这里TIMEOUT之后直接ERROR ,
这段代码是检测CAN是否在SLEEP模式,不上拉引脚
CAN就不会激活,接上收发器之后无需上拉也可以。

CAN的自动休眠 即总线不成立,CAN就不会被激活。

评论

我就是单步运**在这里,如何解决呢,接了tja1050也没反应  发表于 2023-4-7 16:59
antusheng 发表于 2018-4-13 14:59 | 显示全部楼层
代码量庞大。效率不高。
这是我最讨厌的了,经常是一个寄存器搞很长名字,一堆结构体。
 楼主| 焊丝滚成球 发表于 2018-4-16 09:05 | 显示全部楼层
本帖最后由 焊丝滚成球 于 2018-4-16 09:06 编辑
antusheng 发表于 2018-4-13 14:59
代码量庞大。效率不高。
这是我最讨厌的了,经常是一个寄存器搞很长名字,一堆结构体。 ...

其实除了初始化,其他的功能函数中加入了 断言,计时器以及各种判断语句,避免了异常错误,寄存器操作最好
102856 发表于 2018-5-25 10:59 | 显示全部楼层
楼主,可以把代码分享给我参考吗?新版的hal库和之前的不一样,有点不太懂
 楼主| 焊丝滚成球 发表于 2018-6-11 10:43 | 显示全部楼层
102856 发表于 2018-5-25 10:59
楼主,可以把代码分享给我参考吗?新版的hal库和之前的不一样,有点不太懂 ...

链接:https://pan.baidu.com/s/1sk3yQNcgCsSRvUoQTN9Jhg 密码:48ff
kft91lx 发表于 2018-8-16 11:30 | 显示全部楼层
焊丝滚成球 发表于 2018-6-11 10:43
链接:https://pan.baidu.com/s/1sk3yQNcgCsSRvUoQTN9Jhg 密码:48ff

这个压缩包文件损坏了啊
Crown133 发表于 2018-9-4 19:12 | 显示全部楼层
焊丝滚成球 发表于 2018-4-12 12:16
补充一点:CAN1  hal库初始化失败有以下原因:
1.while ((hcan->Instance->MSR & CAN_MSR_SLAK) != RESET)  ...

我初始化卡在这了,请问这是什么意思呢,有点看不懂
aizaixiyuanqian 发表于 2018-9-4 20:14 | 显示全部楼层
can的回环测试可以就行了
xuanhuanzi 发表于 2018-9-4 20:29 | 显示全部楼层
搞定CAN,好多工作都轻松。
 楼主| 焊丝滚成球 发表于 2018-10-6 18:43 | 显示全部楼层
Crown133 发表于 2018-9-4 19:12
我初始化卡在这了,请问这是什么意思呢,有点看不懂

can总线最少要有2个节点才能正常工作
founderHAN 发表于 2018-10-15 15:27 | 显示全部楼层
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);

查看接口源码:
      /* Store the Tx mailbox */
      *pTxMailbox = 1U << transmitmailbox;

所以入参的pTxMailbox需要自行定义变量,将地址传入,
HAL_CAN_AddTxMessage(&hcan1,&TxMessage1,TR_BUF,(uint32_t*)CAN_TX_MAILBOX0)的最后一个入参,可能导致错误。

评论

的确会导致错误。  发表于 2019-3-28 10:29
Diyer2015 发表于 2018-10-15 16:02 | 显示全部楼层
这个资料 貌似很到位!
YANG5815 发表于 2018-12-5 15:59 | 显示全部楼层
焊丝滚成球 发表于 2018-4-11 16:07
分享一下CAN总线测试需要注意的几点:
1. 回环模式下通讯正常,但正常模式无反应,检查CAN收发器是否正常工 ...

感谢提醒,谢谢!
whj4674672 发表于 2019-1-7 15:12 | 显示全部楼层
请问一下楼主,我配置后可以发送数据,但是无法进入接收中断,HAL_Status = HAL_CAN_ActivateNotification(&hcan1,   CAN_IT_RX_FIFO0_MSG_PENDING);返回值是HAL_OK,我用HAL库1.6版本可收可发。
frfgfvfd 发表于 2019-3-28 15:32 | 显示全部楼层
感谢楼主分享经验!学习下!
gaoruisolax 发表于 2019-3-29 14:39 | 显示全部楼层
感谢楼主分享~
我最近也在使用最新的CAN库,可是会出现HardFaul()里,是由于HAL_CAN_AddTxMeddage()中的
      /* Set up the Id */
      if (pHeader->IDE == CAN_ID_STD)
      {
        hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->StdId << CAN_TI0R_STID_Pos) |
                                                           pHeader->RTR);
      }
      else
      {
        hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->ExtId << CAN_TI0R_EXID_Pos) |
                                                           pHeader->IDE |
                                                           pHeader->RTR);
      }
产生的,但是不明白是为什么,不知道楼主有遇到过吗?

评论

请问楼主,出现HardFault的问题解决了吗?我也遇到相同问题呢。  发表于 2019-5-15 18:32
liver 发表于 2019-4-6 21:00 | 显示全部楼层
gaoruisolax 发表于 2019-3-29 14:39
感谢楼主分享~
我最近也在使用最新的CAN库,可是会出现HardFaul()里,是由于HAL_CAN_AddTxMeddage()中的
...

前几天还好好的,今天也遇到这个问题了,你解决了么

评论

你的这个情况解决了吗  发表于 2019-4-15 23:48
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

53

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

15

主题

53

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部