搜索
bottom↓
回复: 124

ST的HAL库千万不要用,效率低到惊人!

  [复制链接]

出0入10汤圆

发表于 2015-11-6 17:42:25 | 显示全部楼层 |阅读模式
本帖最后由 10xjzheng 于 2015-11-6 17:44 编辑

反正我还是多自己搞下寄存器吧,用到平常的功能还好,熟练了还比较容易实现,写完某些功能要优化发现不忍直视,用过的朋友就知道。
真心没有之前的标准库用得爽。
  1. /**
  2.   * @brief Initialize the UART mode according to the specified
  3.   *         parameters in the UART_InitTypeDef and initialize the associated handle.
  4.   * @param huart: UART handle.
  5.   * @retval HAL status
  6.   */
  7. HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
  8. {
  9.   /* Check the UART handle allocation */
  10.   if(huart == NULL)
  11.   {
  12.     return HAL_ERROR;
  13.   }

  14.   if(huart->Init.HwFlowCtl != UART_HWCONTROL_NONE)
  15.   {
  16.     /* Check the parameters */
  17.     assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance));
  18.   }
  19.   else
  20.   {
  21.     /* Check the parameters */
  22.     assert_param(IS_UART_INSTANCE(huart->Instance));
  23.   }

  24.   if(huart->State == HAL_UART_STATE_RESET)
  25.   {
  26.     /* Allocate lock resource and initialize it */
  27.     huart->Lock = HAL_UNLOCKED;

  28.     /* Init the low level hardware : GPIO, CLOCK */
  29.     HAL_UART_MspInit(huart);
  30.   }

  31.   huart->State = HAL_UART_STATE_BUSY;

  32.   /* Disable the Peripheral */
  33.   __HAL_UART_DISABLE(huart);

  34.   /* Set the UART Communication parameters */
  35.   if (UART_SetConfig(huart) == HAL_ERROR)
  36.   {
  37.     return HAL_ERROR;
  38.   }

  39.   if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
  40.   {
  41.     UART_AdvFeatureConfig(huart);
  42.   }

  43.   /* In asynchronous mode, the following bits must be kept cleared:
  44.   - LINEN and CLKEN bits in the USART_CR2 register,
  45.   - SCEN, HDSEL and IREN  bits in the USART_CR3 register.*/
  46.   huart->Instance->CR2 &= ~(USART_CR2_LINEN | USART_CR2_CLKEN);
  47.   huart->Instance->CR3 &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN);

  48.   /* Enable the Peripheral */
  49.   __HAL_UART_ENABLE(huart);

  50.   /* TEACK and/or REACK to check before moving huart->State to Ready */
  51.   return (UART_CheckIdleState(huart));
  52. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入10汤圆

 楼主| 发表于 2015-11-16 23:33:18 | 显示全部楼层
建议大家去看LL库,效率比较高!

出0入10汤圆

 楼主| 发表于 2015-11-6 17:47:57 | 显示全部楼层
很无奈的是,我用的STM32L4找不到标志库函数的例程,只有HAL库的。

出0入0汤圆

发表于 2015-11-6 17:55:45 | 显示全部楼层
10xjzheng 发表于 2015-11-6 17:47
很无奈的是,我用的STM32L4找不到标志库函数的例程,只有HAL库的。

楼主也在玩L4啊,有LL库,你看看

出0入0汤圆

发表于 2015-11-6 17:57:01 | 显示全部楼层
不敢苟同。我用F10x,今年的新产品已经迁移到HAL库,只有极少BUG需要规避。

出0入10汤圆

 楼主| 发表于 2015-11-6 18:01:10 | 显示全部楼层
styleno1 发表于 2015-11-6 17:57
不敢苟同。我用F10x,今年的新产品已经迁移到HAL库,只有极少BUG需要规避。

我在一个中断中开启串口接收中断,任何然后丢了几个数据,因为初始化过程很繁琐,本来置寄存器即可,现在还要设置很多标志位。
所以在这种情况下我觉得要帮他改进才行。

出0入10汤圆

 楼主| 发表于 2015-11-6 18:02:07 | 显示全部楼层
qq开始学单片机 发表于 2015-11-6 17:55
楼主也在玩L4啊,有LL库,你看看

你说的是HAL底层操作寄存器的那层还是有另外的?有链接看下吗?

出0入10汤圆

 楼主| 发表于 2015-11-6 18:07:56 | 显示全部楼层
