![366dac596156ccc5817b57ed6d0f337c.png](https://img-blog.csdnimg.cn/img_convert/366dac596156ccc5817b57ed6d0f337c.png)
STM32CubeMX + HAL一些说明底层配置Cube基本使用HAL库函数中断回调函数外设对应时钟配置示例小编有话说USARTRTCSDIO + FATFSSDRAMLTDC + DMA2DFreeRTOSTouchGFX显示LittleVGL待补充...
STM32CubeMX + HAL
一些说明
底层配置
使用STM32CubeMX
代码生成工具,不用关注底层配置的细节,真舒服。
使用教程:
https://sxf1024.lanzoui.com/b09rf2dwj 密码:bgvi
虽然Cube+HAL
很舒服,但新手不建议用。最好还是先去学一下标准库怎么用,有个大致概念后,再来学这一套。
Cube基本使用
- 新建工程
- 选择芯片
- Pinout&Configuration,选择
RCC(HSE:Crystal/Ceramic Resonator)
、SYS(Debug:Serial Wiire)
- Clock Configuration,配置时钟树
![92cfaea9b64653a38c5cebc69efadb57.png](https://img-blog.csdnimg.cn/img_convert/92cfaea9b64653a38c5cebc69efadb57.png)
- Project Manager,配置工程输出项
![9b6f25a86f48c1dc3dd1a3bcecbe6fa7.png](https://img-blog.csdnimg.cn/img_convert/9b6f25a86f48c1dc3dd1a3bcecbe6fa7.png)
- Pinout&Configuration,选择功能(若是选
GPIO
相关,可以直接在Pinout view选择;若是其他功能,可以在左边Categories打开,会自动配置引脚)、设置Parameter Settings/NVIC
等
![7f920808e1b5b1774baaa83c7e00303e.png](https://img-blog.csdnimg.cn/img_convert/7f920808e1b5b1774baaa83c7e00303e.png)
- GENERATE CODE,生成工程,用KEIL打开编辑
HAL库函数
- 函数形式:均以
HAL_
开头 - 寻找过程:在驱动文件
stm32f4xx_hal_XXX.c
或其.h
文件中找函数定义,一般在靠后位置 - 其他说明:
HAL
库并没有把所有的操作都封装成凼数。- 对于底层的寄存器操作(如读取捕获/比较寄存器),还有修改外设的某个配置参数(如改变输入捕获的极性),
HAL
库会使用宏定义来实现。而且会用__HAL_
作为这类宏定义的前缀。 - 获取某个参数,宏定义中一般会有
_GET
;而设置某个参数的,宏定义中就会有_SET
。 - 在开发过程中,如果遇到寄存器级别或者更小范围的操作时,可以到该外设的头文件中查找,一般都能找到相应的宏定义。
HAL
库函数第一个参数一般都是句柄(一个包含了当前对象绝大部分状态的结构体),虽然增加了开销,但是用起来便捷了非常多。
中断回调函数
- 函数形式:
HAL_XXX_XXXCallback()
。 - 寻找过程:中断文件
stm32f4xx_it.c
- > 中断函数XXX_IRQHandler(void)
-> HAL库中断函数HAL_XXX_IRQHandler(GPIO_PIN_13)
-> 回调函数HAL_XXX_XXXCallback()
外设对应时钟
- 随便进入一个外设初始化函数,如
MX_GPIO_Init()
- 随便进入一个时钟使能函数,如
__HAL_RCC_GPIOC_CLK_ENABLE()
- 随便进入一个RCC宏定义,如
RCC_AHB1ENR_GPIOCEN
- 或者直接进入
stm32f429xx.h
文件 - 里面有所有外设与时钟对应关系,如
RCC_AHB1ENR_DMA1EN
配置示例
小编有话说
- 例子源码:https://sxf1024.lanzoui.com/b09rf535a 密码:bf5q
- 如果配置过程中,参数不知道怎么设置,可以去标准库例程(如野火、正点原子)中看对应的参数是什么
- Cube软件只是帮你配置了底层,一些初始化代码还是需要自己手动加的,如SDRAM充电初始化、读写函数等
- 以下内容都是基于“野火F429IGT6挑战者V2开发板”,其他板子按照原理图改改引脚都能用的
USART
源码链接:
https://sxf1024.lanzoui.com/b09rf535a 密码:bf5q
详细教程网上挺多,配置也简单,只要勾选一下USARTx,再开一下中断就行。
![693f51ea01cd85c6f9bccd6efb340339.png](https://img-blog.csdnimg.cn/img_convert/693f51ea01cd85c6f9bccd6efb340339.png)
在Keil就比较要注意了。
由于每次接收完,程序内部自动把接收中断关了,所以每次要手动打开。
总的来说,加这几部分:
main
函数中,while
之前:
// 使能串口中断接收
HAL_UART_Receive_IT(&huart1, (uint8_t*)&DataTemp_UART1, 1);
- 任意位置添加printf重定向函数:
#include "stdio.h"
int fputc(int ch, FILE *f){
HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 0XFF);
return ch;
}
- 任意位置添加中断回调函数:
#define UART1BuffLen 200
extern uint8_t DataBuff_UART1[UART1BuffLen];
extern uint32_t DataTemp_UART1;
extern uint16_t DataSTA_UART1;
uint32_t DataTemp_UART1;
uint8_t DataBuff_UART1[UART1BuffLen];
uint16_t DataSTA_UART1;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1){
if(DataSTA_UART1 < UART1BuffLen){
if(DataTemp_UART1 == 0x0A && DataSTA_UART1>0 && DataBuff_UART1[DataSTA_UART1-1]==0X0D){
printf("USART: %srn", DataBuff_UART1);
DataSTA_UART1 = 0;
}
else{
if(DataSTA_UART1 == 0){
memset(DataBuff_UART1, 0, sizeof(DataBuff_UART1));
}
DataBuff_UART1[DataSTA_UART1++] = DataTemp_UART1;
}
}
// 使能串口中断接收
HAL_UART_Receive_IT(&huart1, (uint8_t*)&DataTemp_UART1, 1);
}
}
RTC
![54a0ee214c4b39710d71b3ac979fbe1f.png](https://img-blog.csdnimg.cn/img_convert/54a0ee214c4b39710d71b3ac979fbe1f.png)
![67c576daeef0093623f631541874c4f8.png](https://img-blog.csdnimg.cn/img_convert/67c576daeef0093623f631541874c4f8.png)
![99ad5a1e4b8ada4a5ff1757b97ff3cf7.png](https://img-blog.csdnimg.cn/img_convert/99ad5a1e4b8ada4a5ff1757b97ff3cf7.png)
![852235e1e3f1365c9cfd5b964cfd5eb2.png](https://img-blog.csdnimg.cn/img_convert/852235e1e3f1365c9cfd5b964cfd5eb2.png)
RTC_DateTypeDef s