首页 > 其他分享 >2023暑假电控组培训第四讲——CAN

2023暑假电控组培训第四讲——CAN

时间:2023-07-01 15:57:15浏览次数:45  
标签:HAL 总线 FilterType 发送 暑假 2023 电控 接收 ID

  • 前言
    在RoboMaster比赛中,无论是电机驱动还是板间通信,CAN通信都发挥了极其重要的作用,但是相比于其它基本知识,CAN是一个相对而言比较复杂的通讯协议,有着更多的特性需要去记忆,也因此成为了很多RMer电控入门阶段的美好回忆,本篇文章将从理论出发,结合实践,讲解如何使用CAN通信。
  • 什么是CAN通信?
    CAN 是控制器域网 (Controller Area Network, CAN) 的简称,是由研发和生产汽车电子产 品著称的德国 BOACH 公司开发,并最终成为国际标准(ISO11898),CAN 是国际上应用 最广泛的现场总线之一。 在北美和西欧,CAN 总线协议已经成为汽车计算机控制系统和嵌 入式工业控制局域网的标准总线,并且拥有以 CAN 为底层协议专为大型货车和重工机械车 辆设计的 J1939 协议。近年来,它具有的高可靠性和良好的错误检测能力受到重视,被广泛应用于汽车计算机控制系统和环境温度恶劣、电磁辐射强及振动大的工业环境。
  • 理论部分
    • 硬件层面
      • 信息传递方式——差分信号​​

        CAN控制器通过组成总线的2根线(CAN-H和CAN-L)的电位差来确定总线的电平,信号是以两线之间的“差分”电压形式出现,总线电平分为显性电平和隐性电平。

        这样,通过采用两种互补的逻辑数值"显性"和"隐性"的方法,用"显性"数值表示逻辑"0",而"隐性"表示逻辑"1"。从而,CAN总线仅通过CAN_H与CAN_L两条线即可实现信息的传递。
        这时我们可以联想到之前学过的另一种通信方式UART

        CAN UART
        比赛中应用 板间通信,大多数电机驱动 与操作手通信
        总线结构 多主机、多从机的总线结构,其中多个节点可以同时发送和接收消息 点对点连接,只有一个发送器和一个接收器
        通信速率 支持高速传输,可以实现较高的数据速率,1 Mbps或更高 低速通信,通常在几十 kbps 到几 Mbps 的范围内
        数据帧格式 使用帧格式来发送和接收数据,其中包括标识符、数据和检验位 异步通信,使用起始位、数据位、校验位和停止位来传输数据
        可靠性和冲突处理 具有较高的可靠性和抗干扰能力,可以检测和处理冲突,确保数据的完整性和正确性 较为简单,没有内置的错误检测和冲突处理机制

        部分内容将会在下面详细讲解

      • 帧仲裁
        在编写控制程序时,我们往往需要处理来自多个传感器或上位机的数据,那么当我们用CAN传递信息时,如果多个模块同时向我们反馈信息,如果不对顺序进行安排,数据将会混在一起无法解算。这种情况下就需要进行仲裁,判断哪个设备可以占用总线,而其他设备要转变为接收或者等待

        CAN的仲裁机制巧妙地利用了差分信号的特性,即显性电平覆盖隐形电平的特性,如果出现多个设备同时发送的情况,则先输出隐形电平的设备会失去对总线的占有权。下图中D为显性电平,R为隐形电平,通过该图可以很容易地理解CAN的仲裁机制。

      • 波特率

        CAN有着很高的通讯速率,通过查阅手册可知,一般RM系列电调的通讯速率为1Mbps,只有波特率一致的情况下,主控才能成功与电调进行通讯,CAN的通讯速率的决定因素包括以下四点:

        • 同步段 (SYNC_SEG) :位变化应该在此时间段内发生。只有一个时间片的固定长度 (1 x tq )

        • 位段 1(BS1) :定义采样点的位置。其持续长度可以在 1 到 16 个时间片之间调整

        • 位段 2(BS2) :定义发送点的位置。其持续长度可以在 1 到 8 个时间片之间调整

        • 同步跳转宽度( SJW ):定义位段加长或缩短的上限。它可以在 1 到 4 个时间片之间调整

        CAN 总线波特率和 tq (Time Quantum),tBS1 (Time Quanta in Bit Segment 1)和 tBS2 (Time Quanta in Bit Segment 1) 的值直接相关,tq 通过总线分频后直接得到,tBS1和 tBS2 则通过 TS1 和 TS2 放大为 tq 的若干倍,需要注意的是下图中 tBS1 和 tBS2 的计 算是通过 tq(TS1+1)和 tq(TS2+1)得到的,而在 CubeMX 中,我们配置的 Time Quanta in Bit Segment 的值对应的就是 (TS1+1)和(TS2+1)。至于CAN究竟挂在哪个总线上就需要查阅数据手册了

    • 软件层面
      • 过滤器
        把CAN总线看作是一个兵种组,每天会为组员安排不同任务,但是队员们并不是每个人都要做全部工作的,不加区分地把数据传给每一个人只会导致工作的混乱。因此我们可以在任务前面加上标识,如电控任务,机械任务,电路任务,视觉任务让每个人只接收自己技术组的任务,而直接过滤掉与自己无关的工作

        事实上,bxCAN的过滤器就是采用上述方法,你只需要设置好你感兴趣的那些CAN报文ID,那么MCU就只能收到这些CAN报文,是从硬件上过滤掉,完全不需要软件参与进来,从而节省了大大节省了MCU的时间,可以更加专注于其他事务,这个就是bxCAN过滤器的意义所在。

        CAN的过滤器模式分为掩码模式列表模式

        • 列表模式

          简单来说就是制作一张ID表,如果来的数据的ID在这张表中则接收,否则不收。

        • 掩码模式

          假设某学校的学工号是 入学年份+学生序号,那么,我想要确定学生的年级的话只需要看学工号就可以了,但是为了省事,其实我们完全可以把学工号后面的序号忽略,只看前面的入学年份部分。这就是掩码模式。

      • 标准数据帧

        CAN的一个标准数据帧包括以下几个部分

        • 仲裁场

          仲裁场包括12位标识符,作用在前面帧仲裁处已进行讲解
        • 控制场

          仲裁场后跟随的是控制场,存放数据长度DLC,数据场中要填写CAN发送的数据
  • 实践部分
    • CUBE配置

      1.选择外部高速晶振

      2.Debug选Serial Wire

      3.配置时钟树

      接下来结合时钟树讲解一下波特率的计算配置

      经查阅,我们知道STM32F407IGHX的CAN挂在APB1总线上,因此我们在时钟树上找到APB1,外设频率为42MHz

      打开CAN

      此时我们设的预分频(Prescaler)为3,所以$$t_q=\frac{1}{f}=\frac{1}{\frac{42MHz}{3}}=\frac{1}{14}ns$$

      因而,由理论部分的公式求得:波特率(Baud Rate)Rb=1000000bit/s.

      选取工作模式为 Normal

      关于各种工作模式,介绍如下:

      工作模式 模式说明 详细说明
      Normal 正常模式 可发可收
      Loopback 回环模式 自发自收
      Silent 静默模式 只收不发
      Loopback combine with Silent 回环静默模式
      记得打开中断以接收。
    • 代码部分

      • 发送初始化

        • 变量含义

          StdId:CAN总线消息的标准ID

          IDE:指定CAN总线消息的标识符扩展位

          RTR:指定CAN总线消息的远程传输请求位

          DLC:指定CAN总线消息的数据长度码

            chassis_tx_message.StdId = 0x222; //标准ID
            chassis_tx_message.StdId = 0x222; //标准ID
            chassis_tx_message.RTR = CAN_RTR_DATA;//设置了远程传输请求位
            chassis_tx_message.IDE = CAN_ID_STD;//使用了标准的11位标识符
            chassis_tx_message.DLC = 0x08;    //8字节长
          
      • 接收初始化

            CAN_FilterTypeDef CAN_FilterType;
            CAN_FilterType.FilterBank=0;                        //使用0号过滤器                   
            CAN_FilterType.FilterIdHigh=0x0000;                 //设置验证码高低各4字节
            CAN_FilterType.FilterIdLow=0x0000;
            CAN_FilterType.FilterMaskIdHigh=0x0000;             //设置屏蔽码高低各4字节
            CAN_FilterType.FilterMaskIdLow=0x0000;
            CAN_FilterType.FilterFIFOAssignment=CAN_RX_FIFO0;   //通过CAN的信息放入0号FIFO
            CAN_FilterType.FilterMode=CAN_FILTERMODE_IDMASK;    //采用掩码模式
            CAN_FilterType.FilterScale=CAN_FILTERSCALE_32BIT;   //设置32位宽
            CAN_FilterType.FilterActivation=ENABLE;             //激活滤波器
            CAN_FilterType.SlaveStartFilterBank=14;
            HAL_CAN_ConfigFilter(hcan, &CAN_FilterType);        //配置过滤器
            HAL_CAN_Start(hcan);                                //开启CAN总线
            HAL_CAN_ActivateNotification(hcan,CAN_IT_RX_FIFO0_MSG_PENDING);//激活CAN接收
        
      • 发送函数

        HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox)
        
        函数名 HAL_CAN_AddTXMessage
        函数功能 将一段数据通过 CAN 总线发送
        返回值 HAL_StatusTypeDef,HAL 库定义的几种状态,如果本次 CAN 发送成功, 则返回 HAL_OK
        参数1 CAN_HandleTypeDef *hcan,即 can 的句柄指针,如果是 can1 就输入&hcan1,can2 就输入&hcan2
        参数2 CAN_TxHeaderTypeDef *pHeader,待发送的 CAN 数据帧信息的结构体指 针,包含了 CAN 的 ID,格式等重要信息
        参数3 uint8_t aData[],装载了待发送的数据的数组名称
        参数4 uint32_t *pTxMailbox,用于存储 CAN 发送所使用的邮箱号

        实例:队内CAN发送函数

        /**
            * @brief      向CAN总线发送信息
            * @param      phcan: 指向CAN句柄的指针
            * @param      txdata: 要发送的信息
            * @retval     无
            */
            void Can_SendMessage(CAN_HandleTypeDef* phcan, CAN_TxHeaderTypeDef* pheader, uint8_t txdata[])
            {
                uint32_t mailbox;
                /* Start the Transmission process */
                uint32_t ret = HAL_CAN_AddTxMessage(phcan, pheader, txdata, &mailbox);
                if (ret != HAL_OK) {
                    /* Transmission request Error */
                
                        Can_Error_Source = 5;
                        Can_Error_Message_Header = *pheader;
                        Can_ErrorHandler(ret);
                }
            }
        
      • 接收函数

        HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]) 
        
        函数名 HAL_CAN_GetRxMessage
        函数功能 接收 CAN 总线上发送来的数据
        返回值 HAL_StatusTypeDef,HAL 库定义的几种状态,如果本次 CAN 接收成功, 则返回 HAL_OK
        参数1 CAN_HandleTypeDef *hcan,即 can 的句柄指针,如果是 can1 就输入&hcan1,can2 就输入&hcan2
        参数2 uint32_t RxFifo,接收时使用的 CAN 接收 FIFO 号,一般为 CAN_RX_FIFO0
        参数3 CAN_RxHeaderTypeDef *pHeader,存储接收到的 CAN 数据帧信息的结构 体指针,包含了 CAN 的 ID,格式等重要信息
        参数4 uint8_t aData[],存储接收到的数据的数组名称

        实例:CAN接收电机反馈值

        void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) 
        {
            
        HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &chassis_rx_message, rxData);
        int i = (int)chassis_rx_message.StdId - 0x204 - 1;
        wheelrxdata.rxangle[i] = ((rxData[0]<<8) | rxData[1]);
            wheelrxdata.rxspeed[i] = ((rxData[2]<<8) | rxData[3]);
            wheelrxdata.rxI[i] = ((rxData[4]<<8) | rxData[5]);
            wheelrxdata.rxT[i] = rxData[6];
        return;
        }
        
      • 总结:

        使用CAN通信的基本思路:

        • 按需求初始化发送/接收(一般是两者兼有)
        • 开启发送函数
        • 书写中断回调函数
        • 得到数据,对数据进行处理以进行进一步操作