大家再看看串口接收的处理函数!
  1. /**
  2.   * @brief Handle UART interrupt request.
  3.   * @param huart: UART handle.
  4.   * @retval None
  5.   */
  6. void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
  7. {
  8. //  /* UART parity error interrupt occurred -------------------------------------*/
  9. //  if((__HAL_UART_GET_IT(huart, UART_IT_PE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE) != RESET))
  10. //  {
  11. //    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_PEF);
  12. //
  13. //    huart->ErrorCode |= HAL_UART_ERROR_PE;
  14. //    /* Set the UART state ready to be able to start again the process */
  15. //    huart->State = HAL_UART_STATE_READY;
  16. //  }
  17. //
  18. //  /* UART frame error interrupt occurred --------------------------------------*/
  19. //  if((__HAL_UART_GET_IT(huart, UART_IT_FE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
  20. //  {
  21. //    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_FEF);
  22. //
  23. //    huart->ErrorCode |= HAL_UART_ERROR_FE;
  24. //    /* Set the UART state ready to be able to start again the process */
  25. //    huart->State = HAL_UART_STATE_READY;
  26. //  }
  27. //
  28. //  /* UART noise error interrupt occurred --------------------------------------*/
  29. //  if((__HAL_UART_GET_IT(huart, UART_IT_NE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
  30. //  {
  31. //    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_NEF);
  32. //
  33. //    huart->ErrorCode |= HAL_UART_ERROR_NE;
  34. //    /* Set the UART state ready to be able to start again the process */
  35. //    huart->State = HAL_UART_STATE_READY;
  36. //  }
  37. //
  38.   /* UART Over-Run interrupt occurred -----------------------------------------*/
  39.   if((__HAL_UART_GET_IT(huart, UART_IT_ORE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET))
  40.   {
  41.     __HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF);

  42. //    huart->ErrorCode |= HAL_UART_ERROR_ORE;
  43. //    /* Set the UART state ready to be able to start again the process */
  44. //    huart->State = HAL_UART_STATE_READY;
  45.   }
  46. //
  47. //   /* Call UART Error Call back function if need be --------------------------*/
  48. //  if(huart->ErrorCode != HAL_UART_ERROR_NONE)
  49. //  {
  50. //    HAL_UART_ErrorCallback(huart);
  51. //  }
  52. //
  53. //  /* UART wakeup from Stop mode interrupt occurred -------------------------------------*/
  54. //  if((__HAL_UART_GET_IT(huart, UART_IT_WUF) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_WUF) != RESET))
  55. //  {
  56. //    __HAL_UART_CLEAR_IT(huart, UART_CLEAR_WUF);
  57. //    /* Set the UART state ready to be able to start again the process */
  58. //    huart->State = HAL_UART_STATE_READY;
  59. //    HAL_UARTEx_WakeupCallback(huart);
  60. //  }

  61.   /* UART in mode Receiver ---------------------------------------------------*/
  62.   if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) != RESET))
  63.   {
  64. //    UART_Receive_IT(huart);
  65.     aRxBuffer[i] = huart->Instance->RDR;
  66.     i++;
  67. //    xTimerResetFromISR(USART1_RX_TimeOut_Tmr,0);
  68.     /* Clear RXNE interrupt flag */
  69.     __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
  70.   }


  71. //  /* UART in mode Transmitter ------------------------------------------------*/
  72. // if((__HAL_UART_GET_IT(huart, UART_IT_TXE) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE) != RESET))
  73. //  {
  74. //    UART_Transmit_IT(huart);
  75. //  }
  76. //
  77. //  /* UART in mode Transmitter (transmission end) -----------------------------*/
  78. // if((__HAL_UART_GET_IT(huart, UART_IT_TC) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC) != RESET))
  79. //  {
  80. //    UART_EndTransmit_IT(huart);
  81. //  }

  82. }
复制代码

出0入10汤圆

 楼主| 发表于 2015-11-6 18:10:38 | 显示全部楼层
本帖最后由 10xjzheng 于 2015-11-6 18:12 编辑

串口接收中断那里,所有的中断都检测一遍,虽然这个很有通用性,但是你只是想接收个串口数据而已啊,要不要这样子。还有,你因为屏蔽掉其他中断就没事啦?No,No。还有接收处理函数,还能不能好好玩耍?这段又是为了通用接收9位和8位数据.....如果这里加上一个宏来裁剪下通用性是不是会好点呢?谁都别跟我说复用性和效率的衡量问题,道理我都懂,可是....
  1. /**
  2.   * @brief Receive an amount of data in interrupt mode.
  3.   * @note   Function is called under interruption only, once
  4.   *         interruptions have been enabled by HAL_UART_Receive_IT()
  5.   * @param  huart: UART handle.
  6.   * @retval HAL status
  7.   */
  8. static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
  9. {
  10.   uint16_t* tmp;
  11.   uint16_t uhMask = huart->Mask;

  12.   if((huart->State == HAL_UART_STATE_BUSY_RX) || (huart->State == HAL_UART_STATE_BUSY_TX_RX))
  13.   {

  14.     if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
  15.     {
  16.       tmp = (uint16_t*) huart->pRxBuffPtr ;
  17.       *tmp = (uint16_t)(huart->Instance->RDR & uhMask);
  18.       huart->pRxBuffPtr +=2;
  19.     }
  20.     else
  21.     {
  22.       *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
  23.     }

  24.     if(--huart->RxXferCount == 0)
  25.     {
  26.       __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

  27.       /* Check if a transmit Process is ongoing or not */
  28.       if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
  29.       {
  30.         huart->State = HAL_UART_STATE_BUSY_TX;
  31.       }
  32.       else
  33.       {
  34.         /* Disable the UART Parity Error Interrupt */
  35.         __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

  36.         /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
  37.         __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

  38.         huart->State = HAL_UART_STATE_READY;
  39.       }

  40.       HAL_UART_RxCpltCallback(huart);

  41.       return HAL_OK;
  42.     }

  43.     return HAL_OK;
  44.   }
  45.   else
  46.   {
  47.     return HAL_BUSY;
  48.   }
  49. }
