0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何设置CAN引脚功能?如何在中断中获取CAN数据?

冬至子 来源:郝飞的俱俱 作者:hf 2023-08-10 17:34 次阅读

MCU:MCU通过APB总线访问CAN外设。② CAN外设:挂载在MCU的APB总线上,实现基本协议CAN2.0A、扩展协议CAN2.0B、接收滤波器、发送优先级及对CAN FD的支持等,并留出外设访问接口给MCU,以便MCU控制。③ CAN收发器:看其收发器框图,因仅包含CANH、CANL总线,所以TXD发出的CANH、CANL与RXD读出的CANH、CANL是连接在一起的,因此CAN收发器TXD发送出来的总线信号会立即被转换从RXD输出给CAN接口(LBME环回模式使用此特性)

图片

MCU通过APB总线访问CAN外设,通过配置相关寄存器配置CAN的运行环境,通过写BUF及相关配置位发送CAN帧;通过轮询某些状态位或者中断,读取收到的BUF或者CAN外设目前处于的状态,并依据部分状态作出相应的动作;CAN收发器将CAN外设的CAN_TX高低电平信号转换为CANH、CANL总线信号,并将接收到的CANH、CANL总线信号转换为CAN外设的CAN_RX高低电平信号,该信号输送给CAN外设,CAN外设根据CAN接收滤波器的设置判断是否接收该数据帧等等。

1、查看原理图,看使用哪一个CAN接口。STB使用的引脚

图片

#define CAN1_TX      (GPIO_PC15)  //pin 75
#define CAN1_RX      (GPIO_PC14)  //pin 74
#define CAN1_STB     (GPIO_PD5)   // pin9

2、进行初始化操作

CAN_InitHardwr();

定义两个结构体变量,CAN_Config和CAN_BaudrateConfig

  1. 初始化硬件接口
    GPIO_SetFunc(CAN1_TX, GPIO_FUNC_1);//设置CAN1引脚复用功能
     GPIO_SetFunc(CAN1_RX, GPIO_FUNC_1);
     GPIO_SetDir(CAN1_STB, GPIO_OUTPUT);//设置CAN1收发器控制为IO控制
     //GPIO_FUNC_1 参考数据手册中“信号多路复用和引脚分配”,使用function 1功能
    
  2. 使能CAN收发器
    CAN1_TRASCVER_NML;//使能CAN收发器
    //#define CAN1_TRASCVER_NML   do{GPIO_ResetPinBits(CAN1_STB);}while(0)
    
  3. 设置波特率和采样点进行配置
/*
   设置波特率为500K,采样点为81.25%.
   tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
   BandRate  = (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1)))
   SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
   在已经知道波特率与采样点的情况下,经过计算后:tSeg1 = 13,tSeg2 = 3.
    */
   canBandrateConfig.S_PRESC  = 5;//分频后时钟为8M.
   canBandrateConfig.S_SEG_1  = 11;
   canBandrateConfig.S_SEG_2  = 2;
   canBandrateConfig.S_SJW  = 2;//满足S_SJW <= tSeg2即可.
  1. 过滤器设置:选择哪一个过滤器、指定过滤模式、过滤的ID类型
    16个过滤器中,可随意选择使用哪个,并制定其过滤模式,制定其过滤ID的类型.
     如果一个过滤器只需要接收一个ID,直接可将其设置CODE模式,然后根据ID类型设置过滤类型.
     如果一个过滤器需要接收多个ID,将其设置为MASK模式,并根据这几个ID的实际类型设置过滤ID类型,如果既有STD又有EXT,则应选择FILTER_IDE_STD_EXT_BOTH.
     此处加宏是为了更清楚的说明各种设置是否有效,在实际应用中,可将各种组合放在一起使用.
     #if (RECV_FRM_KIND_SEL == ONLY_RECV_STD_FRM)
     CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD帧
     CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID2);//使用CODE模式只接收STD帧
     #endif
     #if (RECV_FRM_KIND_SEL == ONLY_RECV_EXT_FRM)
     CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID11);//使用CODE模式只接收EXT帧
     CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID12);//使用CODE模式只接收EXT帧
     #endif
     #if (RECV_FRM_KIND_SEL == RECV_STD_EXT_BOTH_FRM)
     CAN_SetFilterParam( 0, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID1 & CAN1_RECV_DATA_ID11));//使用MASK模式接收两种帧
     CAN_SetFilterParam( 1, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID2 & CAN1_RECV_DATA_ID12));//使用MASK模式接收两种帧
     #endif
    
  2. CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD帧
* @prototype CAN_SetFilterParam(uint8_t filterNum, uint8_t filterEn, CAN_FilterMode_TypeDef filterMode, CAN_FilterMask_TypeDef filterMask, uint32_t ID)
  *
  * @param[in] filterNum:过滤器编码,015可用.
  * @param[in] filterEn:过滤器使能状态,1使能,0禁能
  * @param[in] filterMode:CAN_FilterMode_TypeDef已定义.
  * @param[in] filterMask:参考CAN_FilterMask_TypeDef.
  * @param[in] ID
  * @return  void

