×
单片机 > 单片机程序设计 > 详情

有关STM32固件库的一些想法

发布时间:2020-08-27 发布时间:
|
有关STM32固件库的一些想法, 也许是本人一知半解,在此只想抛砖引玉.

最近在用STM32F做一个产品, 时间很紧. 这是第一次用它, 以前做过ARM7及用过多年的单片机.看了STM32F提供的固件库, 在ST网站上下载, 有KEIL的安装目录也有.有一些自己的想法, 想与大家交流.

很显然, STM32F是一款相当不错的芯片, 与我用过的ARM7相比, 我觉得性价比有一倍的差异.ST给我们提供了库,但就是这个固件库,让我觉得很不爽. 先来说一说这些傻瓜式的库.

因为要用多个串口, 看了KEIL提供的UART的SAMPLE程序, 其中MAIN里这样写

 /* Configure USART2 */

  USART_Init(USART2, &USART_InitStructure);

  

  /* Enable USART1 Receive and Transmit interrupt */

  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

  USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

  /* Enable USART2 Receive and Transmit interrupt */

  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

  USART_ITConfig(USART2, USART_IT_TXE, ENABLE);

  /* Enable the USART1 */

  USART_Cmd(USART1, ENABLE);

  /* Enable the USART2 */

  USART_Cmd(USART2, ENABLE);

  /* Wait until end of transmission from USART1 to USART2 */

  while(RxCounter2 

  {

  }

  /* Wait until end of transmission from USART2 to USART1 */

  while(RxCounter1 

  {

  }

  

  /* Check the received data with the send ones */

  TransferStatus1 = Buffercmp(TxBuffer2, RxBuffer1, RxBufferSize1);

  /* TransferStatus1 = PASSED, if the data transmitted from USART2 and  

     received by USART1 are the same */

  /* TransferStatus1 = FAILED, if the data transmitted from USART2 and 

     received by USART1 are different */

  TransferStatus2 = Buffercmp(TxBuffer1, RxBuffer2, RxBufferSize2);

  /* TransferStatus2 = PASSED, if the data transmitted from USART1 and  

     received by USART2 are the same */

  /* TransferStatus2 = FAILED, if the data transmitted from USART1 and 

     received by USART2 are different */

  while (1)

  {

  }

然后在中断IRQ中有这样的程序

 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)

  {

    /* Read one byte from the receive data register */

    RxBuffer2[RxCounter2++] = USART_ReceiveData(USART2);      

    /* Clear the USART2 Receive interrupt */

    USART_ClearITPendingBit(USART2, USART_IT_RXNE);

    if(RxCounter2 == NbrOfDataToRead1)

    {

      /* Disable the USART2 Receive interrupt */

      USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);

    }

  }

  

  if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)

  {   

    /* Write one byte to the transmit data register */

    USART_SendData(USART2, TxBuffer2[TxCounter2++]);                    

    /* Clear the USART2 transmit interrupt */

    USART_ClearITPendingBit(USART2, USART_IT_TXE); 

    if(TxCounter2 == NbrOfDataToTransfer2)

    {

      /* Disable the USART2 Transmit interrupt */

      USART_ITConfig(USART2, USART_IT_TXE, DISABLE);

    }    

  }

可以看到, 主程序并没有发送的语句,完全是在中断程序中发送和接收的,这正合我意, 这样做, 不用趴在那里等串口完成标志,有些类似于DMA. 但没有触发中断,怎么会发送, 在单片机C51中, 我会设置TI = 1, 通过软件触发中断.

看了一下SPEC, STM32F有一个发送缓冲区为空的中断TXE, 但就可,TXE需要等TXEIE标志为1才有效, TXEIE上电复位为0,那上面的语句为哪里置这个标志为1呢,只有 USART_ITConfig(USART2, USART_IT_TXE, ENABLE);这条语句了.

但这里是USART_IT_TXE,看了一下USART_IT_TXE的定义为0X727, 不知道为何是这样的一个值,也没有个说明.

继续看USART_ITConfig函数, 

  uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00;

  uint32_t usartxbase = 0x00;

  /* Check the parameters */

  assert_param(IS_USART_ALL_PERIPH(USARTx));

  assert_param(IS_USART_CONFIG_IT(USART_IT));

  assert_param(IS_USART_PERIPH_IT(USARTx, USART_IT)); /* The CTS interrupt is not available for UART4 and UART5 */

  assert_param(IS_FUNCTIONAL_STATE(NewState));

  usartxbase = (*(uint32_t*)&(USARTx));

  /* Get the USART register index */

  usartreg = (((uint8_t)USART_IT) >> 0x05); 

  /* Get the interrupt position */

  itpos = USART_IT & IT_Mask;

  itmask = (((uint32_t)0x01) <

    

  if (usartreg == 0x01) /* The IT is in CR1 register */

  {

    usartxbase += 0x0C;

  }

  else if (usartreg == 0x02) /* The IT is in CR2 register */

  {

    usartxbase += 0x10;

  }

  else /* The IT is in CR3 register */

  {

    usartxbase += 0x14; 

  }

  if (NewState != DISABLE)

  {

    *(__IO uint32_t*)usartxbase  |= itmask;

  }

  else

  {

    *(__IO uint32_t*)usartxbase &= ~itmask;

  }

上面的函数是根据定义的UARTX指针,得到UART的基地址, 然后在这个基地址为加上各个寄存器的偏移地址, 然后对寄存器操作.

回到USART_ITConfig(USART2, USART_IT_TXE, ENABLE);这条语句, USART_IT_TXE定义0X727, 最低字节的27位实际是对CR1的TXEIE置1, 拜托,,上面定义为TXE, 结果是对TXEIE来操作.

再来看上面的函数,那么一大堆语句, 不就是执行这个的一个功能吗?

If (ENABLE)

UART2_CR1 | = (1 << 0x07);  // SET TXEIE bit

Else 

UART2_CR1 & = ~ (1 << 0x07); // RESET TXEIE bit

究其原因, 是因为固件库, 是一个通用性的写法. 上面的UART寄存器,完全可定义直接的地址, 不用指针(也许这样用有特殊的用法)

这个函数是用在中断里的,执行这样的语句对性能是个不小的折扣. 象嵌入式系统的话, 本来资源就比较紧张.

所以, 我觉得使用固件库做产品的话, 值得考虑. 仅学习STM32的话,倒也无妨.

也许我是只见树本,不见森林.,还望大家批评指正.


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机制作超级流水灯