复制代码

出0入0汤圆

发表于 2015-11-6 18:29:44 | 显示全部楼层
同意,加1

出0入0汤圆

发表于 2015-11-6 18:34:18 | 显示全部楼层
我觉得还不错,目前卡在了SPI和DMA+中断看得实在是晕。

出0入4汤圆

发表于 2015-11-6 18:40:17 | 显示全部楼层
我调F7的时候看的头都大了,没法下手

出0入0汤圆

发表于 2015-11-6 18:42:12 | 显示全部楼层
F4 的 DMA代码很复杂的,生成的代码比较大。

出0入0汤圆

发表于 2015-11-6 19:01:07 | 显示全部楼层
hal+寄存器 双剑合璧,hal可以快速开发和移植 实时性要求高的自然要再跟进看寄存器做优化,关键代码保持高效率即可
举个栗子:开发完功能实现了,看中断不行太占cpu受不了,跟UART_Receive_IT函数 重写中断处理
另外 一般真不差那几个cpu周期,初始化不差,中断一般也不差,难道1s要进1000000次?那它本身就并不合理

出0入0汤圆

发表于 2015-11-6 19:34:49 | 显示全部楼层
标题党!

什么叫千万不能用?你用着不好,不代表别人用也不好,每个人的需求都不一样

出0入0汤圆

发表于 2015-11-6 20:45:17 | 显示全部楼层
HAL层已经让你不懂原理的设计程序了,更谈不上提高了基础知识了..........HAL在嵌入式系统使用才好,封装硬件驱动到应用之间.......

出0入10汤圆

 楼主| 发表于 2015-11-6 20:57:26 | 显示全部楼层
一天的蓝 发表于 2015-11-6 19:01
hal+寄存器 双剑合璧,hal可以快速开发和移植 实时性要求高的自然要再跟进看寄存器做优化,关键代码保持高 ...

这个说得比较好,目前也是这样子,工作量小。

出0入10汤圆

 楼主| 发表于 2015-11-6 21:02:54 | 显示全部楼层
activeleo 发表于 2015-11-6 20:45
HAL层已经让你不懂原理的设计程序了,更谈不上提高了基础知识了..........HAL在嵌入式系统使用才好,封装硬 ...

目的是好的,但是不懂原理的设计程序在我看来很难做好高效率驱动。
另外HAL跟嵌入式系统没有半毛钱关系,嵌入式系统只是帮你协调调度好,跟驱动那些没有直接关系。

出110入0汤圆

发表于 2015-11-7 00:02:11 | 显示全部楼层
HAL库还可以呀,配合cube挺好用,频繁中断的中断函数自己重建一下就好

出0入0汤圆

发表于 2015-11-7 01:59:40 | 显示全部楼层
效率其实低下, 用到的地方自己改写,

出0入0汤圆

发表于 2015-11-7 02:14:45 | 显示全部楼层
自己改下 最好

出0入0汤圆

发表于 2015-11-7 07:14:42 来自手机 | 显示全部楼层
最好跟着主流走 这样系统的bug有人帮你找

出0入0汤圆

发表于 2015-11-7 09:02:13 | 显示全部楼层
这就跟做事只看结果,而不看稳定性..........比如我们老板!

出0入0汤圆

发表于 2015-11-7 09:44:00 来自手机 | 显示全部楼层
尝试用mdk5的rte吧,不是必须要用st提供的框架的

出0入0汤圆

发表于 2015-11-7 09:57:16 | 显示全部楼层
感觉大势所趋 ,正在熟悉中 !

出100入101汤圆

发表于 2015-11-7 10:38:03 | 显示全部楼层
styleno1 发表于 2015-11-6 17:57
不敢苟同。我用F10x,今年的新产品已经迁移到HAL库,只有极少BUG需要规避。

能说下哪些bug需要规避么?

出10入0汤圆

发表于 2015-11-7 10:44:29 | 显示全部楼层
10xjzheng 发表于 2015-11-6 18:01
我在一个中断中开启串口接收中断,任何然后丢了几个数据,因为初始化过程很繁琐,本来置寄存器即可,现在 ...

开始学PC了,升级一下软件,让你用F4去。
不但空间多用了很多,效率就更不必多说了。
多了去的判断校验,效率肯定不好的。像我们开个10KHZ的中断,哪里受的了这样的速度。

出0入0汤圆

发表于 2015-11-7 10:44:43 | 显示全部楼层
库函数我见过avr32 studio的framework, 绝对大师级写的

出0入8汤圆

发表于 2015-11-7 10:46:18 | 显示全部楼层
10xjzheng 发表于 2015-11-6 20:57
这个说得比较好,目前也是这样子,工作量小。

@一天的蓝 说的是一种合理的工程实践模式

