stm32 HAL库分析之CAN

阻塞发送

 HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)                       565 {                                                                                                   566   uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;                                                567   uint32_t tickstart = 0U;                                                                          568                                                                                                     569   /* Check the parameters */                                                                        570   assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));                                                   571   assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));                                                      572   assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));                                                      573                                                                                                     574   if(((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) || \                                                                                                                           575      ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) || \                                      576      ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2))                                          577   {                                                                                                 578     /* Process locked */                                                                            579     __HAL_LOCK(hcan);                                                                               580                                                                                                     581     /* Change CAN state */                                                                          582     switch(hcan->State)                                                                             583     {                                                                                               584       case(HAL_CAN_STATE_BUSY_RX0):                                                                 585           hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;                                                  586           break;                                                                                    587       case(HAL_CAN_STATE_BUSY_RX1):                                                                 588           hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;                                                  589           break;                                                                                    590       case(HAL_CAN_STATE_BUSY_RX0_RX1):                                                             591           hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;                                              592           break;                                                                                    593       default: /* HAL_CAN_STATE_READY */                                                            594           hcan->State = HAL_CAN_STATE_BUSY_TX;                                                      595           break;                                                                                    596     }                                                                                               597                                                                                                     598     /* Select one empty transmit mailbox */                                                         599     if ((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)                                         600     {                                                                                               601       transmitmailbox = CAN_TXMAILBOX_0;                                                            602     }                                                                                               603     else if ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)                                    604     {                                                                                               605       transmitmailbox = CAN_TXMAILBOX_1;                                                            606     }                                                                                               607     else                                                                                            608     {                                                                                               609       transmitmailbox = CAN_TXMAILBOX_2;                                                            610     }                                                                                               611  612     /* Set up the Id */                                                                             613     hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;                               614     if (hcan->pTxMsg->IDE == CAN_ID_STD)                                                            615     {                                                                                               616       assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));                                                                                                                                   617       hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21U) | \          618                                                   hcan->pTxMsg->RTR);                               619     }                                                                                               620     else                                                                                            621     {                                                                                               622       assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));                                              623       hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3U) | \           624                                                   hcan->pTxMsg->IDE | \                             625                                                   hcan->pTxMsg->RTR);                               626     }                                                                                               627                                                                                                     628     /* Set up the DLC */                                                                            629     hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;                                                       630     hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0U;                      631     hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;                          632                                                                                                     633     /* Set up the data field */                                                                     634     hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3U] << 24U) | 635                                              ((uint32_t)hcan->pTxMsg->Data[2U] << 16U) |            636                                              ((uint32_t)hcan->pTxMsg->Data[1U] << 8U) |             637                                              ((uint32_t)hcan->pTxMsg->Data[0U]));                   638     hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7U] << 24U) | 639                                              ((uint32_t)hcan->pTxMsg->Data[6U] << 16U) |            640                                              ((uint32_t)hcan->pTxMsg->Data[5U] << 8U) |             641                                              ((uint32_t)hcan->pTxMsg->Data[4U]));                   642     /* Request transmission */                                                                      643     hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;                               644                                                                                                     645     /* Get tick */                                                                                  646     tickstart = HAL_GetTick();                                                                      647                                                                                                     648     /* Check End of transmission flag */                                                            649     while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))                                      650     {                                                                                               651       /* Check for the Timeout */                                                                   652       if(Timeout != HAL_MAX_DELAY)                                                                  653       {                                                                                             654        if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))655        {                                                                                            656          hcan->State = HAL_CAN_STATE_TIMEOUT;                                                       657                                                                                                     658          __HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox);                                          659                                                                                                     660          /* Process unlocked */                                                                     661          __HAL_UNLOCK(hcan);                                                                        662          return HAL_TIMEOUT;                                                                        663         }                                                                                           664       }                                                                                             665     }                                                                                               666                                                                                                     667     /* Change CAN state */                                                                          668     switch(hcan->State)                                                                             669     {                                                                                               670       case(HAL_CAN_STATE_BUSY_TX_RX0):                                                              671           hcan->State = HAL_CAN_STATE_BUSY_RX0;                                                     672           break;                                                                                    673       case(HAL_CAN_STATE_BUSY_TX_RX1):                                                              674           hcan->State = HAL_CAN_STATE_BUSY_RX1;                                                     675           break;                                                                                    676       case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):                                                          677           hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;                                                 678           break;                                                                                    679       default: /* HAL_CAN_STATE_BUSY_TX */                                                          680           hcan->State = HAL_CAN_STATE_READY;                                                        681           break;                                                                                    682     }                                                                                               683                                                                                                     684     /* Process unlocked */                                                                          685     __HAL_UNLOCK(hcan);                                                                             686                                                                                                     687     /* Return function status */                                                                    688     return HAL_OK;                                                                                                                                                                       689   }                                                                                                 690   else                                                                                              691   {                                                                                                 692     /* Change CAN state */                                                                          693     hcan->State = HAL_CAN_STATE_ERROR;                                                              694                                                                                                     695     /* Return function status */                                                                    696     return HAL_ERROR;                                                                               697   }                                                                                                 698 }                            

