Help getting Started with STM32 using the HAL Drivers - Page 1
Forum section: electronics / beginners

author: fomu
author_rank: Newbie
timestamp: March 21, 2015, 02:00:14 am
content: Hello EEVbloggers,This is my first post as I just joined the community.I recently bought a STM32F407 Discovery board by ST Microelectronics.As I´m new to ARM, I´ve searched the web for good learning resources besides the documentation that comes from the manufacturer STM. Currently I´m using the following documents for my experiments:UM1725 Description of the STM32F4 HAL driversSTM32F407xx DatasheetRM0090 Reference ManualUM1472 User Manual for Discovery Kit for STM32F407/17I´m using IAR Embedded Workbench for coding.And to create the projects I use STM32CubeMX.I´ve managed to make a blinking led tutorial from a webpage I saw. The thing is that this, just as other tutorials I´ve seen use the STM32 standard library and since I use STM32CubeMX, most of those tutorials don´t work for me.I´ve been trying to make a PWM for about a two weeks and still haven´t had any success.So my questions are:Is there any good books, webpage or any other kind of resource that explains how to program STM32 using the HAL library from scratch?Does anyone here use the HAL library so that I could show you my code and see whats the problem?Below is the code I made with my lacky knowledge.Thanks and regards!!!Code:/********************************************************************************* File Name : main.c* Date : 18/03/2015 20:46:45* Description : Main program body******************************************************************************** COPYRIGHT(c) 2015 STMicroelectronics** Redistribution and use in source and binary forms, with or without modification,* are permitted provided that the following conditions are met:* 1. Redistributions of source code must retain the above copyright notice,* this list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright notice,* this list of conditions and the following disclaimer in the documentation* and/or other materials provided with the distribution.* 3. Neither the name of STMicroelectronics nor the names of its contributors* may be used to endorse or promote products derived from this software* without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.********************************************************************************//* Includes ------------------------------------------------------------------*/#include "stm32f4xx_hal.h"/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/void SystemClock_Config(void);void TIM_Initialize(void);/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* USER CODE BEGIN 0 *//* USER CODE END 0 */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();/* Configure the system clock */SystemClock_Config();/* Initialize all configured peripherals */TIM_Initialize();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* USER CODE BEGIN 3 *//* Infinite loop */while (1){}/* USER CODE END 3 */}/** System Clock Configuration*/void SystemClock_Config(void){RCC_OscInitTypeDef RCC_OscInitStruct;__PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = 6;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;HAL_RCC_OscConfig(&RCC_OscInitStruct);}// First we initialize the TIM low level resources:void TIM_Initialize(void){/*--------------PWM_MSP_Init------------------*/// Invocation of PWM_MspInit()TIM_HandleTypeDef TIM_HandleTypeDefStruct;TIM_HandleTypeDefStruct.Instance= TIM4;HAL_TIM_ActiveChannel Channel_1=HAL_TIM_ACTIVE_CHANNEL_1;TIM_HandleTypeDefStruct.Channel=Channel_1;//Define the elements of the TIM_Base_InitTypeDef structTIM_Base_InitTypeDef TIM_Base_InitTypeDefStruct;TIM_Base_InitTypeDefStruct.Prescaler=0; // No prescaleTIM_Base_InitTypeDefStruct.CounterMode = TIM_COUNTERMODE_UP; // Timer count upTIM_Base_InitTypeDefStruct.Period= 100; // Period of counter to 100 cyclesTIM_HandleTypeDefStruct.Init = TIM_Base_InitTypeDefStruct; //Load the elements into the structureTIM_HandleTypeDef* htim= &TIM_HandleTypeDefStruct; //Pass the data to a pointer variableHAL_TIM_PWM_MspInit(htim); //Pass the variable as argument to PWM_MspInit()/*---------------CLOCKS---------------*///Initialize the timer related clocks__TIM4_CLK_ENABLE();__GPIOD_CLK_ENABLE();/*---------------GPIO-----------------*/// GPIO TypeDef InitializationGPIO_TypeDef GPIO_TypeDefStruct;/* // No se para que mierda es esto si uso PWMGPIO_TypeDefStruct.MODER |= ((31<<1)|(29<<1)|(27<<1)|(25<<1));GPIO_TypeDefStruct.OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR15_1 | GPIO_OSPEEDER_OSPEEDR_14_1GPIO_OSPEEDER_OSPEEDR13_1 | GPIO_OSPEEDER_OSPEEDR_12_1);*/GPIO_TypeDefStruct.AFR |=(28<<GPIO_AF2_TIM4|24<<GPIO_AF2_TIM4|20<<GPIO_AF2_TIM4|16<<GPIO_AF2_TIM4);GPIO_TypeDef* GPIO_D = & GPIO_TypeDefStruct;//GPIO InitTypeDef InitializationGPIO_InitTypeDef GPIO_InitTypeDefStruct;GPIO_InitTypeDefStruct.Pin = GPIO_PIN_12;GPIO_InitTypeDefStruct.Mode= GPIO_MODE_AF_OD;GPIO_InitTypeDef* GPIO_Init= & GPIO_InitTypeDefStruct;HAL_GPIO_Init(GPIO_D,GPIO_Init);/*-------------------Hal TIM PWM Init-----------------*/HAL_TIM_PWM_Init(htim);/*-------------HAL_TIM_PWM_ConfigChannel--------------*/TIM_OC_InitTypeDef TIM_OC_InitTypeDefStruct;TIM_OC_InitTypeDef* sConfig =& TIM_OC_InitTypeDefStruct;HAL_TIM_PWM_ConfigChannel(htim,sConfig,TIM_CHANNEL_1);/*----------------HAL_TIM_PWM_Start-------------------*/HAL_TIM_PWM_Start(htim,TIM_CHANNEL_1);}/* USER CODE BEGIN 4 *//* USER CODE END 4 */#ifdef USE_FULL_ASSERT/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/void assert_failed(uint8_t* file, uint32_t line){/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */}#endif/*** @}*//*** @}*//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: March 21, 2015, 02:26:06 am
content: I have the pwm working using HAL for the STM32F030 chips.I haven't used HAL with the STM32F4XX chips.What doesn't work?Cant compile?Timers not set up right?In the cube download zip there should be an example project in something like the "examples/TIM" folder. At least there was for the F0 chips.Also there should probably be two data sheets relevant to your chip not just the one you have listed.One which covers the pinouts and alternate functions which is the STM32F407xx Datasheet and is relatively short. But the one you need will be calledSTM32F4.pdf or similar maybe DM00031020 STM32F4.pdf the key factor here is that it is massive. 1000+ pages. that will give you all the details.Many people don't like the HAL including importantly Clive1 from the ST forums.I don't find it better or worse that the previous libraries.

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: March 21, 2015, 02:28:57 am
content: Just noticed you posted your code.Did it compile and link.Can you attach a debugger? Should be easy if you have a Dev board. I find that so useful.Also make your code more readable using the insert code button next to the insert quote button.

