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.
stm32f0xx_nucleo_ihm01a1.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f0xx_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_STM32F0 00039 /* Includes ------------------------------------------------------------------*/ 00040 #include "mbed.h" 00041 #include "stm32f0xx_nucleo_ihm01a1.h" 00042 00043 /** @addtogroup BSP 00044 * @{ 00045 */ 00046 00047 /** @defgroup STM32F0XX_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 00090 /** @defgroup IHM01A1_Board_Private_Functions 00091 * @{ 00092 */ 00093 00094 /******************************************************//** 00095 * @brief This function provides an accurate delay in milliseconds 00096 * @param[in] delay time length in milliseconds 00097 * @retval None 00098 **********************************************************/ 00099 void BSP_MotorControlBoard_Delay(uint32_t delay) 00100 { 00101 HAL_Delay(delay); 00102 } 00103 00104 /******************************************************//** 00105 * @brief This function disable the interruptions 00106 * @param None 00107 * @retval None 00108 **********************************************************/ 00109 void BSP_MotorControlBoard_DisableIrq(void) 00110 { 00111 __disable_irq(); 00112 } 00113 00114 /******************************************************//** 00115 * @brief This function enable the interruptions 00116 * @param None 00117 * @retval None 00118 **********************************************************/ 00119 void BSP_MotorControlBoard_EnableIrq(void) 00120 { 00121 __enable_irq(); 00122 } 00123 00124 /******************************************************//** 00125 * @brief Initiliases the GPIOs used by the L6474s 00126 * @param[in] nbDevices number of L6474 devices 00127 * @retval None 00128 **********************************************************/ 00129 void BSP_MotorControlBoard_GpioInit(uint8_t nbDevices) 00130 { 00131 GPIO_InitTypeDef GPIO_InitStruct; 00132 00133 /* GPIO Ports Clock Enable */ 00134 __GPIOC_CLK_ENABLE(); 00135 __GPIOA_CLK_ENABLE(); 00136 __GPIOB_CLK_ENABLE(); 00137 00138 /* Configure L6474 - DIR pin for device 1 -------------------------------*/ 00139 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_DIR_1_PIN; 00140 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00141 GPIO_InitStruct.Pull = GPIO_NOPULL; 00142 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00143 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_DIR_1_PORT, &GPIO_InitStruct); 00144 00145 /* Configure L6474 - Flag pin -------------------------------------------*/ 00146 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_FLAG_PIN; 00147 GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; 00148 GPIO_InitStruct.Pull = GPIO_PULLUP; 00149 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00150 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_FLAG_PORT, &GPIO_InitStruct); 00151 00152 /* Set Priority of External Line Interrupt used for the Flag interrupt*/ 00153 HAL_NVIC_SetPriority(EXTI_MCU_LINE_IRQn, 5, 0); 00154 00155 /* Enable the External Line Interrupt used for the Flag interrupt*/ 00156 HAL_NVIC_EnableIRQ(EXTI_MCU_LINE_IRQn); 00157 00158 /* Configure L6474 - CS pin ---------------------------------------------*/ 00159 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_CS_PIN; 00160 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00161 GPIO_InitStruct.Pull = GPIO_NOPULL; 00162 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00163 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_CS_PORT, &GPIO_InitStruct); 00164 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_CS_PORT, BSP_MOTOR_CONTROL_BOARD_CS_PIN, GPIO_PIN_SET); 00165 00166 /* Configure L6474 - STBY/RESET pin -------------------------------------*/ 00167 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_RESET_PIN; 00168 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00169 GPIO_InitStruct.Pull = GPIO_NOPULL; 00170 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00171 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_RESET_PORT, &GPIO_InitStruct); 00172 BSP_MotorControlBoard_Reset(); 00173 00174 if (nbDevices > 1) 00175 { 00176 /* Configure L6474 - DIR pin for device 2 ----------------------------*/ 00177 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_DIR_2_PIN; 00178 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00179 GPIO_InitStruct.Pull = GPIO_NOPULL; 00180 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00181 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_DIR_2_PORT, &GPIO_InitStruct); 00182 } 00183 if (nbDevices > 2) 00184 { 00185 /* Configure L6474 - DIR pin for device 3 ----------------------------*/ 00186 GPIO_InitStruct.Pin = BSP_MOTOR_CONTROL_BOARD_DIR_3_PIN; 00187 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 00188 GPIO_InitStruct.Pull = GPIO_NOPULL; 00189 GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; 00190 HAL_GPIO_Init(BSP_MOTOR_CONTROL_BOARD_DIR_3_PORT, &GPIO_InitStruct); 00191 } 00192 } 00193 00194 /******************************************************//** 00195 * @brief Sets the frequency of PWM1 used by device 0 00196 * @param[in] newFreq in Hz 00197 * @retval None 00198 * @note The frequency is directly the current speed of the device 00199 **********************************************************/ 00200 void BSP_MotorControlBoard_Pwm1SetFreq(uint16_t newFreq) 00201 { 00202 uint32_t sysFreq = HAL_RCC_GetSysClockFreq(); 00203 uint32_t period = (sysFreq/ (TIMER_PRESCALER * BSP_MOTOR_CONTROL_BOARD_PWM1_FREQ_RESCALER * (uint32_t)newFreq)) - 1; 00204 00205 __HAL_TIM_SetAutoreload(&hTimPwm1, period); 00206 __HAL_TIM_SetCompare(&hTimPwm1, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM1, period >> 1); 00207 HAL_TIM_PWM_Start_IT(&hTimPwm1, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM1); 00208 } 00209 00210 /******************************************************//** 00211 * @brief Sets the frequency of PWM2 used by device 1 00212 * @param[in] newFreq in Hz 00213 * @retval None 00214 * @note The frequency is directly the current speed of the device 00215 **********************************************************/ 00216 void BSP_MotorControlBoard_Pwm2SetFreq(uint16_t newFreq) 00217 { 00218 uint32_t sysFreq = HAL_RCC_GetSysClockFreq(); 00219 uint32_t period = (sysFreq/ (TIMER_PRESCALER * BSP_MOTOR_CONTROL_BOARD_PWM2_FREQ_RESCALER * (uint32_t)newFreq)) - 1; 00220 00221 __HAL_TIM_SetAutoreload(&hTimPwm2, period); 00222 __HAL_TIM_SetCompare(&hTimPwm2, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM2, period >> 1); 00223 HAL_TIM_PWM_Start_IT(&hTimPwm2, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM2); 00224 } 00225 /******************************************************//** 00226 * @brief Sets the frequency of PWM3 used by device 2 00227 * @param[in] newFreq in Hz 00228 * @retval None 00229 * @note The frequency is directly the current speed of the device 00230 **********************************************************/ 00231 void BSP_MotorControlBoard_Pwm3SetFreq(uint16_t newFreq) 00232 { 00233 uint32_t sysFreq = HAL_RCC_GetSysClockFreq(); 00234 /* Double the frequency as the SW is generated by SW */ 00235 uint32_t period = (sysFreq/ (TIMER_PRESCALER * BSP_MOTOR_CONTROL_BOARD_PWM3_FREQ_RESCALER * (uint32_t)newFreq)) - 1; 00236 00237 __HAL_TIM_SetAutoreload(&hTimPwm3, period); 00238 __HAL_TIM_SetCompare(&hTimPwm3, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM3, period >> 1); 00239 HAL_TIM_PWM_Start_IT(&hTimPwm3, BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM3); 00240 } 00241 00242 /******************************************************//** 00243 * @brief Initialises the PWM uses by the specified device 00244 * @param[in] deviceId (from 0 to 2) 00245 * @retval None 00246 * @note Device 0 uses PWM1 based on timer 1 00247 * Device 1 uses PWM 2 based on timer 2 00248 * Device 2 uses PWM3 based timer 0 00249 **********************************************************/ 00250 void BSP_MotorControlBoard_PwmInit(uint8_t deviceId) 00251 { 00252 TIM_OC_InitTypeDef sConfigOC; 00253 TIM_MasterConfigTypeDef sMasterConfig; 00254 TIM_HandleTypeDef *pHTim; 00255 uint32_t channel; 00256 00257 switch (deviceId) 00258 { 00259 00260 case 0: 00261 default: 00262 pHTim = &hTimPwm1; 00263 pHTim->Instance = BSP_MOTOR_CONTROL_BOARD_TIMER_PWM1; 00264 channel = BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM1; 00265 00266 break; 00267 case 1: 00268 pHTim = &hTimPwm2; 00269 pHTim->Instance = BSP_MOTOR_CONTROL_BOARD_TIMER_PWM2; 00270 channel = BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM2; 00271 break; 00272 00273 00274 case 2: 00275 pHTim = &hTimPwm3; 00276 pHTim->Instance = BSP_MOTOR_CONTROL_BOARD_TIMER_PWM3; 00277 channel = BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM3; 00278 break; 00279 } 00280 pHTim->Init.Prescaler = TIMER_PRESCALER -1; 00281 pHTim->Init.CounterMode = TIM_COUNTERMODE_UP; 00282 pHTim->Init.Period = 0; 00283 pHTim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 00284 HAL_TIM_PWM_Init(pHTim); 00285 00286 sConfigOC.OCMode = TIM_OCMODE_PWM1; 00287 sConfigOC.Pulse = 0; 00288 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; 00289 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; 00290 HAL_TIM_PWM_ConfigChannel(pHTim, &sConfigOC, channel); 00291 00292 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; 00293 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; 00294 HAL_TIMEx_MasterConfigSynchronization(pHTim, &sMasterConfig); 00295 } 00296 00297 /******************************************************//** 00298 * @brief Stops the PWM uses by the specified device 00299 * @param[in] deviceId (from 0 to 2) 00300 * @retval None 00301 **********************************************************/ 00302 void BSP_MotorControlBoard_PwmStop(uint8_t deviceId) 00303 { 00304 switch (deviceId) 00305 { 00306 case 0: 00307 HAL_TIM_PWM_Stop(&hTimPwm1,BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM1); 00308 00309 break; 00310 case 1: 00311 HAL_TIM_PWM_Stop(&hTimPwm2,BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM2); 00312 00313 break; 00314 case 2: 00315 HAL_TIM_PWM_Stop(&hTimPwm3,BSP_MOTOR_CONTROL_BOARD_CHAN_TIMER_PWM3); 00316 00317 break; 00318 default: 00319 break;//ignore error 00320 } 00321 } 00322 00323 /******************************************************//** 00324 * @brief Releases the L6474 reset (pin set to High) of all devices 00325 * @param None 00326 * @retval None 00327 **********************************************************/ 00328 void BSP_MotorControlBoard_ReleaseReset(void) 00329 { 00330 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_RESET_PORT, BSP_MOTOR_CONTROL_BOARD_RESET_PIN, GPIO_PIN_SET); 00331 } 00332 00333 /******************************************************//** 00334 * @brief Resets the L6474 (reset pin set to low) of all devices 00335 * @param None 00336 * @retval None 00337 **********************************************************/ 00338 void BSP_MotorControlBoard_Reset(void) 00339 { 00340 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_RESET_PORT, BSP_MOTOR_CONTROL_BOARD_RESET_PIN, GPIO_PIN_RESET); 00341 } 00342 00343 /******************************************************//** 00344 * @brief Set the GPIO used for the direction 00345 * @param[in] deviceId (from 0 to 2) 00346 * @param[in] gpioState state of the direction gpio (0 to reset, 1 to set) 00347 * @retval None 00348 **********************************************************/ 00349 void BSP_MotorControlBoard_SetDirectionGpio(uint8_t deviceId, uint8_t gpioState) 00350 { 00351 switch (deviceId) 00352 { 00353 case 2: 00354 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_DIR_3_PORT, BSP_MOTOR_CONTROL_BOARD_DIR_3_PIN, (GPIO_PinState)gpioState); 00355 break; 00356 case 1: 00357 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_DIR_2_PORT, BSP_MOTOR_CONTROL_BOARD_DIR_2_PIN, (GPIO_PinState)gpioState); 00358 break; 00359 case 0: 00360 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_DIR_1_PORT, BSP_MOTOR_CONTROL_BOARD_DIR_1_PIN, (GPIO_PinState)gpioState); 00361 break; 00362 default: 00363 ; 00364 } 00365 } 00366 00367 /******************************************************//** 00368 * @brief Initialise the SPI used by L6474 00369 * @param None 00370 * @retval HAL_OK if SPI transaction is OK, HAL_KO else 00371 **********************************************************/ 00372 uint8_t BSP_MotorControlBoard_SpiInit(void) 00373 { 00374 HAL_StatusTypeDef status; 00375 00376 /* Initialises the SPI --------------------------------------------------*/ 00377 SpiHandle.Instance = SPIx; 00378 SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; 00379 SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; 00380 SpiHandle.Init.CLKPhase = SPI_PHASE_2EDGE; 00381 SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH; 00382 SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; 00383 SpiHandle.Init.CRCPolynomial = 7; 00384 SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; 00385 SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; 00386 SpiHandle.Init.NSS = SPI_NSS_SOFT; 00387 SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED; 00388 00389 SpiHandle.Init.Mode = SPI_MODE_MASTER; 00390 00391 status = HAL_SPI_Init(&SpiHandle); 00392 00393 return (uint8_t) status; 00394 } 00395 /******************************************************//** 00396 * @brief Write and read SPI byte to the L6474 00397 * @param[in] pByteToTransmit pointer to the byte to transmit 00398 * @param[in] pReceivedByte pointer to the received byte 00399 * @param[in] nbDevices Number of device in the SPI chain 00400 * @retval HAL_OK if SPI transaction is OK, HAL_KO else 00401 **********************************************************/ 00402 uint8_t BSP_MotorControlBoard_SpiWriteBytes(uint8_t *pByteToTransmit, uint8_t *pReceivedByte, uint8_t nbDevices) 00403 { 00404 HAL_StatusTypeDef status; 00405 uint32_t i; 00406 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_CS_PORT, BSP_MOTOR_CONTROL_BOARD_CS_PIN, GPIO_PIN_RESET); 00407 for (i = 0; i < nbDevices; i++) 00408 { 00409 status = HAL_SPI_TransmitReceive(&SpiHandle, pByteToTransmit, pReceivedByte, 1, SPIx_TIMEOUT_MAX); 00410 if (status != HAL_OK) 00411 { 00412 break; 00413 } 00414 pByteToTransmit++; 00415 pReceivedByte++; 00416 } 00417 HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_CS_PORT, BSP_MOTOR_CONTROL_BOARD_CS_PIN, GPIO_PIN_SET); 00418 00419 return (uint8_t) status; 00420 } 00421 00422 /** 00423 * @} 00424 */ 00425 00426 /** 00427 * @} 00428 */ 00429 00430 /** 00431 * @} 00432 */ 00433 #endif 00434 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 22:53:31 by 1.7.2