打印
[STM32F4]

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

[复制链接]
25893|111
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
焊丝滚成球|  楼主 | 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总线上一定要有两个节点正常工作,否则示波器检测不到正常信号。

使用特权

评论回复
评论
合适的花少北 2019-11-29 16:11 回复TA
可以看一下can2的配置吗 
板凳
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就不会被激活。

使用特权

评论回复
评论
小唐东子 2023-4-7 16:59 回复TA
我就是单步运**在这里,如何解决呢,接了tja1050也没反应 
5
antusheng| | 2018-4-13 14:59 | 只看该作者
代码量庞大。效率不高。
这是我最讨厌的了,经常是一个寄存器搞很长名字,一堆结构体。

使用特权

评论回复
6
焊丝滚成球|  楼主 | 2018-4-16 09:05 | 只看该作者
本帖最后由 焊丝滚成球 于 2018-4-16 09:06 编辑
antusheng 发表于 2018-4-13 14:59
代码量庞大。效率不高。
这是我最讨厌的了,经常是一个寄存器搞很长名字,一堆结构体。 ...

其实除了初始化,其他的功能函数中加入了 断言,计时器以及各种判断语句,避免了异常错误,寄存器操作最好

使用特权

评论回复
7
102856| | 2018-5-25 10:59 | 只看该作者
楼主,可以把代码分享给我参考吗?新版的hal库和之前的不一样,有点不太懂

使用特权

评论回复
8
焊丝滚成球|  楼主 | 2018-6-11 10:43 | 只看该作者
102856 发表于 2018-5-25 10:59
楼主,可以把代码分享给我参考吗?新版的hal库和之前的不一样,有点不太懂 ...

链接:https://pan.baidu.com/s/1sk3yQNcgCsSRvUoQTN9Jhg 密码:48ff

使用特权

评论回复
9
kft91lx| | 2018-8-16 11:30 | 只看该作者
焊丝滚成球 发表于 2018-6-11 10:43
链接:https://pan.baidu.com/s/1sk3yQNcgCsSRvUoQTN9Jhg 密码:48ff

这个压缩包文件损坏了啊

使用特权

评论回复
10
Crown133| | 2018-9-4 19:12 | 只看该作者
焊丝滚成球 发表于 2018-4-12 12:16
补充一点:CAN1  hal库初始化失败有以下原因:
1.while ((hcan->Instance->MSR & CAN_MSR_SLAK) != RESET)  ...

我初始化卡在这了,请问这是什么意思呢,有点看不懂

使用特权

评论回复
11
aizaixiyuanqian| | 2018-9-4 20:14 | 只看该作者
can的回环测试可以就行了

使用特权

评论回复
12
xuanhuanzi| | 2018-9-4 20:29 | 只看该作者
搞定CAN,好多工作都轻松。

使用特权

评论回复
13
焊丝滚成球|  楼主 | 2018-10-6 18:43 | 只看该作者
Crown133 发表于 2018-9-4 19:12
我初始化卡在这了,请问这是什么意思呢,有点看不懂

can总线最少要有2个节点才能正常工作

使用特权

评论回复
14
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)的最后一个入参,可能导致错误。

使用特权

评论回复
评论
liver 2019-3-28 10:29 回复TA
的确会导致错误。 
15
Diyer2015| | 2018-10-15 16:02 | 只看该作者
这个资料 貌似很到位!

使用特权

评论回复
16
YANG5815| | 2018-12-5 15:59 | 只看该作者
焊丝滚成球 发表于 2018-4-11 16:07
分享一下CAN总线测试需要注意的几点:
1. 回环模式下通讯正常,但正常模式无反应,检查CAN收发器是否正常工 ...

感谢提醒,谢谢!

使用特权

评论回复
17
whj4674672| | 2019-1-7 15:12 | 只看该作者
请问一下楼主,我配置后可以发送数据,但是无法进入接收中断,HAL_Status = HAL_CAN_ActivateNotification(&hcan1,   CAN_IT_RX_FIFO0_MSG_PENDING);返回值是HAL_OK,我用HAL库1.6版本可收可发。

使用特权

评论回复
18
frfgfvfd| | 2019-3-28 15:32 | 只看该作者
感谢楼主分享经验!学习下!

使用特权

评论回复
19
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);
      }
产生的,但是不明白是为什么,不知道楼主有遇到过吗?

使用特权

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

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

使用特权

评论回复
评论
橡皮擦擦 2019-4-15 23:48 回复TA
你的这个情况解决了吗 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

53

帖子

0

粉丝