author: AndreasF
author_rank: Frequent Contributor
timestamp: March 21, 2015, 10:13:27 am
content: Yes, the HAL/CUBE libraries are not very popular (there's a whole thread here just about this).Having a quick look at your code, this looks suspicious:Code:/*---------------GPIO-----------------*/// GPIO TypeDef InitializationGPIO_TypeDef GPIO_TypeDefStruct;/* // No se para que mierda es esto si uso PWMGPIO_TypeDefStruct.MODER |= ((31<<1)|(29<<1)|(27<<1)|(25<<1));GPIO_TypeDefStruct.OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR15_1 | GPIO_OSPEEDER_OSPEEDR_14_1GPIO_OSPEEDER_OSPEEDR13_1 | GPIO_OSPEEDER_OSPEEDR_12_1);*/GPIO_TypeDefStruct.AFR |=(28<<GPIO_AF2_TIM4|24<<GPIO_AF2_TIM4|20<<GPIO_AF2_TIM4|16<<GPIO_AF2_TIM4);GPIO_TypeDef* GPIO_D = & GPIO_TypeDefStruct;//GPIO InitTypeDef InitializationGPIO_InitTypeDef GPIO_InitTypeDefStruct;GPIO_InitTypeDefStruct.Pin = GPIO_PIN_12;GPIO_InitTypeDefStruct.Mode= GPIO_MODE_AF_OD;GPIO_InitTypeDef* GPIO_Init= & GPIO_InitTypeDefStruct;HAL_GPIO_Init(GPIO_D,GPIO_Init);In the first part you seem to be trying to use the GPIO registers directly, but in the second, you're using the HAL functions & structures to do the initializations. The problem is, by the end of the first part you've re-assigned GPIO_D to a different value (the address of the GPIO_Type structure you previously declared - I'm surprised it lets you do this!).If you want to use the HAL libraries you don't need that first part. That's the whole point of these libraries, to avoid having to deal with registers directly (HAL = hardware abstraction library/layer).The most helpful document for me learning the Standard Peripheral Library was actually the "Compiled HTML Help file" that came with the library, because it referenced all the functions and structures, which were all nicely cross linked, so it was easy to see what type of input the different functions expected, and what valid value options were. The HAL has this as well, though I haven't looked at it in detail.