代码分析:
1. 检查参数,根据TSR发送状态寄存器,判断可用的发送邮箱的个数,如果有可用邮箱的话就继续往下走,没有的话就报错.
2. 由小往大选定一个可用的邮箱.
3. 对邮箱的TIR寄存,标识寄存器器进行配置,主要是ID和发送的帧的数据类型,数据帧还是遥控帧.

4. 将数据的长度放到长度控制和时间戳控制寄存器TDTR
5. 将8个字节的数据放到邮箱的数据寄存器,分别是TDLR,TDHR,每个寄存器各放4个字节的数据.
6. 将TIR寄存器的TXRQ置位,请求发送邮箱里面的数据.
7. 循环等待,CAN_TSR_RQCP(上一次发送成功置位),CAN_TSR_TXOK(邮箱请求完成置位),CAN_TSR_TME(邮箱为空置位)这3个寄存器是否被置位.并且判断整个发送过程中是否超时.
8. 根据状态返回值.

无阻塞发送

706 HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef* hcan)                                      707 {                                                                                                   708   uint32_t  transmitmailbox = CAN_TXSTATUS_NOMAILBOX;                                               709                                                                                                     710   /* Check the parameters */                                                                        711   assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));                                                   712   assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));                                                      713   assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));                                                      714                                                                                                     715   if(((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) || \                                                                                                                           716      ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) || \                                      717      ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2))                                          718   {                                                                                                 719     /* Process Locked */                                                                            720     __HAL_LOCK(hcan);                                                                               721                                                                                                     722     /* Select one empty transmit mailbox */                                                         723     if((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)                                          724     {                                                                                               725       transmitmailbox = CAN_TXMAILBOX_0;                                                            726     }                                                                                               727     else if((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)                                     728     {                                                                                               729       transmitmailbox = CAN_TXMAILBOX_1;                                                            730     }                                                                                               731     else                                                                                            732     {                                                                                               733       transmitmailbox = CAN_TXMAILBOX_2;                                                            734     }                                                                                               735                                                                                                     736     /* Set up the Id */                                                                             737     hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;                               738     if(hcan->pTxMsg->IDE == CAN_ID_STD)                                                             739     {                                                                                               740       assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));                                              741       hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21U) | \          742                                                 hcan->pTxMsg->RTR);                                 743     }                                                                                               744     else                                                                                            745     {                                                                                               746       assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));                                              747       hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3U) | \           748                                                 hcan->pTxMsg->IDE | \                               749                                                 hcan->pTxMsg->RTR);                                 750     }                                                                                               751752     /* Set up the DLC */                                                                            753     hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;                                                       754     hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0U;                      755     hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;                          756                                                                                                     757     /* Set up the data field */                                                                                                                                                          758     hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3U] << 24U) | 759                                            ((uint32_t)hcan->pTxMsg->Data[2U] << 16U) |              760                                            ((uint32_t)hcan->pTxMsg->Data[1U] << 8U) |               761                                            ((uint32_t)hcan->pTxMsg->Data[0U]));                     762     hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7U] << 24U) | 763                                            ((uint32_t)hcan->pTxMsg->Data[6U] << 16U) |              764                                            ((uint32_t)hcan->pTxMsg->Data[5U] << 8U) |               765                                            ((uint32_t)hcan->pTxMsg->Data[4U]));                     766                                                                                                     767     /* Change CAN state */                                                                          768     switch(hcan->State)                                                                             769     {                                                                                               770       case(HAL_CAN_STATE_BUSY_RX0):                                                                 771           hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;                                                  772           break;                                                                                    773       case(HAL_CAN_STATE_BUSY_RX1):                                                                 774           hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;                                                  775           break;                                                                                    776       case(HAL_CAN_STATE_BUSY_RX0_RX1):                                                             777           hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;                                              778           break;                                                                                    779       default: /* HAL_CAN_STATE_READY */                                                            780           hcan->State = HAL_CAN_STATE_BUSY_TX;                                                      781           break;                                                                                    782     }                                                                                               783                                                                                                     784     /* Set CAN error code to none */                                                                785     hcan->ErrorCode = HAL_CAN_ERROR_NONE;                                                           786                                                                                                     787     /* Process Unlocked */                                                                          788     __HAL_UNLOCK(hcan);                                                                             789                                                                                                     790     /* Request transmission */                                                                      791     hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;                               792793     /* Enable Error warning, Error passive, Bus-off,                                                794        Last error and Error Interrupts */                                                           795     __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |                                                          796                               CAN_IT_EPV |                                                          797                               CAN_IT_BOF |                                                          798                               CAN_IT_LEC |                                                          799                               CAN_IT_ERR |                                                          800                               CAN_IT_TME);                                                          801   }                                                                                                 802   else                                                                                              803   {                                                                                                 804     /* Change CAN state */                                                                          805     hcan->State = HAL_CAN_STATE_ERROR;                                                              806                                                                                                     807     /* Return function status */                                                                    808     return HAL_ERROR;                                                                               809   }                                                                                                 810                                                                                                     811   return HAL_OK;                                                                                                                                                                         812 }                                                                                       