如今都会是所谓的trun key模式,而且会越来越流行
随着硬件复杂度和软件复杂度的上升,我们不可能回到原始的51之类、单片机模式
原始简单的操作寄存器,从0开始。。。

而这道理,我想你也懂
不过你起的这标题,属于标题党。

至于效率问题,如今的对于硬件主频而言,问题不是那么敏感
一个80M的主频,考虑理想模型,都是单周期指令,一条指令,只要12.5ns
多执行一些指令,消耗的时间也是可以接受的

如果真是敏感的话,那就特殊局部优化,绕过HAL。

出10入0汤圆

发表于 2015-11-7 10:49:07 | 显示全部楼层
myxiaonia 发表于 2015-11-7 09:44
尝试用mdk5的rte吧,不是必须要用st提供的框架的

相比还是ST对自己做的更全面一些。
RTE不是不好,而是统一了ARM核的驱动,ST这样的公司可不乐意啊

出0入0汤圆

发表于 2015-11-7 11:01:28 | 显示全部楼层
感觉HAL库是要做成中间层软件的样子,想法挺好,也是大势所趋。不过,目前还不怎么成熟的样子啊,效率先不说,感觉目前HAL库的易用性和可靠性还没发展到那种能让人直接忽略底层工作原理的程度,还是过过在看了。

出0入0汤圆

发表于 2015-11-7 11:22:25 | 显示全部楼层
正在用RTC  HAL 库,没法修改亚秒分辨率   一直默认为255   

出0入0汤圆

发表于 2015-11-7 11:34:42 | 显示全部楼层
我的批量化的产品都用HAL库,不解楼主

出0入0汤圆

发表于 2015-11-7 12:59:46 | 显示全部楼层
跟着走,哎……习惯3.5,现在搞出个CUBEMX,是比较麻烦
可能是先入为主了

出0入0汤圆

发表于 2015-11-8 10:05:51 来自手机 | 显示全部楼层
用HAL的USB搞双缓冲,Bug漫天飞,搞了一星期才成,吐了我满地血。 现在换USB lib,一看才发现HAL基本就是从lib抄过来的嘛,一样满地血

出0入0汤圆

发表于 2015-11-8 11:56:14 | 显示全部楼层
bart 发表于 2015-11-8 10:05
用HAL的USB搞双缓冲,Bug漫天飞,搞了一星期才成,吐了我满地血。 现在换USB lib,一看才发现HAL基本就是从 ...

可以尝试下用mdk的usb库,虽然没有源码,基本上都移植好了直接能用,自用感觉不错

出0入0汤圆

发表于 2015-11-8 11:58:50 | 显示全部楼层
huike 发表于 2015-11-7 10:49
相比还是ST对自己做的更全面一些。
RTE不是不好,而是统一了ARM核的驱动,ST这样的公司可不乐意啊 ...

不管st乐意不乐意,mdk就是有这样的雄心壮志。。。

mdk和st是相辅相成的,st要是怠慢下mdk,mdk给st穿小鞋不是分分钟的事情么

出0入0汤圆

发表于 2015-11-8 13:11:06 | 显示全部楼层
效率是有点低,但是开发简单点。另外你可以删除那些判断状态的程序,直接用

出0入0汤圆

发表于 2015-11-8 22:56:03 | 显示全部楼层
fangy 发表于 2015-11-7 11:22
正在用RTC  HAL 库,没法修改亚秒分辨率   一直默认为255

初始化的时候改异步和同步分频器的值然后在它那个结构体里面找寄存器定义,直接赋值。

出0入10汤圆

 楼主| 发表于 2015-11-10 10:11:58 | 显示全部楼层
liugang1986 发表于 2015-11-7 11:01
感觉HAL库是要做成中间层软件的样子,想法挺好,也是大势所趋。不过,目前还不怎么成熟的样子啊,效率先不 ...

就是!   

出0入0汤圆

发表于 2015-11-10 10:53:09 | 显示全部楼层
我最近做M0就莫名其妙遇到串口出现FE和ORE的标志,非得每次都判断一下,以前F10X的M3都没这情况。不过我没有用HAL库,用ST的底层LIB自己搞的。

出0入0汤圆

发表于 2015-11-10 13:44:50 | 显示全部楼层
现在没有标准库,只能有HAL库,st趋势已经改变不了了,hal库生成工程还是比较简单的。

出0入0汤圆

发表于 2015-11-17 08:50:01 | 显示全部楼层
LL库是什么来的?百度不到。HAL库让我看到了针对以前的库前所未有的考虑,冗余也好,麻烦也罢,反正就是各种判断,各种超时退出机制

出0入0汤圆

发表于 2015-11-17 08:56:19 | 显示全部楼层
非关键代码用ST库,关键代码自己扒寄存器吧

出0入0汤圆

发表于 2015-11-17 09:25:16 | 显示全部楼层
初始化用库,需要实时性的用寄存器

出0入0汤圆

发表于 2015-11-17 14:15:40 | 显示全部楼层
做产品,用库
搞学习,用寄存器

出0入0汤圆

发表于 2016-7-19 11:00:25 | 显示全部楼层
gamalot 发表于 2015-11-6 19:34
标题党!