author: dannyf
author_rank: Super Contributor
timestamp: March 21, 2015, 01:41:35 pm
content: Getting pwm on those chips are simple:1) set the time base for pwm's frequency;2) set the output compare for the duty cycle;3) set the pins for alternate functions.then you are done.I don't use the cube stuff but it is mostly identical to the standard peripheral library - which I do use. I can post some simple code to get you started on the standard peripheral library but you will need to find the corresponding functions for your chip / cube version.The cube is a terrible mistake by ST. I would stay away from it, at least until it matures to a point of being usable.

author: fomu
author_rank: Newbie
timestamp: March 25, 2015, 12:39:19 am
content: dannyF, Andreasf and Hacked,First of all. Thanks a lot for your quick answer! I'll try the things you say and tell you how they worked. Though I´m a bit concerned. So, do you recommend me to stay away from the HAL libraries for now? They do seem troublesome to be honest. The worst part is the lack of help as they´re new and not being well received. But i liked the fact that the STMCube MX app creates all the project structure for you and that you can modify it with its pretty visual interface. Too bad it doesn´t work with the "Standard library" or does it? ST Microelectronics should create tutorials that teach you how to use it at least!

author: fomu
author_rank: Newbie
timestamp: March 25, 2015, 12:53:41 am
content: Hacked,I think STM32cube MX doesn´t have any examples but, STM32cube F4 does. The bad news is that for the TIM module, it only has PWMIn and Timebase examples.The code I posted does NOT compile.The following error messages appear:Code:Building configuration: PWMTest05 - PWMTest05 ConfigurationUpdating build tree...LinkingError: no definition for "HAL_TIM_PWM_MspInit" [referenced from C:\Users\Mauricio\Desktop\ARM\Tutorials\PWMTest05\EWARM\PWMTest05Configuration\Obj\main.o]Error: no definition for "HAL_TIM_PWM_Init" [referenced from C:\Users\Mauricio\Desktop\ARM\Tutorials\PWMTest05\EWARM\PWMTest05Configuration\Obj\main.o]Error: no definition for "HAL_TIM_PWM_ConfigChannel" [referenced from C:\Users\Mauricio\Desktop\ARM\Tutorials\PWMTest05\EWARM\PWMTest05 Configuration\Obj\main.o]Error: no definition for "HAL_TIM_PWM_Start" [referenced from C:\Users\Mauricio\Desktop\ARM\Tutorials\PWMTest05\EWARM\PWMTest05Configuration\Obj\main.o]Error while running LinkerTotal number of errors: 4Total number of warnings: 0

author: fomu
author_rank: Newbie
timestamp: March 25, 2015, 12:59:40 am
content: AndreasF,I see what you´re telling me. I´ll change it and tell you if it worked. Thanks!