代码分析:
前面1-6的步骤和阻塞是发送都是一样的.
7. 开启中断
一帧数据发送完成之后,进入can的中断.
注意开启的中断:

449 #define CAN_IT_TME                  ((uint32_t)CAN_IER_TMEIE)   /*!< Transmit mailbox empty interrupt */463 /* Error Interrupts */
464 #define CAN_IT_EWG                  ((uint32_t)CAN_IER_EWGIE) /*!< Error warning interrupt   */
465 #define CAN_IT_EPV                  ((uint32_t)CAN_IER_EPVIE) /*!< Error passive interrupt   */
466 #define CAN_IT_BOF                  ((uint32_t)CAN_IER_BOFIE) /*!< Bus-off interrupt         */
467 #define CAN_IT_LEC                  ((uint32_t)CAN_IER_LECIE) /*!< Last error code interrupt */
468 #define CAN_IT_ERR                  ((uint32_t)CAN_IER_ERRIE) /*!< Error Interrupt           */ 

一个发送邮箱空中断,还有5种错误情况引起的中断

1251   if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
1252   {
1253     tmp1 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0);
1254     tmp2 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1);
1255     tmp3 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2);
1256     if(tmp1 || tmp2 || tmp3)
1257     {
1258       tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK0);
1259       tmp2 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK1);
1260       tmp3 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK2);
1261       /* Check Transmit success */
1262       if(tmp1 || tmp2 || tmp3)
1263       {
1264         /* Call transmit function */
1265         CAN_Transmit_IT(hcan);
1266       }
1267       else /* Transmit failure */
1268       {
1269         /* Set CAN error code to TXFAIL error */
1270         errorcode |= HAL_CAN_ERROR_TXFAIL;
1271       }
1272
1273       /* Clear transmission status flags (RQCPx and TXOKx) */
1274       SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP0  | CAN_TSR_RQCP1  | CAN_TSR_RQCP2 | \
1275                                    CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);
1276     }
1277   }  

其中判断,发送是否完成的代码.
1. 第一句话还是和之前的一样,读取到三个邮箱的状态,也就是RQCP, TXOK,TME,三个寄存器的状态.
2. 第二句话就是进一步去判断,TXOK寄存器,检查三个寄存器中是否有发送完成的邮箱.


具体的判断逻辑如上所示,也就是去检查TSR这个寄存器的第1,9,11位来判断是否发送完成.如果发送完成就可去调用CAN_Transmit_IT,在这个里面主要是关中断,再调用用户的回调函数.
3. 清掉RQCP, TXOK寄存器的标志位

