最近在用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的话,倒也无妨.
也许我是只见树本,不见森林.,还望大家批评指正.
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』