stm32 LL库usart串口
使用stm32cubemx也一段时间了,确实用起来方便。但是stm32cubemx基于的hal库随随便便配置个串口生成代码编译一看,已经占用了4K的flash空间了。这个对于使用低成本小内存类似stm32F030F4的单片机来说着实是一件痛苦的事情。那么就要考虑看是牺牲图形化配置的高效率还是牺牲单片机的flash空间。看来鱼与熊掌不可兼得啊。
不过最近stm32又发布了另一种库LL库。这个LL库相比HAL库更倾向于底层。所以自然编译出来的代码也可以省空间了。关键的是他也可以使用stm32cube用来配置,并且也可以选择和hal混合使用。最近正好要用到stm32F030F4的芯片串口,就先基于他做个实验。
好了,我们打开cubemx按照正常方式配置串口:
这个就不重点讲了,和hal配置的时候一样,配置中把波特率改为了115200,并且使能串口中断。关键点来了,下一步我要生成代码,那么我要怎么生成基于LL库的代码呢。首先你要保证把你的cubemx进行升级到最新版,然后才能操作下面一步。
这样生成代码就是串口部分和GPIO部分都是基于LL库的。因为我想用HAL_Delay函数,所以我就把RCC还是使用HAL库。我查了st官方的资料,现在针对LL的说明还很少,我没有查到相关的API说明,所以只能看stm32F0xx_ll_usart.h文件看有哪些接口了。里面的接口函数相当多,实际上也都是把操作寄存器用函数进行了一个封装。这个真的是比以前的标准外设库还要底层。
那么我想让uart串口工作起来又该调用哪些接口函数?建议st尽快出一个LL库的接口文档也方便查找。
我要实现的是用中断接收数据,接收到以后再发送出去。而我看了生成的初始化代码,默认是没有打开接收中断的,所以我自己又建立了个初始化的函数:
1 2 3 4 5 |
void user_usartInit() { LL_USART_EnableIT_RXNE(USART1); LL_USART_EnableIT_PE(USART1); } |
这两句一句是打开接收完成中断,一句是打开串口总中断的。
然后就是在main函数里面调用了他:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration----------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_5); user_usartInit(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_Delay(1000); } /* USER CODE END 3 */ } |
这样整个串口初始化才算完成。然后就是中断服务函数了,这个是在stm32F0xx_it.c文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ uint8_t tmp; if(LL_USART_IsActiveFlag_RXNE(USART1)) //检测是否接收中断 { LL_GPIO_ResetOutputPin(GPIOA,LL_GPIO_PIN_5); tmp=LL_USART_ReceiveData8(USART1); //读取出来接收到的数据 LL_USART_TransmitData8(USART1,tmp); //把数据再从串口发送出去 } /* USER CODE END USART1_IRQn 0 */ /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ } |
这样需要的功能就完成了。是不是挣个流程比hal库清爽多了。但是上手难度肯定会提供了,有很多功能看是要去看参考手册的。