一.库开发的优势
开发速度快,便于移植。
二.stm32F7xx几个重要文件
1. HAL库关键文件
2.stm32f7xx_it.c/h
中断服务函数。基本都是空函数,我们可以去掉里面的函数,把中断服务函数写在任意可见的文件中。
3.stm32f7xx.h
所有F7系列的顶层头文件。通过条件编译包含某型号的头文件(此宏一般在target——c/c++里面定义STM32F767xx,后面都以stm32f767为例)。
- #if defined(STM32F756xx)
- #include "stm32f756xx.h"
- #elif defined(STM32F746xx)
- #include "stm32f746xx.h"
- #elif defined(STM32F745xx)
- #include "stm32f745xx.h"
- #elif defined(STM32F765xx)
- #include "stm32f765xx.h"
- #elif defined(STM32F767xx)
- #include "stm32f767xx.h"
- #elif defined(STM32F769xx)
- #include "stm32f769xx.h"
- #elif defined(STM32F777xx)
- #include "stm32f777xx.h"
- #elif defined(STM32F779xx)
- #include "stm32f779xx.h"
- #else
- #error "Please select first the target STM32F7xx device used in your application (in stm32f7xx.h file)"
- #endif
复制代码
4.stm32f767xx.h
主要就是寄存器的声明(一堆结构体和宏定义)。
5.system_stm32f7xx.c/h
主要定义了SystemInit和SystemCoreClockUpdate两个函数,后续会在这个文件里面加一个SetSysClock()函数. SystemInit主要是时钟系统的初始化和中断向量偏移地址设置(有bootloader的向量偏移需要修改)。SystemCoreClock是一个全局的值(这个在FreeRTOS的时钟配置的时候需要)。
6.stm32f7xx_hal_msp.c
带MspInit的函数进行MCU级别硬件初始化设置,通常被上一层调用(如HAL_UART_Init——HAL_UART_MspInit)。
7.startup_stm32f767xx.s
启动文件,上电先运行SystemInit,再运行到main。
- ; Reset handler
- Reset_Handler PROC
- EXPORT Reset_Handler [WEAK]
- IMPORT SystemInit
- IMPORT __main
- LDR R0, =SystemInit
- BLX R0
- LDR R0, =__main
- BX R0
- ENDP
复制代码
三.HAL库中__weak修饰符
weak:弱。被__weak修饰的函数就是“弱函数”,我们可以在自定义的文件中重新定义此函数(去掉__weak),编译器会执行我们自定义的函数。HAL库中一般在回调函数时用到。HAL中默认定义一个空的回调函数,保证编译器不会报错。
四.程序的执行过程
Reset_Handler —— SystemInit —— main —— HAL_init —— SetSysClock —— xxxInit…(FreeRTOS:xTaskCreate —— xTaskCreate)
五.启动文件
主要指令:
Stack——栈,Stack_Size EQU 0x00000400 (局部变量,函数形参,函数调用等),值可以人为修改(不能超过内部SRAM)。
Heap——堆,Heap_Size EQU 0x00000200(动态内存分配malloc/free)
向量表——中断向量服务函数
复位程序——先进入SystemInit——main
关于启动文件详细描述请参考:STM32启动文件详细说明
六.时钟设置(设置系统时钟)
- /************************* PLL Parameters *************************************/
- //时钟设置函数
- //Fvco=Fs*(plln/pllm);
- //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
- //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
- //Fvco:VCO频率
- //Fsys:系统时钟频率
- //Fusb:USB,SDIO,RNG等的时钟频率
- //Fs:PLL输入时钟频率,可以是HSI,HSE等.
- //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.
- //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
- //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
- //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
- //外部晶振为25M的时候,推荐值:plln=432,pllm=25,pllp=2,pllq=9.
- //得到:Fvco=25*(432/25)=432Mhz
- // Fsys=432/2=216Mhz
- // Fusb=432/9=48Mhz
- #define PLL_M 25
- #define PLL_Q 9
- #define PLL_N 432
- #define PLL_P 2
- void SetSysClock(void)
- {
- HAL_StatusTypeDef ret = HAL_OK;
- RCC_OscInitTypeDef RCC_OscInitStructure;
- RCC_ClkInitTypeDef RCC_ClkInitStructure;
- // __HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
- RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE; //时钟源为HSE
- RCC_OscInitStructure.HSEState = RCC_HSE_ON; //打开HSE
- RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON; //打开PLL
- RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE; //PLL时钟源选择HSE
- RCC_OscInitStructure.PLL.PLLM = PLL_M; //主PLL和音频PLL分频系数(PLL之前的分频)
- RCC_OscInitStructure.PLL.PLLN = PLL_N; //主PLL倍频系数(PLL倍频)
- RCC_OscInitStructure.PLL.PLLP = PLL_P; //系统时钟的主PLL分频系数(PLL之后的分频)
- RCC_OscInitStructure.PLL.PLLQ = PLL_Q; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)
- ret = HAL_RCC_OscConfig(&RCC_OscInitStructure); //初始化
- if(ret != HAL_OK) while(1);
- ret = HAL_PWREx_EnableOverDrive(); //开启Over-Driver功能
- if(ret != HAL_OK) while(1);
- //选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2
- RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
- RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //设置系统时钟时钟源为PLL
- RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1; //AHB分频系数为1
- RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4; //APB1分频系数为4
- RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2; //APB2分频系数为2
- ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_7); //同时设置FLASH延时周期为7WS,也就是8个CPU周期。
- if(ret != HAL_OK) while(1);
- }
复制代码
|