STM32F103RCT6学习笔记

问题解决

时钟资源无法使用外部时钟HSE、LSE

在RCC设置中打开

High Speed Clock(HSE)高速时钟
Low Speed Clock (LSE)低速时钟

CrystakCeramic Resonator 外部晶振时钟源
BYPASS Clock Source 旁路时钟源

printf重定向

按照教程重写fputc函数发现能在串口输出东西,但是是乱码
后来发现,那是使用keil编译器时才需要重写的函数,如果是GCC的话,需要重写 __io_putchar()_write()

int __io_putchar(int ch){
    uint8_t temp[1]={ch};
    HAL_UART_Transmit(&huart1,temp,1,0xff);
    return (ch);
}
int _write(int fd, char *ptr, int len)
{
    HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, 0xFFFF);
    return len;
}

使用clion自带的串口moniter时发现,不加printf内容最后要加\n,否则无法打印,原因未知

每次MX重新生成代码都需要重写CMakeList

在CMakelist_template中添加代码,CLion中选择update CMakelist with STM32CubeMX

使用uart中断回调函数实现串口收发时只能生效一次

查阅资料了解到HAL库对于USART的接收中断的处理,划分了好几层。

首先,串口接收中断触发后的入口程序在启动文件startup_stm32f401xc.s中定义为USART1_IRQHandler()和USART2_IRQHandler();

然后,USARTx_IRQHandler()的内容就一句:调用HAL_UART_IRQHandler();

接着,HAL_UART_IRQHandler()对一系列的异常场景进行处理后,再调用UART_Receive_IT();

最后,而在UART_Receive_IT()中,会判断RxXfeiCount值是否为0,当为0时就关断了串口接收中断!RxXfeiCount是UART结构体中“剩余待接收的数据计数值”。——也就是说,每当接收完HAL_UART_Receive_IT()函数中规定的RXBUFFERSIZE个数据就关闭接收中断。这也解释了为什么会出现只收到第1批数据后,再也无法接收数据的现象了。

HAL库对于串口接收中断处理的几层调用关系如下:

USARTx_IRQHandler()
 ┗━ HAL_UART_IRQHandler()
          ┗━ UART_Receive_IT()
                 {
                     if (--huart->RxXferCount == 0U)
                          {
                             /* Disable the UART Data Register not empty Interrupt */
                                __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
                      .......
                      .......
                      HAL_UART_RxCpltCallback();
                       .......
                   }

显然,在Main()中每次调用HAL_UART_Receive_IT()后,都能收到一批数据,那么采用循环的方式也可以持续接收到串口数据。但是这样做和“查询接收”没啥区别了吧。另一种更好的思路是:每完成一批数据接收后,自动使能接收中断。

而在UART_Receive_IT()函数中调用了接收回调函数HAL_UART_RxCpltCallback()。只要在这个回调函数中末尾再添加HAL_UART_Receive_IT(),重新打开串口接收中断、并设定接收的数据量就解决了。

提示:这里填写该问题的具体解决方案:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{ 
        .............
        .............
        HAL_UART_Receive_IT(UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
}

Q.E.D.