题外话:
公司的代码,移植的是can的驱动代码,里面有一句话让我觉得很奇怪:

    if(HAL_CAN_Transmit(&g_sCAN_Handler[dwDevice], 10) != HAL_OK){//注:如果发送中断使能,因在发送中断里会清相关标志,这样会导致此函数会超时,而发送实际是成功的return FALSE; }

为什么会有这样一句奇怪的注释,这里使用的阻塞的方式发送数据,那么计算超时的时候就会检查RQCP, TXOK,这两个位用来判断是否发送完成。但是在hal库里面没有发送时中断是关掉了,根本就不会在中断里面清掉标志位,根本就不存在这个问题。当我们使用中断的方式发送时, 又不会进行超时判断。因此只有在使用不规范的时候才会出现这个问题,因此这句注释就是无稽之谈。

stm32 HAL库分析之CAN相关推荐

  1. stm32 hal库分析之uart

    hal库 uart 基本概念: 同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式. 异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式. 同步是阻塞 ...

  2. STM32的HAL库分析及使用

    STM32的三种开发方式 通常新手在入门STM32的时候,首先都要先选择一种要用的开发方式,不同的开发方式会导致你编程的架构是完全不一样的.一般大多数都会选用标准库和HAL库,而极少部分人会通过直接配 ...

  3. STM32 HAL库 串口DMA(收发)和STM32串口中断接收(接收时间管理机制)+ESP8266 wifi模组通信问题

    一.HAL库 串口 DMA+ESP8266模组通信问题 用STM32 HAL库串口的DMA发送和空闲中断接收处理数据,单片机发送AT指令给ESP8266 wifi模组问题:单片机连续几次给wifi模组 ...

  4. STM32 HAL库学习笔记4-SPI

    STM32 HAL库学习笔记4-SPI 前言 一.SPI协议简介 SPI物理层 SPI协议层 1.基本通讯过程 2. 通讯的起始和停止信号 3. 数据有效性 4. CPOL/CPHA 及通讯模式 二. ...

  5. stm32+HAL库制作转速仪

    stm32+HAL库制作转速仪 前言 电机在运行过程中,需要实时检测其转速的稳定性,有效反映电机的运行情况. 本文介绍了基于stm32的转速仪的设计,可以用光电门传感器和红外对管传感器测量,可以设置选 ...

  6. STM32 HAL库 CubeMX教程(五)串口通信基础

    STM32 HAL库 CubeMX教程(五)串口通信基础 串口通信简介 CubeMX配置 初始化程序分析 程序编写 参考文献 STM32 HAL库 CubeMX系列教程 目录 串口通信简介 UART: ...

  7. STM32 HAL库详解 及 手动移植

    源: STM32 HAL库详解 及 手动移植

  8. STM32 HAL库、标准外设库、LL库(STM32 Embedded Software)

    STM32 Embedded Software 工作以来一直使用ST的STM32系列芯片,ST为开发者提供了非常方便的开发库.到目前为止,有标准外设库(STD库).HAL库.LL库 三种.前两者都是常 ...

  9. STM32 HAL库PID控制电机 第二章 TB6612FNG芯片驱动GB37-520电机

    STM32 HAL库PID控制电机 第二章 TB6612FNG芯片驱动GB37-520电机(HAL库) 1 电路图 2 TB6612简介 TB6612是双驱动,可同时驱动两个电机 STBY:接单片机的 ...

最新文章

  1. requireJS 从概念到实战
  2. 金融贷款逾期的模型构建7——模型融合
  3. Ubuntu-C++环境设置
  4. BZOJ 3884 上帝与集合的正确用法
  5. Scala-列表操作
  6. 字符串类习题、面试题详解(第二篇)
  7. Oracle 11g xe版本---总结1
  8. 表格序号_让Excel表格中的序号自动更新,再也不怕删除、插入行了
  9. [NLP]OpenNLP Maven工程的依赖
  10. 禁止绿盟扫描oracle,Oracle Enterprise Manager Grid Control JSP代码执行漏洞(CVE-2010-3600)
  11. 联想笔记本电源管理-设置充电上下限
  12. 百度UEditor编辑器压缩(缩放)图片只压缩jpg格式的解决方法
  13. 短视频直播美颜sdk可以接入其它视频社交平台吗?
  14. NFT 生成物及素材展示(小熊、性别形象、道具)
  15. java下载m3u8转ts合成mp4
  16. css所有属性大合集,包含中文标题
  17. 智能电网与配网自动化工程建设
  18. Spark删除redis千万级别set集合数据
  19. 电脑pc页面在手机缩放显示
  20. 数据库系统概论(第五版)王珊 自用复习笔记

热门文章

  1. 四、NPP/VIIRS夜间灯光数据校正之连续性校正
  2. 从寻找美食到美食家,源于一份分享
  3. Android小游戏开发:简单的合金弹头游戏(一)游戏框架
  4. get和post的差别
  5. 计算机怎么删除证书,win7电脑如何删除过期IE证书
  6. 离散实验偏序关系满足实验报告C语言,离散数学实验三
  7. ASP木马提升权限的N种方法
  8. 利用canconvert合并两个dbc,FileNotFoundError解决!!!
  9. 小程序中是否存在跨域限制
  10. java电商和企业项目_java电商和企业项目