什么叫千万不能用?你用着不好,不代表别人用也不好,每个人的需求都不一样

同意

出0入0汤圆

发表于 2016-7-20 00:47:18 | 显示全部楼层
目前都是用HAL库,基本都是CubeMx配置,只有在需要再快那么几us的地方才改成寄存器操作。。

出0入0汤圆

发表于 2016-7-20 01:00:58 | 显示全部楼层
不要说得这么严重,效率差不多。以前F4用STD库,F7用HAL库。现在全换HAL库,方便多了。

出0入8汤圆

发表于 2016-7-20 09:18:34 | 显示全部楼层
用过NXP,才知道,ST的寄存器分配有多烂

楼上说HAL库行的,应该没有做过:

1、BOOT+IAP ,对boot占用空间严格要求

2、没有各平台交叉移植,比如ST NXP FSL

3、SI 开发

出0入0汤圆

发表于 2016-7-20 09:48:06 | 显示全部楼层
刚开发完一个STM32L0系列基于HAL库的项目,感觉确实存在效率问题,解决方法就是自己改下代码,比如直接用操作寄存器的方式接收数据(STM32L0x3 ref manual里面最后就有相关代码),但是初始化之类的还是十分好用的。另外,上面有人说老是置位ORE中断,这个是HAL库默认打开的一个中断,可以在初始化的时候加入下面两行代码就行了。
  1. UartzHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT;
  2. UartzHandle.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
复制代码

出0入0汤圆

发表于 2016-9-18 19:36:41 | 显示全部楼层
在做crazyflie,用的就是HAL库

出0入0汤圆

发表于 2016-9-18 20:35:34 | 显示全部楼层
设计理念不一样。芯片厂商设计的库需要兼容性强,安全性高,客户上手简单快速。也是现在项目的潮流,不是每个人都需要去了解最底层的寄存器,也不是每个项目都有时间人员去重新开发驱动库。我也是很难接受这种写法,可是这是潮流,不赶上就落伍了,ATMEAL的很早就这么干的。

出0入0汤圆

发表于 2016-9-19 09:56:11 | 显示全部楼层
还没有用到,来学习一下

出0入42汤圆

发表于 2016-9-19 10:10:49 | 显示全部楼层
这是大趋势 类似楼主的还是小众市场  ST考虑到的是 上手快  片子易用性

出0入0汤圆

发表于 2016-9-21 18:47:55 | 显示全部楼层
库代码,效率是低一些。主要是方便

出0入0汤圆

发表于 2016-9-22 18:56:33 来自手机 | 显示全部楼层
个人认为效率不是首要考虑因素

出0入0汤圆

发表于 2016-9-22 23:18:04 | 显示全部楼层
觉得根据具体情况决定用不用吧,

出0入17汤圆

发表于 2016-9-22 23:31:04 | 显示全部楼层
感觉也没差到哪去

出0入0汤圆

发表于 2016-9-23 05:16:53 | 显示全部楼层
关键是要用正确的技术,例如使用 DMA 等等。就算库的效率不是特别高,结果差别也不会特别大。
如果你要库作很多中断处理的那效率影响就会比较多。

出0入0汤圆

发表于 2016-9-23 08:51:38 | 显示全部楼层
关键代码用寄存器就是了。

出0入0汤圆

发表于 2016-9-23 10:19:40 | 显示全部楼层
我还在用HAL库,觉得两面性吧,好处是初始化很方便,效率的话如果要求不高可以考虑使用,毕竟是ST官方的,而且以后的趋势就是HAL库了

出0入4汤圆

发表于 2016-9-23 10:33:12 | 显示全部楼层
对寄存器头大的人(寄存器一会就忘了)用CubeMX自动生成的模板好用,稍微改下就能用。

出100入101汤圆

发表于 2016-9-23 10:40:30 | 显示全部楼层
一般应用可以不考虑效率

出0入0汤圆

发表于 2016-9-23 11:05:18 | 显示全部楼层
clesun 发表于 2016-9-23 10:33
对寄存器头大的人(寄存器一会就忘了)用CubeMX自动生成的模板好用,稍微改下就能用。 ...

可以用他的初始化,但是我觉得模板有点乱,还是喜欢自己的模板

出0入0汤圆

发表于 2016-9-23 13:19:39 | 显示全部楼层
寄存器可读性不好,追求效率的地方才用寄存器

出0入0汤圆

发表于 2016-10-17 23:42:47 | 显示全部楼层
myxiaonia 发表于 2015-11-8 11:58
不管st乐意不乐意,mdk就是有这样的雄心壮志。。。

mdk和st是相辅相成的,st要是怠慢下mdk,mdk给st穿小 ...

请问,你说的mdk的usb库是指什么RL-USB吗?有没有这方面的资料。

出0入0汤圆

发表于 2016-10-18 09:09:49 | 显示全部楼层
HAL库里面提供了一个LL层(基本上是寄存器操作),两者可以结合使用。用HAL初始化,具体的操作使用LL层即可。

出0入0汤圆