author: fomu
author_rank: Newbie
timestamp: March 25, 2015, 01:07:52 am
content: dannyf and AndreasF,The reason i did it is because on the HAL Driver Description document there´s a section called: How to use this driver in the TIM part, this section states the following:1. Initialize the TIM low level resources by implementing the following functionsdepending from feature used :? Time Base : HAL_TIM_Base_MspInit()? Input Capture : HAL_TIM_IC_MspInit()? Output Compare : HAL_TIM_OC_MspInit()? PWM generation : HAL_TIM_PWM_MspInit()? One-pulse mode output : HAL_TIM_OnePulse_MspInit()? Encoder mode output : HAL_TIM_Encoder_MspInit()2. Initialize the TIM low level resources :a. Enable the TIM interface clock using __TIMx_CLK_ENABLE();b. TIM pins configuration? Enable the clock for the TIM GPIOs using the following function:__GPIOx_CLK_ENABLE();? Configure these TIM pins in Alternate function mode usingHAL_GPIO_Init();3. The external Clock can be configured, if needed (the default clock is the internal clockfrom the APBx), using the following function: HAL_TIM_ConfigClockSource, the clockconfiguration should be done before any start function.4. Configure the TIM in the desired functioning mode using one of the initializationfunction of this driver:? HAL_TIM_Base_Init: to use the Timer to generate a simple time base? HAL_TIM_OC_Init and HAL_TIM_OC_ConfigChannel: to use the Timer togenerate an Output Compare signal.? HAL_TIM_PWM_Init and HAL_TIM_PWM_ConfigChannel: to use the Timer togenerate a PWM signal.? HAL_TIM_IC_Init and HAL_TIM_IC_ConfigChannel: to use the Timer tomeasure an external signal.? HAL_TIM_OnePulse_Init and HAL_TIM_OnePulse_ConfigChannel: to use theTimer in One Pulse Mode.? HAL_TIM_Encoder_Init: to use the Timer Encoder Interface.5. Activate the TIM peripheral using one of the start functions depending from thefeature used:? Time Base : HAL_TIM_Base_Start(), HAL_TIM_Base_Start_DMA(),HAL_TIM_Base_Start_IT()? Input Capture : HAL_TIM_IC_Start(), HAL_TIM_IC_Start_DMA(),HAL_TIM_IC_Start_IT()? Output Compare : HAL_TIM_OC_Start(), HAL_TIM_OC_Start_DMA(),HAL_TIM_OC_Start_IT()? PWM generation : HAL_TIM_PWM_Start(), HAL_TIM_PWM_Start_DMA(),HAL_TIM_PWM_Start_IT()? One-pulse mode output : HAL_TIM_OnePulse_Start(),HAL_TIM_OnePulse_Start_IT()? Encoder mode output : HAL_TIM_Encoder_Start(),HAL_TIM_Encoder_Start_DMA(), HAL_TIM_Encoder_Start_IT().6. The DMA Burst is managed with the two following functions:HAL_TIM_DMABurst_WriteStart() HAL_TIM_DMABurst_ReadStart()Which is the reason why I configured the GPIO registers, because it says so in the manual UM1725 page 728. But I´ll try so find a shorter version. Either that or go to the standard library.

author: AndreasF
author_rank: Frequent Contributor
timestamp: March 25, 2015, 07:58:15 am
content: I'm not saying don't initialize the GPIO - you DO need to do that. What I was trying to say earlier was that you should either set the register directly (and properly - the way you do that doesn't work), or do it indirectly via the HAL library function call. However, what the compile errors are telling you is that it's missing some of the files needed to make use of the HAL TIM functions. I don't use IAR, so I don't know how to solve that issue.

author: dannyf
author_rank: Super Contributor
timestamp: March 25, 2015, 11:16:22 am
content: 1. Make sure that you can compile an existing cube project for your chip;2) make sure that you can set up and compile a cube project for your chip.Once you got those two resolved, you have eliminated potential issues with your tool chain - your issue right now is your inability to use the tool chain.

author: fomu
author_rank: Newbie
timestamp: March 26, 2015, 02:00:53 am
content: dannyf,Previously, I´ve compiled and linked projects, mostly tutorials with timers and GPIO, so the toolchain does work. The thing that bothers me is the missing files. If I press go to definition on the editor, IAR redirects me to the source file which is in my project. So things are weird. According to clive1 this issue happens when you call a dynamic function from a static setting, thouh I´m not sure if that applies here.Anyways... I think I might need to get into the std periph library! Because of the lack of tutorials.

author: severspa2004
author_rank: Newbie
timestamp: April 13, 2016, 07:13:12 am
content: You have to start your PWM channel in main{}. Use HAL_TIM_PWM_Start. HAL initialization doesn't start the PWM.