X-CUBE-SPN1-20150128 example source code for one motor compiled under mbed. Tested OK on Nucleo F401. l6474.cpp is modified from original with defines in l6474_target_config.h to select the original behaviour (motor de-energised when halted), or new mode to continue powering with a (reduced) current in the coils (braking/position hold capability). On F401 avoid using mbed's InterruptIn on pins 10-15 (any port). Beware of other conflicts! L0 & F0 are included but untested.
stm32l0xx_nucleo_ihm01a1.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l0xx_nucleo_ihm01a1.c 00004 * @author IPC Rennes 00005 * @version V1.5.0 00006 * @date November 12, 2014 00007 * @brief BSP driver for x-nucleo-ihm01a1 Nucleo extension board 00008 * (based on L6474) 00009 ****************************************************************************** 00010 * @attention 00011 * 00012 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2> 00013 * 00014 * Redistribution and use in source and binary forms, with or without modification, 00015 * are permitted provided that the following conditions are met: 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 2. Redistributions in binary form must reproduce the above copyright notice, 00019 * this list of conditions and the following disclaimer in the documentation 00020 * and/or other materials provided with the distribution. 00021 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00022 * may be used to endorse or promote products derived from this software 00023 * without specific prior written permission. 00024 * 00025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00026 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00028 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00029 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00030 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00031 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00032 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00033 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00034 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00035 * 00036 ****************************************************************************** 00037 */ 00038 #ifdef TARGET_STM32L0 00039 /* Includes ------------------------------------------------------------------*/ 00040 #include "mbed.h" 00041 #include "stm32l0xx_nucleo_ihm01a1.h" 00042 00043 /** @addtogroup BSP 00044 * @{ 00045 */ 00046 00047 /** @defgroup STM32L0XX_NUCLEO_IHM01A1 00048 * @{ 00049 */ 00050 00051 /* Private constants ---------------------------------------------------------*/ 00052 00053 /** @defgroup IHM01A1_Private_Constants 00054 * @{ 00055 */ 00056 00057 /// Timer Prescaler 00058 #define TIMER_PRESCALER (1024) 00059 00060 /// SPI Maximum Timeout values for flags waiting loops 00061 #define SPIx_TIMEOUT_MAX ((uint32_t)0x1000) 00062 00063 /** 00064 * @} 00065 */ 00066 00067 /* Private variables ---------------------------------------------------------*/ 00068 00069 /** @defgroup IHM01A1_Board_Private_Variables 00070 * @{ 00071 */ 00072 /// SPI handler declaration 00073 static SPI_HandleTypeDef SpiHandle; 00074 /// Timer handler for PWM1 00075 TIM_HandleTypeDef hTimPwm1; 00076 /// imer handler for PWM2 00077 TIM_HandleTypeDef hTimPwm2; 00078 /// Timer handler for PWM3 00079 TIM_HandleTypeDef hTimPwm3; 00080 /** 00081 * @} 00082 */ 00083 00084 /** 00085 * @} 00086 */ 00087 00088 00089 /** @defgroup IHM01A1_Board_Private_Functions 00090 * @{ 00091 */ 00092 00093 /******************************************************//** 00094 * @brief This function provides an accurate delay in milliseconds 00095 * @param[in] delay time length in milliseconds 00096 * @retval None 00097 **********************************************************/ 00098 void BSP_MotorControlBoard_Delay(uint32_t delay) 00099 { 00100 HAL_Delay(delay); 00101 } 00102 00103 /******************************************************//** 00104 * @brief This function disable the interruptions 00105 * @param None 00106 * @retval None 00107 **********************************************************/ 00108 void BSP_MotorControlBoard_DisableIrq(void) 00109 { 00110 __disable_irq(); 00111 } 00112 00113 /******************************************************//** 00114 * @brief This function enable the interruptions 00115 * @param None 00116 * @retval None 00117 **********************************************************/ 00118 void BSP_MotorControlBoard_EnableIrq(void) 00119 { 00120 __enable_irq(); 00121 } 00122 00123 /******************************************************//** 00124 * @brief Initiliases the GPIOs used by the L6474s 00125 * @param[in] nbDevices number of L6474 devices 00126 * @retval None 00127 **********************************************************/ 00128 void BSP_MotorControlBoard_GpioInit(uint8_t nbDevices) 00129 { 00130 GPIO_InitTypeDef GPIO_InitStruct; 00131 00132 /* GPIO Ports Clock Enable */ 00133 __GPIOC_CLK_ENABLE(); 00134 __GPIOA_CLK_ENABLE(); 00135 __GPIOB_CLK_ENABLE(); 00136 00137 /* Configure L6474 - DIR pin for device 1 -------------------------------*/ 00138 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_DIR_1_PIN; 00139 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00140 GPIO_InitStruct.Pull = GPIO_NOPULL; 00141 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00142 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_DIR_1_PORT, &GPIO_InitStruct); 00143 00144 /* Configure L6474 - Flag pin -------------------------------------------*/ 00145 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_FLAG_PIN; 00146 GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; 00147 GPIO_InitStruct.Pull = GPIO_PULLUP; 00148 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00149 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_FLAG_PORT, &GPIO_InitStruct); 00150 00151 /* Set Priority of External Line Interrupt used for the Flag interrupt*/ 00152 HAL_NVIC_SetPriority(EXTI_MCU_LINE_IRQn, 5, 0); 00153 00154 /* Enable the External Line Interrupt used for the Flag interrupt*/ 00155 HAL_NVIC_EnableIRQ(EXTI_MCU_LINE_IRQn); 00156 00157 /* Configure L6474 - CS pin ---------------------------------------------*/ 00158 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_CS_PIN; 00159 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00160 GPIO_InitStruct.Pull = GPIO_NOPULL; 00161 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00162 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_CS_PORT, &GPIO_InitStruct); 00163 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_CS_PORT, BSP_MOTOR_CONTROL_BOARD_CS_PIN, GPIO_PIN_SET); 00164 00165 /* Configure L6474 - STBY/RESET pin -------------------------------------*/ 00166 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_RESET_PIN; 00167 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00168 GPIO_InitStruct.Pull = GPIO_NOPULL; 00169 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00170 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_RESET_PORT, &GPIO_InitStruct); 00171 BSP_MotorControlBoard_Reset(); 00172 00173 if (nbDevices > 1) 00174 { 00175 /* Configure L6474 - DIR pin for device 2 ----------------------------*/ 00176 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_DIR_2_PIN; 00177 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00178 GPIO_InitStruct.Pull = GPIO_NOPULL; 00179 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00180 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_DIR_2_PORT, &GPIO_InitStruct); 00181 } 00182 if (nbDevices > 2) 00183 { 00184 /* Configure L6474 - DIR pin for device 3 ----------------------------*/ 00185 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_DIR_3_PIN; 00186 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00187 GPIO_InitStruct.Pull = GPIO_NOPULL; 00188 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00189 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_DIR_3_PORT, &GPIO_InitStruct); 00190 } 00191 } 00192 00193 /******************************************************//** 00194 * @brief Sets the frequency of PWM1 used by device 0 00195 * @param[in] newFreq in Hz 00196 * @retval None 00197 * @note The frequency is directly the current speed of the device 00198 **********************************************************/ 00199 void BSP_MotorControlBoard_Pwm1SetFreq(uint16_t newFreq) 00200 { 00201 uint32_t sysFreq = HAL_RCC_GetSysClockFreq(); 00202 uint32_t period = (sysFreq/ (TIMER_PRESCALER * BSP_MOTOR_CONTROL_BOARD_PWM1_FREQ_RESCALER * (uint32_t)newFreq)) - 1; 00203 00204 __HAL_TIM_SetAutoreload(&hTimPwm1, period); 00205 __HAL_TIM_SetCompare(&hTimPwm1, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM1, period >> 1); 00206 HAL_TIM_PWM_Start_IT(&hTimPwm1, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM1); 00207 } 00208 00209 /******************************************************//** 00210 * @brief Sets the frequency of PWM2 used by device 1 00211 * @param[in] newFreq in Hz 00212 * @retval None 00213 * @note The frequency is directly the current speed of the device 00214 **********************************************************/ 00215 void BSP_MotorControlBoard_Pwm2SetFreq(uint16_t newFreq) 00216 { 00217 uint32_t sysFreq = HAL_RCC_GetSysClockFreq(); 00218 uint32_t period = (sysFreq/ (TIMER_PRESCALER * BSP_MOTOR_CONTROL_BOARD_PWM2_FREQ_RESCALER * (uint32_t)newFreq)) - 1; 00219 00220 __HAL_TIM_SetAutoreload(&hTimPwm2, period); 00221 __HAL_TIM_SetCompare(&hTimPwm2, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM2, period >> 1); 00222 HAL_TIM_PWM_Start_IT(&hTimPwm2, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM2); 00223 } 00224 /******************************************************//** 00225 * @brief Sets the frequency of PWM3 used by device 2 00226 * @param[in] newFreq in Hz 00227 * @retval None 00228 * @note The frequency is directly the current speed of the device 00229 **********************************************************/ 00230 void BSP_MotorControlBoard_Pwm3SetFreq(uint16_t newFreq) 00231 { 00232 uint32_t sysFreq = HAL_RCC_GetSysClockFreq(); 00233 /* Double the frequency as the SW is generated by SW */ 00234 uint32_t period = (sysFreq/ (TIMER_PRESCALER * BSP_MOTOR_CONTROL_BOARD_PWM3_FREQ_RESCALER * (uint32_t)newFreq)) - 1; 00235 00236 __HAL_TIM_SetAutoreload(&hTimPwm3, period); 00237 __HAL_TIM_SetCompare(&hTimPwm3, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM3, period >> 1); 00238 HAL_TIM_PWM_Start_IT(&hTimPwm3, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM3); 00239 } 00240 00241 /******************************************************//** 00242 * @brief Initialises the PWM uses by the specified device 00243 * @param[in] deviceId (from 0 to 2) 00244 * @retval None 00245 * @note Device 0 uses PWM1 based on timer 1 00246 * Device 1 uses PWM 2 based on timer 2 00247 * Device 2 uses PWM3 based timer 0 00248 **********************************************************/ 00249 void BSP_MotorControlBoard_PwmInit(uint8_t deviceId) 00250 { 00251 TIM_OC_InitTypeDef sConfigOC; 00252 TIM_MasterConfigTypeDef sMasterConfig; 00253 TIM_HandleTypeDef *pHTim; 00254 uint32_t channel; 00255 00256 switch (deviceId) 00257 { 00258 00259 case 0: 00260 default: 00261 pHTim = &hTimPwm1; 00262 pHTim->Instance = BSP_MOTOR_CONTROL_BOARD_TIMER_PWM1; 00263 channel = BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM1; 00264 00265 break; 00266 case 1: 00267 pHTim = &hTimPwm2; 00268 pHTim->Instance = BSP_MOTOR_CONTROL_BOARD_TIMER_PWM2; 00269 channel = BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM2; 00270 break; 00271 00272 00273 case 2: 00274 pHTim = &hTimPwm3; 00275 pHTim->Instance = BSP_MOTOR_CONTROL_BOARD_TIMER_PWM3; 00276 channel = BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM3; 00277 break; 00278 } 00279 pHTim->Init.Prescaler = TIMER_PRESCALER -1; 00280 pHTim->Init.CounterMode = TIM_COUNTERMODE_UP; 00281 pHTim->Init.Period = 0; 00282 pHTim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 00283 HAL_TIM_PWM_Init(pHTim); 00284 00285 sConfigOC.OCMode = TIM_OCMODE_PWM1; 00286 sConfigOC.Pulse = 0; 00287 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; 00288 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; 00289 HAL_TIM_PWM_ConfigChannel(pHTim, &sConfigOC, channel); 00290 00291 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; 00292 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; 00293 HAL_TIMEx_MasterConfigSynchronization(pHTim, &sMasterConfig); 00294 } 00295 00296 /******************************************************//** 00297 * @brief Stops the PWM uses by the specified device 00298 * @param[in] deviceId (from 0 to 2) 00299 * @retval None 00300 **********************************************************/ 00301 void BSP_MotorControlBoard_PwmStop(uint8_t deviceId) 00302 { 00303 switch (deviceId) 00304 { 00305 case 0: 00306 HAL_TIM_PWM_Stop(&hTimPwm1,BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM1); 00307 00308 break; 00309 case 1: 00310 HAL_TIM_PWM_Stop(&hTimPwm2,BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM2); 00311 00312 break; 00313 case 2: 00314 HAL_TIM_PWM_Stop(&hTimPwm3,BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM3); 00315 00316 break; 00317 default: 00318 break;//ignore error 00319 } 00320 } 00321 00322 /******************************************************//** 00323 * @brief Releases the L6474 reset (pin set to High) of all devices 00324 * @param None 00325 * @retval None 00326 **********************************************************/ 00327 void BSP_MotorControlBoard_ReleaseReset(void) 00328 { 00329 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_RESET_PORT, BSP_MOTOR_CONTROL_BOARD_RESET_PIN, GPIO_PIN_SET); 00330 } 00331 00332 /******************************************************//** 00333 * @brief Resets the L6474 (reset pin set to low) of all devices 00334 * @param None 00335 * @retval None 00336 **********************************************************/ 00337 void BSP_MotorControlBoard_Reset(void) 00338 { 00339 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_RESET_PORT, BSP_MOTOR_CONTROL_BOARD_RESET_PIN, GPIO_PIN_RESET); 00340 } 00341 00342 /******************************************************//** 00343 * @brief Set the GPIO used for the direction 00344 * @param[in] deviceId (from 0 to 2) 00345 * @param[in] gpioState state of the direction gpio (0 to reset, 1 to set) 00346 * @retval None 00347 **********************************************************/ 00348 void BSP_MotorControlBoard_SetDirectionGpio(uint8_t deviceId, uint8_t gpioState) 00349 { 00350 switch (deviceId) 00351 { 00352 case 2: 00353 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_DIR_3_PORT, BSP_MOTOR_CONTROL_BOARD_DIR_3_PIN, (GPIO_PinState)gpioState); 00354 break; 00355 case 1: 00356 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_DIR_2_PORT, BSP_MOTOR_CONTROL_BOARD_DIR_2_PIN, (GPIO_PinState)gpioState); 00357 break; 00358 case 0: 00359 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_DIR_1_PORT, BSP_MOTOR_CONTROL_BOARD_DIR_1_PIN, (GPIO_PinState)gpioState); 00360 break; 00361 default: 00362 ; 00363 } 00364 } 00365 00366 /******************************************************//** 00367 * @brief Initialise the SPI used by L6474 00368 * @param None 00369 * @retval HAL_OK if SPI transaction is OK, HAL_KO else 00370 **********************************************************/ 00371 uint8_t BSP_MotorControlBoard_SpiInit(void) 00372 { 00373 HAL_StatusTypeDef status; 00374 00375 /* Initialises the SPI --------------------------------------------------*/ 00376 SpiHandle.Instance = SPIx; 00377 SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; 00378 SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; 00379 SpiHandle.Init.CLKPhase = SPI_PHASE_2EDGE; 00380 SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH; 00381 SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; 00382 SpiHandle.Init.CRCPolynomial = 7; 00383 SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; 00384 SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; 00385 SpiHandle.Init.NSS = SPI_NSS_SOFT; 00386 SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED; 00387 00388 SpiHandle.Init.Mode = SPI_MODE_MASTER; 00389 00390 status = HAL_SPI_Init(&SpiHandle); 00391 00392 return (uint8_t) status; 00393 } 00394 /******************************************************//** 00395 * @brief Write and read SPI byte to the L6474 00396 * @param[in] pByteToTransmit pointer to the byte to transmit 00397 * @param[in] pReceivedByte pointer to the received byte 00398 * @param[in] nbDevices Number of device in the SPI chain 00399 * @retval HAL_OK if SPI transaction is OK, HAL_KO else 00400 **********************************************************/ 00401 uint8_t BSP_MotorControlBoard_SpiWriteBytes(uint8_t *pByteToTransmit, uint8_t *pReceivedByte, uint8_t nbDevices) 00402 { 00403 HAL_StatusTypeDef status; 00404 uint32_t i; 00405 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_CS_PORT, BSP_MOTOR_CONTROL_BOARD_CS_PIN, GPIO_PIN_RESET); 00406 for (i = 0; i < nbDevices; i++) 00407 { 00408 status = HAL_SPI_TransmitReceive(&SpiHandle, pByteToTransmit, pReceivedByte, 1, SPIx_TIMEOUT_MAX); 00409 if (status != HAL_OK) 00410 { 00411 break; 00412 } 00413 pByteToTransmit++; 00414 pReceivedByte++; 00415 } 00416 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_CS_PORT, BSP_MOTOR_CONTROL_BOARD_CS_PIN, GPIO_PIN_SET); 00417 00418 return (uint8_t) status; 00419 } 00420 00421 /** 00422 * @} 00423 */ 00424 00425 /** 00426 * @} 00427 */ 00428 00429 /** 00430 * @} 00431 */ 00432 #endif 00433 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 22:53:31 by 1.7.2