发表于 2016-10-23 11:32:50 | 显示全部楼层
cat_li 发表于 2016-10-18 09:09
HAL库里面提供了一个LL层(基本上是寄存器操作),两者可以结合使用。用HAL初始化,具体的操作使用LL层即可 ...

我比较赞成你的想法,HAL库初始化还是比较好用的,中断部分自己操作寄存器或者用LL库都可以,代码量也不多,相互结合,开发效率就高了

出0入0汤圆

发表于 2016-10-23 12:34:05 | 显示全部楼层
myxiaonia 发表于 2015-11-8 11:56
可以尝试下用mdk的usb库,虽然没有源码,基本上都移植好了直接能用,自用感觉不错 ...

这个哪里有得下载?

出0入0汤圆

发表于 2016-10-25 22:01:21 | 显示全部楼层
HAL库的思想感觉是把所有的中断全部打开然后填回调函数来实现中断应该处理的程序,感觉很恼火,我在公司都直接操作寄存器,比HAL库好用多了,以前耍F1的时候那个基本库还可以

出0入0汤圆

发表于 2016-10-27 09:50:01 | 显示全部楼层
cchwhk 发表于 2016-10-25 22:01
HAL库的思想感觉是把所有的中断全部打开然后填回调函数来实现中断应该处理的程序,感觉很恼火,我在公司都 ...

所以作为补充,HAL库里有提供了一个LL层。实际上只用LL层来写代码也挺方便的。

出0入4汤圆

发表于 2016-10-27 09:58:33 | 显示全部楼层
cat_li 发表于 2016-10-27 09:50
所以作为补充,HAL库里有提供了一个LL层。实际上只用LL层来写代码也挺方便的。 ...

怎么说?LL层怎么操作?

出0入0汤圆

发表于 2016-10-27 10:14:29 | 显示全部楼层
类似下面的,
设置spi时序,直接设置就可以,不需要结构体初始化
LL_SPI_SetClockPhase(spi, LL_SPI_PHASE_1EDGE);
LL_SPI_SetClockPolarity(spi, LL_SPI_POLARITY_LOW);
本身这两个函数是 inline ,并且直接操作寄存器

__STATIC_INLINE void LL_SPI_SetClockPhase(SPI_TypeDef *SPIx, uint32_t ClockPhase)
{
  MODIFY_REG(SPIx->CR1, SPI_CR1_CPHA, ClockPhase);
}

__STATIC_INLINE void LL_SPI_SetTransferDirection(SPI_TypeDef *SPIx, uint32_t TransferDirection)
{
  MODIFY_REG(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE, TransferDirection);
}

__STATIC_INLINE void LL_APB1_GRP1_EnableClock(uint32_t Periphs)
{
  __IO uint32_t tmpreg;
  SET_BIT(RCC->APB1ENR, Periphs);
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->APB1ENR, Periphs);
  (void)tmpreg;
}

即使是利用结构体初始化,其内部也是寄存器操作
static ErrorStatus IC1Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
{
  /* Check the parameters */
  assert_param(IS_TIM_CC1_INSTANCE(TIMx));
  assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
  assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
  assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
  assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));

  /* Disable the Channel 1: Reset the CC1E Bit */
  TIMx->CCER &= (uint32_t)~TIM_CCER_CC1E;

  /* Select the Input and set the filter and the prescaler value */
  MODIFY_REG(TIMx->CCMR1,
             (TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC),
             (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U);

  /* Select the Polarity and set the CC1E Bit */
  MODIFY_REG(TIMx->CCER,
             (TIM_CCER_CC1P | TIM_CCER_CC1NP),
             (TIM_ICInitStruct->ICPolarity | TIM_CCER_CC1E));

  return SUCCESS;
}

HAL库更多考虑代码的健壮,内部做了很多的判断

出0入8汤圆

发表于 2016-10-27 10:20:54 | 显示全部楼层
乱七八糟

用HAL,cubemx ,只是为了初学者加入

如果哪个工程师用这种方式开发产品,在我这边一定给PASS

出0入0汤圆

发表于 2016-10-27 10:37:05 | 显示全部楼层
10xjzheng 发表于 2015-11-6 21:02
目的是好的,但是不懂原理的设计程序在我看来很难做好高效率驱动。
另外HAL跟嵌入式系统没有半毛钱关系, ...

楼主,支持你,寄存器什么的还是得吃透,靠这些花里胡哨的东西始终要吃大亏的。
别和一些新手一般见识,没有踏踏实实做过好产品,光玩过开发板的,你和他们说有意思吗?

出0入4汤圆