参数说明:0:选用的过滤器编码

1:1标识使能,0为禁止

CAN_FILTER_CODE_MODE:分code模式和mask模式,code只能接收一个ID,mask可以接收多个ID

FILTER_IDE_STD_ONLY:分标准帧、扩展帧、混合帧

ID:需要过滤的ID,表示这个ID可以通过,单片机可以接收到数据。

  1. 设置can配置
    canConfig.interruptEnable = TRUE;//使能中断
     canConfig.TSSS = TRUE;//使用次发送缓冲区发送
     canConfig.canMode = CAN_MODE_NORMAL;
     canConfig.autoReset = TRUE;//CAN BUSOFF后,自动恢复
     canConfig.filterList = g_canFilterTab;//赋值过滤器设置list
    
  2. 设置回调函数CAN_SetEventCallBack(CAN1, CAN1_IRQnCallBack);
  3. /**
    * @prototype CAN1_IRQnCallBack(uint32_t event, uint32_t wparam, uint32_t lparam)
    *
    * @param[in] ...
    * @return  ...
    *
    * @brief    CAN1 module interrupt handler.
    *    CAN1中断处理函数.
    */
    int32_t CAN1_IRQnCallBack(uint32_t event, uint32_t wparam, uint32_t lparam)
    {
     if (event & CAN_EVENT_RECVMSG)
     {
      if (CAN_IsMsgInReceiveBuf((CAN_Type*)lparam))
            {
                CAN_MessageRead((CAN_Type*)lparam, &g_recvCANMsgInfo);
    
       g_recvedCANDataRdy = TRUE;
            }
     }
    
     return 1;
    }
    
  4. 调用库函数CAN_Initialize()。

CAN_Initialize(CAN1, &canConfig, &canBandrateConfig);//程序引用

CAN_Initialize(CAN_Type *CANx, CAN_Config *config, const CAN_BaudrateConfig *baudrate)//函数原型

参数说明:

  • @param[in] CANx: CAN type pointer
  • @param[in] config: CAN config
  • @param[in] baudrate: CAN baud rate
  • @return 0: no error, 1: Initialize error
void CAN_InitHardwr(void)
{
 CAN_Config canConfig = {0};
 CAN_BaudrateConfig canBandrateConfig = {0};
 
 GPIO_SetFunc(CAN1_TX, GPIO_FUNC_1);//设置CAN1引脚复用功能
 GPIO_SetFunc(CAN1_RX, GPIO_FUNC_1);
 GPIO_SetDir(CAN1_STB, GPIO_OUTPUT);//设置CAN1收发器控制为IO控制
 CAN1_TRASCVER_NML;//使能CAN收发器
 
 /*
 设置波特率为500K,采样点为81.25%.
 tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
 BandRate  = (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1)))
 SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
 在已经知道波特率与采样点的情况下,经过计算后:tSeg1 = 13,tSeg2 = 3.
  */
 canBandrateConfig.S_PRESC  = 5;//分频后时钟为8M.
 canBandrateConfig.S_SEG_1  = 11;
 canBandrateConfig.S_SEG_2  = 2;
 canBandrateConfig.S_SJW  = 2;//满足S_SJW <= tSeg2即可.
 
 /* 
 16个过滤器中,可随意选择使用哪个,并制定其过滤模式,制定其过滤ID的类型.
 如果一个过滤器只需要接收一个ID,直接可将其设置CODE模式,然后根据ID类型设置过滤类型.
 如果一个过滤器需要接收多个ID,将其设置为MASK模式,并根据这几个ID的实际类型设置过滤ID类型,如果既有STD又有EXT,则应选择FILTER_IDE_STD_EXT_BOTH.
 
 此处加宏是为了更清楚的说明各种设置是否有效,在实际应用中,可将各种组合放在一起使用.
  */
 #if (RECV_FRM_KIND_SEL == ONLY_RECV_STD_FRM)
 CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD帧
 CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID2);//使用CODE模式只接收STD帧
 #endif
 #if (RECV_FRM_KIND_SEL == ONLY_RECV_EXT_FRM)
 CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID11);//使用CODE模式只接收EXT帧
 CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID12);//使用CODE模式只接收EXT帧
 #endif
 #if (RECV_FRM_KIND_SEL == RECV_STD_EXT_BOTH_FRM)
 CAN_SetFilterParam( 0, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID1 & CAN1_RECV_DATA_ID11));//使用MASK模式接收两种帧
 CAN_SetFilterParam( 1, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID2 & CAN1_RECV_DATA_ID12));//使用MASK模式接收两种帧
 #endif
 
 canConfig.interruptEnable = TRUE;//使能中断
 canConfig.TSSS = TRUE;//使用次发送缓冲区发送
 canConfig.canMode = CAN_MODE_NORMAL;
 canConfig.autoReset = TRUE;//CAN BUSOFF后,自动恢复
 canConfig.filterList = g_canFilterTab;//赋值过滤器设置list
 
 CAN_SetEventCallBack(CAN1, CAN1_IRQnCallBack);
 CAN_Initialize(CAN1, &canConfig, &canBandrateConfig);
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 滤波器
    +关注

    关注

    158

    文章

    7332

    浏览量

    174793
  • AMBA
    +关注

    关注

    0

    文章

    67

    浏览量

    14812
  • CAN收发器
    +关注

    关注

    2

    文章

    149

    浏览量

    25332
  • 串口中断
    +关注

    关注

    0

    文章

    63

    浏览量

    13614
  • MCU控制器
    +关注

    关注

    0

    文章

    27

    浏览量

    6820