标签:HAL,总线,FilterType,发送,暑假,2023,电控,接收,ID
From: https://www.cnblogs.com/bit-dreamchaser/p/17519369.html

相关文章

  • 【题解】#68. 「NOIP2004」津津的储蓄计划 题解(2023-07-01更新)
    #68.「NOIP2004」津津的储蓄计划题解题目传送门欢迎大家指出错误并联系这个蒟蒻更新日志2023-02-0117:20文章完成2023-02-0316:09文章审核通过2023-02-0422:15修改了注释2023-05-2709:27修改了$\LaTeX$2023-07-0115:45修改了代码题目知识点模拟题目分析......
  • C/C++《数据结构课程设计》题目[2023-07-01]
    C/C++《数据结构课程设计》题目[2023-07-01]《数据结构课程设计》题目一、【大数四则运算】——线性表[习题描述]设计—个实现任意长的整数进行四则运算和幂次运算的演示程序。[基本要求]利用双向循环链表实现大数的存储,每个结点含一个整型变量。[实现提示]实现原理:任何一......
  • [OSPP开源之夏-2023] 结合NWR实现Flexible Raft
    FeatureName:ImplementingFlexibleRaftwithNWRAuthor:[email protected]:2023-06-28IssueLink:https://github.com/sofastack/sofa-jraft/issues/1003Summary我们希望在原始RAFT算法的基础上,让Leader选举和日志复制除了能需要获得多数派确认模型的支持之......
  • 参考资料------ 快速使用Python-Tkinter设计界面 方法与代码-20230701
    作者:干饭小熊猫链接:https://www.zhihu.com/question/68663671/answer/2519875621来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 1简介1.1Tkinter是什么?Tkinter是Python自带的GUI库,Python的IDEL就是Tkinter的应用实例。Tkinter可以看作是Tk......
  • 20230630巴蜀暑期集训测试
    T1BS5656最大值Max期望/实际:\(17/17\)考场没思路,打暴力。将每个数分开看,dp预处理出对于每个数,再某些位置被加最终值得概率。再次dp,合并每个数的信息。T2BS5657染色Paint期望/实际:\(0/0\)部分分没调完。答案有下界,分析可得答案必过一条中轴线,分别处理两个方向......
  • 20230701水题选做
    CF1676D题意给定一个无根树,点从\(1\)到\(n\)编号。你需要给每个点分配一个正整数权值\(w_i\)。定义一个节点为好节点,当且仅当其权值等于所有相邻节点的权值之和。请最大化好节点的个数,并且在好节点个数最大的前提下最小化所有节点的权值和。分析我们先考虑一种特殊情况,......
  • 提升网页阅读体验的三款优秀大纲插件(2023)
    阅读长篇文章或复杂网页时,清晰的大纲结构可以帮助我们更好地理解和组织信息。在这篇博客中,我将向大家推荐三款优秀的网页大纲插件,帮助您提升阅读效率和体验。FlashOutlineFlashSwitcher是一个专注于提高浏览器使用效率和体验的综合插件,其最新的智能大纲功能专门为提高网页阅读体......
  • 电池充放电测试仪行业市场调查及策略分析报告2023-2029
    2023-2029全球电池充放电测试仪行业调研及趋势分析报告2022年全球电池充放电测试仪市场规模约亿元,2018-2022年年复合增长率CAGR约为%,预计未来将持续保持平稳增长的态势,到2029年市场规模将接近亿元,未来六年CAGR为%。从核心市场看,中国电池充放电测试仪市场占据全球约%的市场份......
  • 光学玻璃球行业市场调查及策略分析报告2023-2029
    2023-2029全球光学玻璃球行业调研及趋势分析报告2022年全球光学玻璃球市场规模约亿元,2018-2022年年复合增长率CAGR约为%,预计未来将持续保持平稳增长的态势,到2029年市场规模将接近亿元,未来六年CAGR为%。从核心市场看,中国光学玻璃球市场占据全球约%的市场份额,为全球最主要的消......
  • 皮秒脉冲驱动器行业市场调查及策略分析报告2023-2029
    2023-2029全球皮秒脉冲驱动器行业调研及趋势分析报告2022年全球皮秒脉冲驱动器市场规模约亿元,2018-2022年年复合增长率CAGR约为%,预计未来将持续保持平稳增长的态势,到2029年市场规模将接近亿元,未来六年CAGR为%。从核心市场看,中国皮秒脉冲驱动器市场占据全球约%的市场份额,为全......