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.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l0xx_nucleo_ihm01a1.cpp Source File

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>&copy; 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****/