收藏 人收藏

    评论

    相关推荐

    stm32 can 中断

    FIFO0接收数据信息存入消息结构体 if ((RxMessage.IDE == CAN_ID_STD)) //如果消息标识符的类型为标准帧模式 {for(i=0;iRF0R|=
    发表于 11-01 15:11

    请问CAN接收中断DSP底层会怎么样?

    请教:正常流程:CAN设置中断接收方式,通过CAN调试助手,发送一帧数据,产生一个CAN接收
    发表于 10-17 14:37

    基于STM32F103实现CAN数据收发的功能

    。基于rt-thread,已经有CAN的驱动框架,可以快速实现CAN数据的收发。这里基于STM32F103 实现CAN数据收发的
    发表于 08-19 07:20

    使用CAN1中断接收数据,无法接收到CAN数据是为什么?

    我是用CAN1中断进行接收信息,在ch32v30x_it.c添加了中断声明void CAN1_RX1_IRQHandler(void) _
    发表于 06-24 11:21

    实现功能安全性冗余CAN参考设计

    描述该参考设计展示了如何在物理层实施冗余(并行)CAN 以实现功能安全性。其中包括两个 SN65HVD257 CAN 收发器以及可确保两个收发器收到相同
    发表于 09-23 07:09

    何在外设设置CAN实例启用灵活数据速率复选框?

    我一直在使用S32SDK_S321XX_RTM_4.0.1 can_pal_s32k144示例。 在该示例CAN 0 实例已在外设设置
    发表于 03-21 08:00

    KW45板CAN收发器静默模式下未接收到CAN Rx中断是怎么回事?

    我目前正在使用 KW45 开发板。CAN收发芯片是NXP的TJA1057GT/3。我目前正在静默模式下测试 Can Rx,我将 gpio 引脚设置为连接到
    发表于 04-14 07:49

    CAN通信波特率设置

    CAN通信波特率设置 LM3S2000、LM3S5000、LM3S8000系列CPU内部有1~3路CAN控制器,通过对CAN位定时寄存器CANBIT及
    发表于 04-06 18:00 24次下载

    STM32F429 基于HAL库的双路CAN中断收发实例

    进不去第二路CAN 中断 找到的各种方法都试了 没效果/** \addtogroup can_group can通讯模块 *//*@{*/CA
    发表于 12-04 15:36 33次下载
    STM32F429 基于HAL库的双路<b class='flag-5'>CAN</b><b class='flag-5'>中断</b>收发实例

    STM32CubeMX生成CAN相关程序一(发送中断与接收中断

    目录一、CubeMX配置1、时钟设置2、CAN1设置1)引脚修改2)中断使能3)波特率计算3、SYS设置
    发表于 12-04 18:21 23次下载
    STM32CubeMX生成<b class='flag-5'>CAN</b>相关程序一(发送<b class='flag-5'>中断</b>与接收<b class='flag-5'>中断</b>)

    STM32的CAN收发数据死在硬件错误中断

    STM32的CAN收发数据死在硬件错误中断使用uCosIII的消息队列,当CAN接收到数据,使用消息队列给
    发表于 12-09 09:36 22次下载
    STM32的<b class='flag-5'>CAN</b>收发<b class='flag-5'>数据</b>死在硬件错误<b class='flag-5'>中断</b>

    基于RA6M4开发板的CAN通信功能

    添加完成后,单击CAN模块。再点击Properties打开配置界面,设置name,选择通道、ID模式,设置CAN中断回调函数名称。
    发表于 10-18 12:50 718次阅读

    APM32F103RCT6_CAN_CAN无法进入中断

    APM32F103RCT6_CAN_CAN无法进入中断
    发表于 11-09 21:03 4次下载
    APM32F103RCT6_<b class='flag-5'>CAN_CAN</b>无法进入<b class='flag-5'>中断</b>

    CAN总线学习笔记|CAN盒测试STM32的CAN中断接收

    CAN基础知识介绍文中介绍了CAN协议相关的基础知识,以及STM32F4芯片的CAN控制器相关知识,下面将通过实例,利用STM32CubeMX图形化配置工具,并配合CAN盒,来实现
    的头像 发表于 01-16 17:17 4104次阅读