发表于 2016-10-27 10:59:19 | 显示全部楼层
cat_li 发表于 2016-10-27 10:14
类似下面的,
设置spi时序,直接设置就可以,不需要结构体初始化
LL_SPI_SetClockPhase(spi, LL_SPI_PHASE_ ...

这个要看看,更改一个PWM的频率,实例代码一堆,基本把所有的参水都重设,我的理解是改一个寄存器就够了,大不了重新启动一下,没曾想有些东西不是注释掉不用的就行的。

出0入0汤圆

发表于 2016-10-27 11:50:22 | 显示全部楼层
LL层的例程代码
STM32Cube_FW_F0_V1.6.0\Projects\STM32F072RB-Nucleo  这个目录下比较齐全,其它的只有几个,或者没有

出0入0汤圆

发表于 2016-10-27 12:43:19 | 显示全部楼层
现在用L系列的,只提供hal库

出0入0汤圆

发表于 2016-11-18 23:27:28 | 显示全部楼层
cat_li 发表于 2016-10-27 09:50
所以作为补充,HAL库里有提供了一个LL层。实际上只用LL层来写代码也挺方便的。 ...

具体不知道,我大部分都是直接操作寄存器

出10入10汤圆

发表于 2016-11-19 07:48:29 | 显示全部楼层
降低了代码效率,提高了开发效率?

出0入0汤圆

发表于 2016-11-19 08:59:47 | 显示全部楼层
10xjzheng 发表于 2015-11-6 18:10
串口接收中断那里,所有的中断都检测一遍,虽然这个很有通用性,但是你只是想接收个串口数据而已啊,要不要 ...

将不用的隐藏掉就行了

出0入10汤圆

发表于 2016-11-19 09:20:03 | 显示全部楼层
我觉得这是趋势,就像以前大家为了效率和空间去用汇编,现在估计很少人这么干了!
以后芯片更新和迭代会更快的,性能也会越来越好,到时候我们考虑更多的是开发时间和成本问题!
估计也是极少情况下你才会考虑去优化性能.
就比如现在的MCU主频是1GHZ,你还会浪费几天的时间和精力去熟悉寄存器吗

出0入10汤圆

 楼主| 发表于 2016-11-20 08:39:45 | 显示全部楼层
dwiller_ARM 发表于 2016-11-19 09:20
我觉得这是趋势,就像以前大家为了效率和空间去用汇编,现在估计很少人这么干了!
以后芯片更新和迭代会更 ...

现在我也是赞同,慢慢地会向树莓派那边靠边,到时可就不是EE工程师来做了,而是原厂+CS程序员。

出0入0汤圆

发表于 2016-11-27 21:58:56 | 显示全部楼层
HAL库也是为方便用户使用的,自己可以取舍搭配使用。

出0入0汤圆

发表于 2016-11-28 11:36:02 | 显示全部楼层
附一段代码:
/* GPIOx_CRL and GPIOx_CRH
*cnf[1:0]|mode[1:0]
* |        |                | |-------00:input mode        01:output mode 10MHz
* |        |                |---------10:output mode 2MHz 11:output mode 50MHz
* |         |-----------------mode[1:0]=0->00:analog 01:floating input 10:input 11:res
* |-------------------mode[1:0]>0->00:output push/pll 01:open drain 10:alternate push/pll
* |-------------------mode[1:0]>0->11:alternate open drain
* configure PA9,PA10 as USART1, PB10,PB11 as ouput
* basic input: 0x08
* basic output:0x01 || 0x03
* analog input:0x00
* afio output: 0x09
* floating input: 0x04
*/
#define        GPIO_CONFIG_PORTA_CRL                0x09914944
                                                                         /*||||||||----PA0->CRH[PA8]
                                                                             |||||||-----PA1->CRH[PA9]
                                                                             ||||||------PA2->CRH[PA10]
                                                                             |||||-------PA3->CRH[PA11]
                                                                             ||||--------PA4->CRH[PA12]
                                                                             |||---------PA5->CRH[PA13]
                                                                             ||----------PA6->CRH[PA14]
                                                                      |-----------PA7->CRH[PA15]*/

       /* 配置PORT A端口 */
        GPIOA->CRL = GPIO_CONFIG_PORTA_CRL;
其实不用库有一大堆道理,用hal的人也有道理
看你追求的是什么,追求效率,请远离hal;追求开发速度,请熟悉hal机制.

出0入0汤圆

发表于 2016-11-28 13:31:32 | 显示全部楼层
楼主说对了一点,效率是不怎么高 。 但是大部分时候没什么影响的,接受数据实时要求高,可以考虑自己写。 但是不能否定HAL的实用性,小项目用cube 不用看手册,一天能搞定了。 如果自己写就未必了。

出0入0汤圆

发表于 2017-2-12 11:14:34 | 显示全部楼层
弱弱的问一下,如果执行到这里 huart->ErrorCode |= HAL_UART_ERROR_NE;串口就再也接收不到数据了,我在这里应该怎么处理呀

出0入0汤圆

发表于 2017-6-6 14:00:51 | 显示全部楼层
本帖最后由 kinsno 于 2017-6-6 14:04 编辑

我终于理解楼主为啥吐槽HAL了。
特别是看到串口这里,真是奇葩的接收回调,谁敢说它用HAL不改代码,那我就服他。
PS:希望后面其它别的不会这样子奇葩吧。
PS2: 真是可怕的设计,代码里看到了C++的影子,为何不直接设计成C++,设计者真是脑子不太正常。







出0入0汤圆

发表于 2017-6-6 15:52:28 | 显示全部楼层
我去年开始使用HAL库,没发现什么不妥。

出0入0汤圆

发表于 2017-6-16 10:21:52 | 显示全部楼层
用库总归是没有直接用寄存器效率高,但是也要看应用场合,要求不高用库完全没问题,除非你对时序要求极高

出0入0汤圆

发表于 2017-7-2 22:18:23 | 显示全部楼层
jingwaner 发表于 2016-10-27 10:20
乱七八糟

用HAL,cubemx ,只是为了初学者加入

我这相反, 如果哪个工程师,做事不知道什么是效率和可靠性,缺乏标准意识的自我意淫,天天没事就研究底层倒底是这个好还是那个好,我一定pass。

出0入0汤圆

发表于 2017-7-3 00:43:47 来自手机 | 显示全部楼层
当年也有过汇编和c语言之争

出0入8汤圆

发表于 2017-7-3 09:01:44 | 显示全部楼层
相由心生 发表于 2017-7-2 22:18
我这相反, 如果哪个工程师,做事不知道什么是效率和可靠性,缺乏标准意识的自我意淫,天天没事就研究底层 ...

有几种情况会让你头疼:

1、ST缺货了,老板要你马上换其他品牌MCU,比如NXP,NUVTON,限你一周内完成代码移植

2、ST只提供HOST驱动U盘的例子,因项目需要,要你改个驱动USB打印机

3、数据需要快收快处理

如果一个工程师连编译原理,数据结构都不懂,这种小学生我也PASS

出0入0汤圆

发表于 2017-7-3 09:03:40 | 显示全部楼层
10xjzheng 发表于 2015-11-6 18:01
我在一个中断中开启串口接收中断,任何然后丢了几个数据,因为初始化过程很繁琐,本来置寄存器即可,现在 ...

UART我使用DMA来处理,就不会丢数据了,要不然收不及时 。

出0入0汤圆

发表于 2017-7-3 10:01:20 | 显示全部楼层
jingwaner 发表于 2017-7-3 09:01
有几种情况会让你头疼:

1、ST缺货了,老板要你马上换其他品牌MCU,比如NXP,NUVTON,限你一周内完成代 ...

有几种情况会让你头疼:

1、ST缺货了,老板要你马上换其他品牌MCU,比如NXP,NUVTON,限你一周内完成代码移植

2、ST只提供HOST驱动U盘的例子,因项目需要,要你改个驱动USB打印机

3、数据需要快收快处理

如果一个工程师连编译原理,数据结构都不懂,这种小学生我也PASS


说明
1、这家公司是小公司,不会有巨大前途。芯片切换至少要留1至2个月时间。切换芯片,至少要重新测试,认证等,硬件的更换周期至少要1个月。
2、同上,不一定什么都需要自己的工程师来完成,可以找st的协助,也可以找外协。
3、即使在F0的主频下,类似串口这样的低速设备,多半是卡在软件驾构下,没有缓冲,DMA使用混乱,流程不清晰,之前的技术积累为0(那么这家公司也不适合继续待下去),其它任务影响没搞清楚。
4、对于工程师有编译原理、数据结构的要求的,要么是超级公司偏僻职位,要么就是小公司主管个人爱好,无论是以上两个哪个选项,这家公司肯定不会提供高薪,也不会提供持续成长的道路。

对于工程师而言,这是场噩梦。
对于大部分中国企业来讲,如果可靠有效率的完成任务,不把时间浪费在GCC倒底有几条指令,堆和栈到底有什么区别上更有意义。
这也从事实上讲明,大部分的安卓和IOS工程师的收入比电工高很多。

不需要所有的人都做底层技术,关注社会,关注前途。选择比专注更重要。

出0入0汤圆

发表于 2017-8-8 21:56:44 | 显示全部楼层
现在开发都会向着软件开发演进, 硬件就即使是单片机硬件性能也不错了, 做开发讲究的是一个性价比, 在可控的前提下, 降低成本, 一个项目不可能每个都是非常精通的, 只需要几个人精通, 其他人可以正常搬砖就行的, 精通的人负责review代码, 或者关键代码的编写, 这样的搭配, 是可控成本低见效快的, 我见过一些互联网的快速开发, 很多都是这样的, 甚至就是面向api开发, 你自己关注你的核心竞争力就行了, 你的产品买出去并不是代码的效率有多高, 而是你的产品 满足客户需要或者产品好看巴拉巴拉,,
说的难听一点这点代码效率值几个钱?有调api快速开发的这点时间值钱么? 我们需要做的就是拥抱变化, 就像c把asm替代大部分, 可能有一天可以用lua甚至更高级的语言开发, 那也不一定

出0入0汤圆

发表于 2017-8-9 11:42:03 | 显示全部楼层
本帖最后由 flash3g 于 2017-8-9 11:44 编辑

同意楼主说的,HAL库不好玩

出0入0汤圆

发表于 2017-8-9 13:36:37 | 显示全部楼层
cube 这是方便  毒药啊

出0入0汤圆

发表于 2017-8-11 13:40:03 | 显示全部楼层
10xjzheng 发表于 2015-11-6 18:10
串口接收中断那里,所有的中断都检测一遍,虽然这个很有通用性,但是你只是想接收个串口数据而已啊,要不要 ...

同意楼主看法,面明占用程序空间。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 16:43

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表