Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of X_NUCLEO_IHM01A1 by
l6474_class.cpp
00001 /** 00002 ****************************************************************************** 00003 * @file l6474_class.cpp 00004 * @author IPC Rennes 00005 * @version V1.5.0 00006 * @date November 12, 2014 00007 * @brief L6474 driver (fully integrated microstepping motor driver) 00008 * @note (C) COPYRIGHT 2014 STMicroelectronics 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 00039 00040 /* Generated with STM32CubeTOO -----------------------------------------------*/ 00041 00042 00043 /* Revision ------------------------------------------------------------------*/ 00044 /* 00045 Repository: http://svn.x-nucleodev.codex.cro.st.com/svnroot/X-NucleoDev 00046 Branch/Trunk/Tag: trunk 00047 Based on: X-CUBE-SPN1/trunk/Drivers/BSP/Components/l6474/l6474.c 00048 Revision: 0 00049 */ 00050 00051 00052 /* Includes ------------------------------------------------------------------*/ 00053 00054 #include "l6474_class.h" 00055 00056 00057 /* Definitions ---------------------------------------------------------------*/ 00058 00059 /* Error while initialising the SPI. */ 00060 #define L6474_ERROR_0 (0x8000) 00061 00062 /* Error of bad SPI transaction. */ 00063 #define L6474_ERROR_1 (0x8001) 00064 00065 /* Maximum number of steps. */ 00066 #define MAX_STEPS (0x7FFFFFFF) 00067 00068 /* Maximum frequency of the PWMs in Hz. */ 00069 #define L6474_MAX_PWM_FREQ (10000) 00070 00071 /* Minimum frequency of the PWMs in Hz. */ 00072 #define L6474_MIN_PWM_FREQ (2) 00073 00074 00075 /* Variables ----------------------------------------------------------------*/ 00076 00077 /* Number of devices. */ 00078 uint8_t L6474::number_of_devices = 0; 00079 00080 /* ISR flags used to restart an interrupted SPI transfer when an error is reported. */ 00081 bool L6474::spi_preemtion_by_isr = FALSE; 00082 bool L6474::isr_flag = FALSE; 00083 00084 /* SPI Transmission for Daisy-Chain Configuration. */ 00085 uint8_t L6474::spi_tx_bursts[L6474_CMD_ARG_MAX_NB_BYTES][MAX_NUMBER_OF_DEVICES]; 00086 uint8_t L6474::spi_rx_bursts[L6474_CMD_ARG_MAX_NB_BYTES][MAX_NUMBER_OF_DEVICES]; 00087 00088 00089 /* Methods -------------------------------------------------------------------*/ 00090 00091 /********************************************************** 00092 * @brief Attaches a user callback to the error Handler. 00093 * The call back will be then called each time the library 00094 * detects an error 00095 * @param[in] callback Name of the callback to attach 00096 * to the error Hanlder 00097 * @retval None 00098 **********************************************************/ 00099 void L6474::L6474_AttachErrorHandler(void (*callback)(uint16_t error)) 00100 { 00101 error_handler_callback = (void (*)(uint16_t error)) callback; 00102 } 00103 00104 /********************************************************** 00105 * @brief Starts the L6474 library 00106 * @param init Initialization structure. 00107 * @retval COMPONENT_OK in case of success. 00108 **********************************************************/ 00109 Status_t L6474::L6474_Init(void *init) 00110 { 00111 /* Initialise the PWMs used for the Step clocks ----------------------------*/ 00112 L6474_PwmInit(); 00113 00114 /* Initialise the L6474s ------------------------------------------------*/ 00115 00116 /* Standby-reset deactivation */ 00117 L6474_ReleaseReset(); 00118 00119 /* Let a delay after reset */ 00120 L6474_Delay(1); 00121 00122 /* Set device parameters to the predefined values from "l6474_target_config.h". */ 00123 L6474_SetDeviceParamsToPredefinedValues(); 00124 00125 if (init == NULL) 00126 /* Set device registers to the predefined values from "l6474_target_config.h". */ 00127 L6474_SetRegisterToPredefinedValues(); 00128 else 00129 /* Set device registers to the passed initialization values. */ 00130 L6474_SetRegisterToInitializationValues((L6474_Init_t *) init); 00131 00132 /* Disable L6474 powerstage */ 00133 L6474_CmdDisable(); 00134 00135 /* Get Status to clear flags after start up */ 00136 L6474_CmdGetStatus(); 00137 00138 return COMPONENT_OK; 00139 } 00140 00141 /********************************************************** 00142 * @brief Read id 00143 * @param id pointer to the identifier to be read. 00144 * @retval COMPONENT_OK in case of success. 00145 **********************************************************/ 00146 Status_t L6474::L6474_ReadID(uint8_t *id) 00147 { 00148 *id = device_instance; 00149 00150 return COMPONENT_OK; 00151 } 00152 00153 /********************************************************** 00154 * @brief Returns the acceleration of the specified device 00155 * @retval Acceleration in pps^2 00156 **********************************************************/ 00157 uint16_t L6474::L6474_GetAcceleration(void) 00158 { 00159 return (device_prm.acceleration); 00160 } 00161 00162 /********************************************************** 00163 * @brief Returns the current speed of the specified device 00164 * @retval Speed in pps 00165 **********************************************************/ 00166 uint16_t L6474::L6474_GetCurrentSpeed(void) 00167 { 00168 return device_prm.speed; 00169 } 00170 00171 /********************************************************** 00172 * @brief Returns the deceleration of the specified device 00173 * @retval Deceleration in pps^2 00174 **********************************************************/ 00175 uint16_t L6474::L6474_GetDeceleration(void) 00176 { 00177 return (device_prm.deceleration); 00178 } 00179 00180 /********************************************************** 00181 * @brief Returns the device state 00182 * @retval State (ACCELERATING, DECELERATING, STEADY or INACTIVE) 00183 **********************************************************/ 00184 motorState_t L6474::L6474_GetDeviceState(void) 00185 { 00186 return device_prm.motionState; 00187 } 00188 00189 /********************************************************** 00190 * @brief Returns the FW version of the library 00191 * @param None 00192 * @retval L6474_FW_VERSION 00193 **********************************************************/ 00194 uint8_t L6474::L6474_GetFwVersion(void) 00195 { 00196 return (L6474_FW_VERSION); 00197 } 00198 00199 /********************************************************** 00200 * @brief Returns the mark position of the specified device 00201 * @retval Mark register value converted in a 32b signed integer 00202 **********************************************************/ 00203 int32_t L6474::L6474_GetMark(void) 00204 { 00205 return L6474_ConvertPosition(L6474_CmdGetParam(L6474_MARK)); 00206 } 00207 00208 /********************************************************** 00209 * @brief Returns the max speed of the specified device 00210 * @retval maxSpeed in pps 00211 **********************************************************/ 00212 uint16_t L6474::L6474_GetMaxSpeed(void) 00213 { 00214 return (device_prm.maxSpeed); 00215 } 00216 00217 /********************************************************** 00218 * @brief Returns the min speed of the specified device 00219 * @retval minSpeed in pps 00220 **********************************************************/ 00221 uint16_t L6474::L6474_GetMinSpeed(void) 00222 { 00223 return (device_prm.minSpeed); 00224 } 00225 00226 /********************************************************** 00227 * @brief Returns the ABS_POSITION of the specified device 00228 * @retval ABS_POSITION register value converted in a 32b signed integer 00229 **********************************************************/ 00230 int32_t L6474::L6474_GetPosition(void) 00231 { 00232 return L6474_ConvertPosition(L6474_CmdGetParam(L6474_ABS_POS)); 00233 } 00234 00235 /********************************************************** 00236 * @brief Requests the motor to move to the home position (ABS_POSITION = 0) 00237 * @retval None 00238 **********************************************************/ 00239 void L6474::L6474_GoHome(void) 00240 { 00241 L6474_GoTo(0); 00242 } 00243 00244 /********************************************************** 00245 * @brief Requests the motor to move to the mark position 00246 * @retval None 00247 **********************************************************/ 00248 void L6474::L6474_GoMark(void) 00249 { 00250 uint32_t mark; 00251 00252 mark = L6474_ConvertPosition(L6474_CmdGetParam(L6474_MARK)); 00253 L6474_GoTo(mark); 00254 } 00255 00256 /********************************************************** 00257 * @brief Requests the motor to move to the specified position 00258 * @param[in] targetPosition absolute position in steps 00259 * @retval None 00260 **********************************************************/ 00261 void L6474::L6474_GoTo(int32_t targetPosition) 00262 { 00263 motorDir_t direction; 00264 int32_t steps; 00265 00266 /* Eventually deactivate motor */ 00267 if (device_prm.motionState != INACTIVE) 00268 { 00269 L6474_HardStop(); 00270 } 00271 00272 /* Get current position */ 00273 device_prm.currentPosition = L6474_ConvertPosition(L6474_CmdGetParam(L6474_ABS_POS)); 00274 00275 /* Compute the number of steps to perform */ 00276 steps = targetPosition - device_prm.currentPosition; 00277 00278 if (steps >= 0) 00279 { 00280 device_prm.stepsToTake = steps; 00281 direction = FORWARD; 00282 } 00283 else 00284 { 00285 device_prm.stepsToTake = -steps; 00286 direction = BACKWARD; 00287 } 00288 00289 if (steps != 0) 00290 { 00291 device_prm.commandExecuted = MOVE_CMD; 00292 00293 /* Direction setup */ 00294 L6474_SetDirection(direction); 00295 00296 L6474_ComputeSpeedProfile(device_prm.stepsToTake); 00297 00298 /* Motor activation */ 00299 L6474_StartMovement(); 00300 } 00301 } 00302 00303 /********************************************************** 00304 * @brief Immediatly stops the motor and disable the power bridge 00305 * @retval None 00306 **********************************************************/ 00307 void L6474::L6474_HardStop(void) 00308 { 00309 /* Disable corresponding PWM */ 00310 L6474_PwmStop(); 00311 00312 /* Set inactive state */ 00313 device_prm.motionState = INACTIVE; 00314 device_prm.commandExecuted = NO_CMD; 00315 device_prm.stepsToTake = MAX_STEPS; 00316 } 00317 00318 /********************************************************** 00319 * @brief Moves the motor of the specified number of steps 00320 * @param[in] direction FORWARD or BACKWARD 00321 * @param[in] stepCount Number of steps to perform 00322 * @retval None 00323 **********************************************************/ 00324 void L6474::L6474_Move(motorDir_t direction, uint32_t stepCount) 00325 { 00326 /* Eventually deactivate motor */ 00327 if (device_prm.motionState != INACTIVE) 00328 { 00329 L6474_HardStop(); 00330 } 00331 00332 if (stepCount != 0) 00333 { 00334 device_prm.stepsToTake = stepCount; 00335 00336 device_prm.commandExecuted = MOVE_CMD; 00337 00338 device_prm.currentPosition = L6474_ConvertPosition(L6474_CmdGetParam(L6474_ABS_POS)); 00339 00340 /* Direction setup */ 00341 L6474_SetDirection(direction); 00342 00343 L6474_ComputeSpeedProfile(stepCount); 00344 00345 /* Motor activation */ 00346 L6474_StartMovement(); 00347 } 00348 } 00349 00350 /********************************************************** 00351 * @brief Runs the motor. It will accelerate from the min 00352 * speed up to the max speed by using the device acceleration. 00353 * @param[in] direction FORWARD or BACKWARD 00354 * @retval None 00355 **********************************************************/ 00356 void L6474::L6474_Run(motorDir_t direction) 00357 { 00358 /* Eventually deactivate motor */ 00359 if (device_prm.motionState != INACTIVE) 00360 { 00361 L6474_HardStop(); 00362 } 00363 00364 /* Direction setup */ 00365 L6474_SetDirection(direction); 00366 00367 device_prm.commandExecuted = RUN_CMD; 00368 00369 /* Motor activation */ 00370 L6474_StartMovement(); 00371 } 00372 00373 /********************************************************** 00374 * @brief Changes the acceleration of the specified device 00375 * @param[in] newAcc New acceleration to apply in pps^2 00376 * @retval true if the command is successfully executed, else false 00377 * @note The command is not performed is the device is executing 00378 * a MOVE or GOTO command (but it can be used during a RUN command) 00379 **********************************************************/ 00380 bool L6474::L6474_SetAcceleration(uint16_t newAcc) 00381 { 00382 bool cmdExecuted = FALSE; 00383 if ((newAcc != 0)&& 00384 ((device_prm.motionState == INACTIVE)|| 00385 (device_prm.commandExecuted == RUN_CMD))) 00386 { 00387 device_prm.acceleration = newAcc; 00388 cmdExecuted = TRUE; 00389 } 00390 return cmdExecuted; 00391 } 00392 00393 /********************************************************** 00394 * @brief Changes the deceleration of the specified device 00395 * @param[in] newDec New deceleration to apply in pps^2 00396 * @retval true if the command is successfully executed, else false 00397 * @note The command is not performed is the device is executing 00398 * a MOVE or GOTO command (but it can be used during a RUN command) 00399 **********************************************************/ 00400 bool L6474::L6474_SetDeceleration(uint16_t newDec) 00401 { 00402 bool cmdExecuted = FALSE; 00403 if ((newDec != 0)&& 00404 ((device_prm.motionState == INACTIVE)|| 00405 (device_prm.commandExecuted == RUN_CMD))) 00406 { 00407 device_prm.deceleration = newDec; 00408 cmdExecuted = TRUE; 00409 } 00410 return cmdExecuted; 00411 } 00412 00413 /********************************************************** 00414 * @brief Set current position to be the Home position (ABS pos set to 0) 00415 * @retval None 00416 **********************************************************/ 00417 void L6474::L6474_SetHome(void) 00418 { 00419 L6474_CmdSetParam(L6474_ABS_POS, 0); 00420 } 00421 00422 /********************************************************** 00423 * @brief Sets current position to be the Mark position 00424 * @retval None 00425 **********************************************************/ 00426 void L6474::L6474_SetMark(void) 00427 { 00428 uint32_t mark = L6474_CmdGetParam(L6474_ABS_POS); 00429 L6474_CmdSetParam(L6474_MARK, mark); 00430 } 00431 00432 /********************************************************** 00433 * @brief Changes the max speed of the specified device 00434 * @param[in] newMaxSpeed New max speed to apply in pps 00435 * @retval true if the command is successfully executed, else false 00436 * @note The command is not performed is the device is executing 00437 * a MOVE or GOTO command (but it can be used during a RUN command). 00438 **********************************************************/ 00439 bool L6474::L6474_SetMaxSpeed(uint16_t newMaxSpeed) 00440 { 00441 bool cmdExecuted = FALSE; 00442 if ((newMaxSpeed >= L6474_MIN_PWM_FREQ)&& 00443 (newMaxSpeed <= L6474_MAX_PWM_FREQ) && 00444 (device_prm.minSpeed <= newMaxSpeed) && 00445 ((device_prm.motionState == INACTIVE)|| 00446 (device_prm.commandExecuted == RUN_CMD))) 00447 { 00448 device_prm.maxSpeed = newMaxSpeed; 00449 cmdExecuted = TRUE; 00450 } 00451 return cmdExecuted; 00452 } 00453 00454 /********************************************************** 00455 * @brief Changes the min speed of the specified device 00456 * @param[in] newMinSpeed New min speed to apply in pps 00457 * @retval true if the command is successfully executed, else false 00458 * @note The command is not performed is the device is executing 00459 * a MOVE or GOTO command (but it can be used during a RUN command). 00460 **********************************************************/ 00461 bool L6474::L6474_SetMinSpeed(uint16_t newMinSpeed) 00462 { 00463 bool cmdExecuted = FALSE; 00464 if ((newMinSpeed >= L6474_MIN_PWM_FREQ)&& 00465 (newMinSpeed <= L6474_MAX_PWM_FREQ) && 00466 (newMinSpeed <= device_prm.maxSpeed) && 00467 ((device_prm.motionState == INACTIVE)|| 00468 (device_prm.commandExecuted == RUN_CMD))) 00469 { 00470 device_prm.minSpeed = newMinSpeed; 00471 cmdExecuted = TRUE; 00472 } 00473 return cmdExecuted; 00474 } 00475 00476 /********************************************************** 00477 * @brief Stops the motor by using the device deceleration 00478 * @retval true if the command is successfully executed, else false 00479 * @note The command is not performed is the device is in INACTIVE state. 00480 **********************************************************/ 00481 bool L6474::L6474_SoftStop(void) 00482 { 00483 bool cmdExecuted = FALSE; 00484 if (device_prm.motionState != INACTIVE) 00485 { 00486 device_prm.commandExecuted = SOFT_STOP_CMD; 00487 cmdExecuted = TRUE; 00488 } 00489 return (cmdExecuted); 00490 } 00491 00492 /********************************************************** 00493 * @brief Locks until the device state becomes Inactive 00494 * @retval None 00495 **********************************************************/ 00496 void L6474::L6474_WaitWhileActive(void) 00497 { 00498 /* Wait while motor is running */ 00499 while (L6474_GetDeviceState() != INACTIVE); 00500 } 00501 00502 /********************************************************** 00503 * @brief Issue the Disable command to the L6474 of the specified device 00504 * @retval None 00505 **********************************************************/ 00506 void L6474::L6474_CmdDisable(void) 00507 { 00508 L6474_SendCommand(L6474_DISABLE); 00509 } 00510 00511 /********************************************************** 00512 * @brief Issues the Enable command to the L6474 of the specified device 00513 * @retval None 00514 **********************************************************/ 00515 void L6474::L6474_CmdEnable(void) 00516 { 00517 L6474_SendCommand(L6474_ENABLE); 00518 } 00519 00520 /********************************************************** 00521 * @brief Issues the GetParam command to the L6474 of the specified device 00522 * @param[in] parameter Register adress (L6474_ABS_POS, L6474_MARK,...) 00523 * @retval Register value 00524 **********************************************************/ 00525 uint32_t L6474::L6474_CmdGetParam(L6474_Registers_t parameter) 00526 { 00527 uint32_t i; 00528 uint32_t spiRxData; 00529 uint8_t maxArgumentNbBytes = 0; 00530 uint8_t spiIndex = number_of_devices - device_instance - 1; 00531 bool itDisable = FALSE; 00532 00533 do 00534 { 00535 spi_preemtion_by_isr = FALSE; 00536 if (itDisable) 00537 { 00538 /* re-enable L6474_EnableIrq if disable in previous iteration */ 00539 L6474_EnableIrq(); 00540 itDisable = FALSE; 00541 } 00542 00543 for (i = 0; i < number_of_devices; i++) 00544 { 00545 spi_tx_bursts[0][i] = L6474_NOP; 00546 spi_tx_bursts[1][i] = L6474_NOP; 00547 spi_tx_bursts[2][i] = L6474_NOP; 00548 spi_tx_bursts[3][i] = L6474_NOP; 00549 spi_rx_bursts[1][i] = 0; 00550 spi_rx_bursts[2][i] = 0; 00551 spi_rx_bursts[3][i] = 0; 00552 } 00553 00554 switch (parameter) 00555 { 00556 case L6474_ABS_POS: ; 00557 case L6474_MARK: 00558 spi_tx_bursts[0][spiIndex] = ((uint8_t)L6474_GET_PARAM )| (parameter); 00559 maxArgumentNbBytes = 3; 00560 break; 00561 case L6474_EL_POS: ; 00562 case L6474_CONFIG: ; 00563 case L6474_STATUS: 00564 spi_tx_bursts[1][spiIndex] = ((uint8_t)L6474_GET_PARAM )| (parameter); 00565 maxArgumentNbBytes = 2; 00566 break; 00567 default: 00568 spi_tx_bursts[2][spiIndex] = ((uint8_t)L6474_GET_PARAM )| (parameter); 00569 maxArgumentNbBytes = 1; 00570 } 00571 00572 /* Disable interruption before checking */ 00573 /* pre-emption by ISR and SPI transfers*/ 00574 L6474_DisableIrq(); 00575 itDisable = TRUE; 00576 } while (spi_preemtion_by_isr); // check pre-emption by ISR 00577 00578 for (i = L6474_CMD_ARG_MAX_NB_BYTES-1-maxArgumentNbBytes; 00579 i < L6474_CMD_ARG_MAX_NB_BYTES; 00580 i++) 00581 { 00582 L6474_WriteBytes(&spi_tx_bursts[i][0], &spi_rx_bursts[i][0]); 00583 } 00584 00585 spiRxData = ((uint32_t)spi_rx_bursts[1][spiIndex] << 16) | 00586 (spi_rx_bursts[2][spiIndex] << 8) | 00587 (spi_rx_bursts[3][spiIndex]); 00588 00589 /* re-enable L6474_EnableIrq after SPI transfers*/ 00590 L6474_EnableIrq(); 00591 00592 return (spiRxData); 00593 } 00594 00595 /********************************************************** 00596 * @brief Issues the GetStatus command to the L6474 of the specified device 00597 * @retval Status Register value 00598 * @note Once the GetStatus command is performed, the flags of the status register 00599 * are reset. This is not the case when the status register is read with the 00600 * GetParam command (via the functions L6474ReadStatusRegister or L6474_CmdGetParam). 00601 **********************************************************/ 00602 uint16_t L6474::L6474_CmdGetStatus(void) 00603 { 00604 uint32_t i; 00605 uint16_t status; 00606 uint8_t spiIndex = number_of_devices - device_instance - 1; 00607 bool itDisable = FALSE; 00608 00609 do 00610 { 00611 spi_preemtion_by_isr = FALSE; 00612 if (itDisable) 00613 { 00614 /* re-enable L6474_EnableIrq if disable in previous iteration */ 00615 L6474_EnableIrq(); 00616 itDisable = FALSE; 00617 } 00618 00619 for (i = 0; i < number_of_devices; i++) 00620 { 00621 spi_tx_bursts[0][i] = L6474_NOP; 00622 spi_tx_bursts[1][i] = L6474_NOP; 00623 spi_tx_bursts[2][i] = L6474_NOP; 00624 spi_rx_bursts[1][i] = 0; 00625 spi_rx_bursts[2][i] = 0; 00626 } 00627 spi_tx_bursts[0][spiIndex] = L6474_GET_STATUS; 00628 00629 /* Disable interruption before checking */ 00630 /* pre-emption by ISR and SPI transfers*/ 00631 L6474_DisableIrq(); 00632 itDisable = TRUE; 00633 } while (spi_preemtion_by_isr); // check pre-emption by ISR 00634 00635 for (i = 0; i < L6474_CMD_ARG_NB_BYTES_GET_STATUS + L6474_RSP_NB_BYTES_GET_STATUS; i++) 00636 { 00637 L6474_WriteBytes(&spi_tx_bursts[i][0], &spi_rx_bursts[i][0]); 00638 } 00639 status = (spi_rx_bursts[1][spiIndex] << 8) | (spi_rx_bursts[2][spiIndex]); 00640 00641 /* re-enable L6474_EnableIrq after SPI transfers*/ 00642 L6474_EnableIrq(); 00643 00644 return (status); 00645 } 00646 00647 /********************************************************** 00648 * @brief Issues the Nop command to the L6474 of the specified device 00649 * @retval None 00650 **********************************************************/ 00651 void L6474::L6474_CmdNop(void) 00652 { 00653 L6474_SendCommand(L6474_NOP); 00654 } 00655 00656 /********************************************************** 00657 * @brief Issues the SetParam command to the L6474 of the specified device 00658 * @param[in] parameter Register adress (L6474_ABS_POS, L6474_MARK,...) 00659 * @param[in] value Value to set in the register 00660 * @retval None 00661 **********************************************************/ 00662 void L6474::L6474_CmdSetParam(L6474_Registers_t parameter, uint32_t value) 00663 { 00664 uint32_t i; 00665 uint8_t maxArgumentNbBytes = 0; 00666 uint8_t spiIndex = number_of_devices - device_instance - 1; 00667 bool itDisable = FALSE; 00668 do 00669 { 00670 spi_preemtion_by_isr = FALSE; 00671 if (itDisable) 00672 { 00673 /* re-enable L6474_EnableIrq if disable in previous iteration */ 00674 L6474_EnableIrq(); 00675 itDisable = FALSE; 00676 } 00677 00678 for (i = 0; i < number_of_devices; i++) 00679 { 00680 spi_tx_bursts[0][i] = L6474_NOP; 00681 spi_tx_bursts[1][i] = L6474_NOP; 00682 spi_tx_bursts[2][i] = L6474_NOP; 00683 spi_tx_bursts[3][i] = L6474_NOP; 00684 } 00685 00686 switch (parameter) 00687 { 00688 case L6474_ABS_POS: ; 00689 case L6474_MARK: 00690 spi_tx_bursts[0][spiIndex] = parameter; 00691 spi_tx_bursts[1][spiIndex] = (uint8_t)(value >> 16); 00692 spi_tx_bursts[2][spiIndex] = (uint8_t)(value >> 8); 00693 maxArgumentNbBytes = 3; 00694 break; 00695 case L6474_EL_POS: ; 00696 case L6474_CONFIG: 00697 spi_tx_bursts[1][spiIndex] = parameter; 00698 spi_tx_bursts[2][spiIndex] = (uint8_t)(value >> 8); 00699 maxArgumentNbBytes = 2; 00700 break; 00701 default: 00702 spi_tx_bursts[2][spiIndex] = parameter; 00703 maxArgumentNbBytes = 1; 00704 break; 00705 } 00706 spi_tx_bursts[3][spiIndex] = (uint8_t)(value); 00707 00708 /* Disable interruption before checking */ 00709 /* pre-emption by ISR and SPI transfers*/ 00710 L6474_DisableIrq(); 00711 itDisable = TRUE; 00712 } while (spi_preemtion_by_isr); // check pre-emption by ISR 00713 00714 /* SPI transfer */ 00715 for (i = L6474_CMD_ARG_MAX_NB_BYTES-1-maxArgumentNbBytes; 00716 i < L6474_CMD_ARG_MAX_NB_BYTES; 00717 i++) 00718 { 00719 L6474_WriteBytes(&spi_tx_bursts[i][0],&spi_rx_bursts[i][0]); 00720 } 00721 /* re-enable L6474_EnableIrq after SPI transfers*/ 00722 L6474_EnableIrq(); 00723 } 00724 00725 /********************************************************** 00726 * @brief Reads the Status Register value 00727 * @retval Status register valued 00728 * @note The status register flags are not cleared 00729 * at the difference with L6474CmdGetStatus() 00730 **********************************************************/ 00731 uint16_t L6474::L6474_ReadStatusRegister(void) 00732 { 00733 return (L6474_CmdGetParam(L6474_STATUS)); 00734 } 00735 00736 /********************************************************** 00737 * @brief Set the stepping mode 00738 * @param[in] stepMod from full step to 1/16 microstep as specified in enum motorStepMode_t 00739 * @retval None 00740 **********************************************************/ 00741 void L6474::L6474_SelectStepMode(motorStepMode_t stepMod) 00742 { 00743 uint8_t stepModeRegister; 00744 L6474_STEP_SEL_t l6474StepMod; 00745 00746 switch (stepMod) 00747 { 00748 case STEP_MODE_FULL: 00749 l6474StepMod = L6474_STEP_SEL_1; 00750 break; 00751 case STEP_MODE_HALF: 00752 l6474StepMod = L6474_STEP_SEL_1_2; 00753 break; 00754 case STEP_MODE_1_4: 00755 l6474StepMod = L6474_STEP_SEL_1_4; 00756 break; 00757 case STEP_MODE_1_8: 00758 l6474StepMod = L6474_STEP_SEL_1_8; 00759 break; 00760 case STEP_MODE_1_16: 00761 default: 00762 l6474StepMod = L6474_STEP_SEL_1_16; 00763 break; 00764 } 00765 00766 /* Eventually deactivate motor */ 00767 if (device_prm.motionState != INACTIVE) 00768 { 00769 L6474_HardStop(); 00770 } 00771 00772 /* Read Step mode register and clear STEP_SEL field */ 00773 stepModeRegister = (uint8_t)(0xF8 & L6474_CmdGetParam(L6474_STEP_MODE)) ; 00774 00775 /* Apply new step mode */ 00776 L6474_CmdSetParam(L6474_STEP_MODE, stepModeRegister | (uint8_t)l6474StepMod); 00777 00778 /* Reset abs pos register */ 00779 L6474_SetHome(); 00780 } 00781 00782 /********************************************************** 00783 * @brief Get the direction 00784 * @param None 00785 * @retval direction FORWARD or BACKWARD 00786 **********************************************************/ 00787 motorDir_t L6474::L6474_GetDirection(void) 00788 { 00789 return device_prm.direction; 00790 } 00791 00792 /********************************************************** 00793 * @brief Specifies the direction 00794 * @param[in] dir FORWARD or BACKWARD 00795 * @note The direction change is only applied if the device 00796 * is in INACTIVE state 00797 * @retval None 00798 **********************************************************/ 00799 void L6474::L6474_SetDirection(motorDir_t direction) 00800 { 00801 if (device_prm.motionState == INACTIVE) 00802 { 00803 device_prm.direction = direction; 00804 L6474_SetDirectionGpio(direction); 00805 } 00806 } 00807 00808 /********************************************************** 00809 * @brief Updates the current speed of the device 00810 * @param[in] newSpeed in pps 00811 * @retval None 00812 **********************************************************/ 00813 void L6474::L6474_ApplySpeed(uint16_t newSpeed) 00814 { 00815 if (newSpeed < L6474_MIN_PWM_FREQ) 00816 { 00817 newSpeed = L6474_MIN_PWM_FREQ; 00818 } 00819 if (newSpeed > L6474_MAX_PWM_FREQ) 00820 { 00821 newSpeed = L6474_MAX_PWM_FREQ; 00822 } 00823 00824 device_prm.speed = newSpeed; 00825 00826 L6474_PwmSetFreq(newSpeed); 00827 } 00828 00829 /********************************************************** 00830 * @brief Computes the speed profile according to the number of steps to move 00831 * @param[in] nbSteps number of steps to perform 00832 * @retval None 00833 * @note Using the acceleration and deceleration of the device, 00834 * this function determines the duration in steps of the acceleration, 00835 * steady and deceleration phases. 00836 * If the total number of steps to perform is big enough, a trapezoidal move 00837 * is performed (i.e. there is a steady phase where the motor runs at the maximum 00838 * speed. 00839 * Else, a triangular move is performed (no steady phase: the maximum speed is never 00840 * reached. 00841 **********************************************************/ 00842 void L6474::L6474_ComputeSpeedProfile(uint32_t nbSteps) 00843 { 00844 uint32_t reqAccSteps; 00845 uint32_t reqDecSteps; 00846 00847 /* compute the number of steps to get the targeted speed */ 00848 uint16_t minSpeed = device_prm.minSpeed; 00849 reqAccSteps = (device_prm.maxSpeed - minSpeed); 00850 reqAccSteps *= (device_prm.maxSpeed + minSpeed); 00851 reqDecSteps = reqAccSteps; 00852 reqAccSteps /= (uint32_t)device_prm.acceleration; 00853 reqAccSteps /= 2; 00854 00855 /* compute the number of steps to stop */ 00856 reqDecSteps /= (uint32_t)device_prm.deceleration; 00857 reqDecSteps /= 2; 00858 00859 if(( reqAccSteps + reqDecSteps ) > nbSteps) 00860 { 00861 /* Triangular move */ 00862 /* reqDecSteps = (Pos * Dec) /(Dec+Acc) */ 00863 uint32_t dec = device_prm.deceleration; 00864 uint32_t acc = device_prm.acceleration; 00865 00866 reqDecSteps = ((uint32_t) dec * nbSteps) / (acc + dec); 00867 if (reqDecSteps > 1) 00868 { 00869 reqAccSteps = reqDecSteps - 1; 00870 if(reqAccSteps == 0) 00871 { 00872 reqAccSteps = 1; 00873 } 00874 } 00875 else 00876 { 00877 reqAccSteps = 0; 00878 } 00879 device_prm.endAccPos = reqAccSteps; 00880 device_prm.startDecPos = reqDecSteps; 00881 } 00882 else 00883 { 00884 /* Trapezoidal move */ 00885 /* accelerating phase to endAccPos */ 00886 /* steady phase from endAccPos to startDecPos */ 00887 /* decelerating from startDecPos to stepsToTake*/ 00888 device_prm.endAccPos = reqAccSteps; 00889 device_prm.startDecPos = nbSteps - reqDecSteps - 1; 00890 } 00891 } 00892 00893 /********************************************************** 00894 * @brief Converts the ABS_POSITION register value to a 32b signed integer 00895 * @param[in] abs_position_reg value of the ABS_POSITION register 00896 * @retval operation_result 32b signed integer corresponding to the absolute position 00897 **********************************************************/ 00898 int32_t L6474::L6474_ConvertPosition(uint32_t abs_position_reg) 00899 { 00900 int32_t operation_result; 00901 00902 if (abs_position_reg & L6474_ABS_POS_SIGN_BIT_MASK) 00903 { 00904 /* Negative register value */ 00905 abs_position_reg = ~abs_position_reg; 00906 abs_position_reg += 1; 00907 00908 operation_result = (int32_t) (abs_position_reg & L6474_ABS_POS_VALUE_MASK); 00909 operation_result = -operation_result; 00910 } 00911 else 00912 { 00913 operation_result = (int32_t) abs_position_reg; 00914 } 00915 00916 return operation_result; 00917 } 00918 00919 /********************************************************** 00920 * @brief Error handler which calls the user callback (if defined) 00921 * @param[in] error Number of the error 00922 * @retval None 00923 **********************************************************/ 00924 void L6474::L6474_ErrorHandler(uint16_t error) 00925 { 00926 if (error_handler_callback != 0) 00927 { 00928 (void) error_handler_callback(error); 00929 } 00930 else 00931 { 00932 /* Aborting the program. */ 00933 exit(EXIT_FAILURE); 00934 } 00935 } 00936 00937 /********************************************************** 00938 * @brief Sends a command without arguments to the L6474 via the SPI 00939 * @param[in] param Command to send 00940 * @retval None 00941 **********************************************************/ 00942 void L6474::L6474_SendCommand(uint8_t param) 00943 { 00944 uint32_t i; 00945 bool itDisable = FALSE; 00946 uint8_t spiIndex = number_of_devices - device_instance - 1; 00947 00948 do 00949 { 00950 spi_preemtion_by_isr = FALSE; 00951 if (itDisable) 00952 { 00953 /* re-enable L6474_EnableIrq if disable in previous iteration */ 00954 L6474_EnableIrq(); 00955 itDisable = FALSE; 00956 } 00957 00958 for (i = 0; i < number_of_devices; i++) 00959 { 00960 spi_tx_bursts[3][i] = L6474_NOP; 00961 } 00962 spi_tx_bursts[3][spiIndex] = param; 00963 00964 /* Disable interruption before checking */ 00965 /* pre-emption by ISR and SPI transfers*/ 00966 L6474_DisableIrq(); 00967 itDisable = TRUE; 00968 } while (spi_preemtion_by_isr); // check pre-emption by ISR 00969 00970 L6474_WriteBytes(&spi_tx_bursts[3][0], &spi_rx_bursts[3][0]); 00971 00972 /* re-enable L6474_EnableIrq after SPI transfers*/ 00973 L6474_EnableIrq(); 00974 } 00975 00976 /********************************************************** 00977 * @brief Sets the registers of the L6474 to their predefined values 00978 * from l6474_target_config.h 00979 * @retval None 00980 **********************************************************/ 00981 void L6474::L6474_SetRegisterToPredefinedValues(void) 00982 { 00983 L6474_CmdSetParam( 00984 L6474_ABS_POS, 00985 0); 00986 L6474_CmdSetParam( 00987 L6474_EL_POS, 00988 0); 00989 L6474_CmdSetParam( 00990 L6474_MARK, 00991 0); 00992 switch (device_instance) 00993 { 00994 case 0: 00995 L6474_CmdSetParam( 00996 L6474_TVAL, 00997 L6474_Tval_Current_to_Par(L6474_CONF_PARAM_TVAL_DEVICE_0)); 00998 L6474_CmdSetParam( 00999 L6474_T_FAST, 01000 (uint8_t)L6474_CONF_PARAM_TOFF_FAST_DEVICE_0 | 01001 (uint8_t)L6474_CONF_PARAM_FAST_STEP_DEVICE_0); 01002 L6474_CmdSetParam( 01003 L6474_TON_MIN, 01004 L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TON_MIN_DEVICE_0) 01005 ); 01006 L6474_CmdSetParam( 01007 L6474_TOFF_MIN, 01008 L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TOFF_MIN_DEVICE_0)); 01009 L6474_CmdSetParam( 01010 L6474_OCD_TH, 01011 L6474_CONF_PARAM_OCD_TH_DEVICE_0); 01012 L6474_CmdSetParam( 01013 L6474_STEP_MODE, 01014 (uint8_t)L6474_CONF_PARAM_STEP_SEL_DEVICE_0 | 01015 (uint8_t)L6474_CONF_PARAM_SYNC_SEL_DEVICE_0); 01016 L6474_CmdSetParam( 01017 L6474_ALARM_EN, 01018 L6474_CONF_PARAM_ALARM_EN_DEVICE_0); 01019 L6474_CmdSetParam( 01020 L6474_CONFIG, 01021 (uint16_t)L6474_CONF_PARAM_CLOCK_SETTING_DEVICE_0 | 01022 (uint16_t)L6474_CONF_PARAM_TQ_REG_DEVICE_0 | 01023 (uint16_t)L6474_CONF_PARAM_OC_SD_DEVICE_0 | 01024 (uint16_t)L6474_CONF_PARAM_SR_DEVICE_0 | 01025 (uint16_t)L6474_CONF_PARAM_TOFF_DEVICE_0); 01026 break; 01027 case 1: 01028 L6474_CmdSetParam( 01029 L6474_TVAL, 01030 L6474_Tval_Current_to_Par(L6474_CONF_PARAM_TVAL_DEVICE_1)); 01031 L6474_CmdSetParam( 01032 L6474_T_FAST, 01033 (uint8_t)L6474_CONF_PARAM_TOFF_FAST_DEVICE_1 | 01034 (uint8_t)L6474_CONF_PARAM_FAST_STEP_DEVICE_1); 01035 L6474_CmdSetParam( 01036 L6474_TON_MIN, 01037 L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TON_MIN_DEVICE_1)); 01038 L6474_CmdSetParam( 01039 L6474_TOFF_MIN, 01040 L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TOFF_MIN_DEVICE_1)); 01041 L6474_CmdSetParam( 01042 L6474_OCD_TH, 01043 L6474_CONF_PARAM_OCD_TH_DEVICE_1); 01044 L6474_CmdSetParam( 01045 L6474_STEP_MODE, 01046 (uint8_t)L6474_CONF_PARAM_STEP_SEL_DEVICE_1 | 01047 (uint8_t)L6474_CONF_PARAM_SYNC_SEL_DEVICE_1); 01048 L6474_CmdSetParam( 01049 L6474_ALARM_EN, 01050 L6474_CONF_PARAM_ALARM_EN_DEVICE_1); 01051 L6474_CmdSetParam( 01052 L6474_CONFIG, 01053 (uint16_t)L6474_CONF_PARAM_CLOCK_SETTING_DEVICE_1 | 01054 (uint16_t)L6474_CONF_PARAM_TQ_REG_DEVICE_1 | 01055 (uint16_t)L6474_CONF_PARAM_OC_SD_DEVICE_1 | 01056 (uint16_t)L6474_CONF_PARAM_SR_DEVICE_1 | 01057 (uint16_t)L6474_CONF_PARAM_TOFF_DEVICE_1); 01058 break; 01059 case 2: 01060 L6474_CmdSetParam( 01061 L6474_TVAL, 01062 L6474_Tval_Current_to_Par(L6474_CONF_PARAM_TVAL_DEVICE_2)); 01063 L6474_CmdSetParam( 01064 L6474_T_FAST, 01065 (uint8_t)L6474_CONF_PARAM_TOFF_FAST_DEVICE_2 | 01066 (uint8_t)L6474_CONF_PARAM_FAST_STEP_DEVICE_2); 01067 L6474_CmdSetParam( 01068 L6474_TON_MIN, 01069 L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TON_MIN_DEVICE_2)); 01070 L6474_CmdSetParam( 01071 L6474_TOFF_MIN, 01072 L6474_Tmin_Time_to_Par(L6474_CONF_PARAM_TOFF_MIN_DEVICE_2)); 01073 L6474_CmdSetParam( 01074 L6474_OCD_TH, 01075 L6474_CONF_PARAM_OCD_TH_DEVICE_2); 01076 L6474_CmdSetParam( 01077 L6474_STEP_MODE, 01078 (uint8_t)L6474_CONF_PARAM_STEP_SEL_DEVICE_2 | 01079 (uint8_t)L6474_CONF_PARAM_SYNC_SEL_DEVICE_2); 01080 L6474_CmdSetParam( 01081 L6474_ALARM_EN, 01082 L6474_CONF_PARAM_ALARM_EN_DEVICE_2); 01083 L6474_CmdSetParam( 01084 L6474_CONFIG, 01085 (uint16_t)L6474_CONF_PARAM_CLOCK_SETTING_DEVICE_2 | 01086 (uint16_t)L6474_CONF_PARAM_TQ_REG_DEVICE_2 | 01087 (uint16_t)L6474_CONF_PARAM_OC_SD_DEVICE_2 | 01088 (uint16_t)L6474_CONF_PARAM_SR_DEVICE_2 | 01089 (uint16_t)L6474_CONF_PARAM_TOFF_DEVICE_2); 01090 break; 01091 default: ; 01092 } 01093 } 01094 01095 /********************************************************** 01096 * @brief Sets the registers of the L6474 to initialization values. 01097 * @param init Initialization structure. 01098 * @retval None. 01099 **********************************************************/ 01100 void L6474::L6474_SetRegisterToInitializationValues(L6474_Init_t *init) 01101 { 01102 L6474_CmdSetParam( 01103 L6474_ABS_POS, 01104 0 01105 ); 01106 L6474_CmdSetParam( 01107 L6474_EL_POS, 01108 0 01109 ); 01110 L6474_CmdSetParam( 01111 L6474_MARK, 01112 0 01113 ); 01114 L6474_CmdSetParam( 01115 L6474_TVAL, 01116 L6474_Tval_Current_to_Par(init->torque_regulation_current_mA) 01117 ); 01118 L6474_CmdSetParam( 01119 L6474_T_FAST, 01120 (uint8_t) init->maximum_fast_decay_time | 01121 (uint8_t) init->fall_time 01122 ); 01123 L6474_CmdSetParam( 01124 L6474_TON_MIN, 01125 L6474_Tmin_Time_to_Par(init->minimum_ON_time_us) 01126 ); 01127 L6474_CmdSetParam( 01128 L6474_TOFF_MIN, 01129 L6474_Tmin_Time_to_Par(init->minimum_OFF_time_us) 01130 ); 01131 L6474_CmdSetParam( 01132 L6474_OCD_TH, 01133 init->overcurrent_threshold 01134 ); 01135 L6474_CmdSetParam( 01136 L6474_STEP_MODE, 01137 (uint8_t) init->step_selection | 01138 (uint8_t) init->sync_selection 01139 ); 01140 L6474_CmdSetParam( 01141 L6474_ALARM_EN, 01142 init->alarm 01143 ); 01144 L6474_CmdSetParam( 01145 L6474_CONFIG, 01146 (uint16_t) init->clock | 01147 (uint16_t) init->torque_regulation_method | 01148 (uint16_t) init->overcurrent_shutwdown | 01149 (uint16_t) init->slew_rate | 01150 (uint16_t) init->target_swicthing_period 01151 ); 01152 } 01153 01154 /********************************************************** 01155 * @brief Sets the parameters of the device to predefined values 01156 * from l6474_target_config.h 01157 * @param None 01158 * @retval None 01159 **********************************************************/ 01160 void L6474::L6474_SetDeviceParamsToPredefinedValues(void) 01161 { 01162 switch (device_instance) 01163 { 01164 case 0: 01165 device_prm.acceleration = L6474_CONF_PARAM_ACC_DEVICE_0; 01166 device_prm.deceleration = L6474_CONF_PARAM_DEC_DEVICE_0; 01167 device_prm.maxSpeed = L6474_CONF_PARAM_MAX_SPEED_DEVICE_0; 01168 device_prm.minSpeed = L6474_CONF_PARAM_MIN_SPEED_DEVICE_0; 01169 break; 01170 01171 case 1: 01172 device_prm.acceleration = L6474_CONF_PARAM_ACC_DEVICE_1; 01173 device_prm.deceleration = L6474_CONF_PARAM_DEC_DEVICE_1; 01174 device_prm.maxSpeed = L6474_CONF_PARAM_MAX_SPEED_DEVICE_1; 01175 device_prm.minSpeed = L6474_CONF_PARAM_MIN_SPEED_DEVICE_1; 01176 break; 01177 01178 case 2: 01179 device_prm.acceleration = L6474_CONF_PARAM_ACC_DEVICE_2; 01180 device_prm.deceleration = L6474_CONF_PARAM_DEC_DEVICE_2; 01181 device_prm.maxSpeed = L6474_CONF_PARAM_MAX_SPEED_DEVICE_2; 01182 device_prm.minSpeed = L6474_CONF_PARAM_MIN_SPEED_DEVICE_2; 01183 break; 01184 } 01185 01186 device_prm.accu = 0; 01187 device_prm.currentPosition = 0; 01188 device_prm.endAccPos = 0; 01189 device_prm.relativePos = 0; 01190 device_prm.startDecPos = 0; 01191 device_prm.stepsToTake = 0; 01192 device_prm.speed = 0; 01193 device_prm.commandExecuted = NO_CMD; 01194 device_prm.direction = FORWARD; 01195 device_prm.motionState = INACTIVE; 01196 } 01197 01198 /********************************************************** 01199 * @brief Initialises the bridge parameters to start the movement 01200 * and enable the power bridge 01201 * @retval None 01202 **********************************************************/ 01203 void L6474::L6474_StartMovement(void) 01204 { 01205 /* Enable L6474 powerstage */ 01206 L6474_CmdEnable(); 01207 if (device_prm.endAccPos != 0) 01208 { 01209 device_prm.motionState = ACCELERATING; 01210 } 01211 else 01212 { 01213 device_prm.motionState = DECELERATING; 01214 } 01215 device_prm.accu = 0; 01216 device_prm.relativePos = 0; 01217 L6474_ApplySpeed(device_prm.minSpeed); 01218 } 01219 01220 /********************************************************** 01221 * @brief Handles the device state machine at each ste 01222 * @retval None 01223 * @note Must only be called by the timer ISR 01224 **********************************************************/ 01225 void L6474::L6474_StepClockHandler(void) 01226 { 01227 /* Set isr flag */ 01228 isr_flag = TRUE; 01229 01230 /* Incrementation of the relative position */ 01231 device_prm.relativePos++; 01232 01233 switch (device_prm.motionState) 01234 { 01235 case ACCELERATING: 01236 { 01237 uint32_t relPos = device_prm.relativePos; 01238 uint32_t endAccPos = device_prm.endAccPos; 01239 uint16_t speed = device_prm.speed; 01240 uint32_t acc = ((uint32_t)device_prm.acceleration << 16); 01241 01242 if ((device_prm.commandExecuted == SOFT_STOP_CMD)|| 01243 ((device_prm.commandExecuted != RUN_CMD)&& 01244 (relPos == device_prm.startDecPos))) 01245 { 01246 device_prm.motionState = DECELERATING; 01247 device_prm.accu = 0; 01248 } 01249 else if ((speed >= device_prm.maxSpeed)|| 01250 ((device_prm.commandExecuted != RUN_CMD)&& 01251 (relPos == endAccPos))) 01252 { 01253 device_prm.motionState = STEADY; 01254 } 01255 else 01256 { 01257 bool speedUpdated = FALSE; 01258 /* Go on accelerating */ 01259 if (speed == 0) speed =1; 01260 device_prm.accu += acc / speed; 01261 while (device_prm.accu >= (0X10000L)) 01262 { 01263 device_prm.accu -= (0X10000L); 01264 speed +=1; 01265 speedUpdated = TRUE; 01266 } 01267 01268 if (speedUpdated) 01269 { 01270 if (speed > device_prm.maxSpeed) 01271 { 01272 speed = device_prm.maxSpeed; 01273 } 01274 device_prm.speed = speed; 01275 L6474_ApplySpeed(device_prm.speed); 01276 } 01277 } 01278 break; 01279 } 01280 case STEADY: 01281 { 01282 uint16_t maxSpeed = device_prm.maxSpeed; 01283 uint32_t relativePos = device_prm.relativePos; 01284 if ((device_prm.commandExecuted == SOFT_STOP_CMD)|| 01285 ((device_prm.commandExecuted != RUN_CMD)&& 01286 (relativePos >= (device_prm.startDecPos))) || 01287 ((device_prm.commandExecuted == RUN_CMD)&& 01288 (device_prm.speed > maxSpeed))) 01289 { 01290 device_prm.motionState = DECELERATING; 01291 device_prm.accu = 0; 01292 } 01293 else if ((device_prm.commandExecuted == RUN_CMD)&& 01294 (device_prm.speed < maxSpeed)) 01295 { 01296 device_prm.motionState = ACCELERATING; 01297 device_prm.accu = 0; 01298 } 01299 break; 01300 } 01301 case DECELERATING: 01302 { 01303 uint32_t relativePos = device_prm.relativePos; 01304 uint16_t speed = device_prm.speed; 01305 uint32_t deceleration = ((uint32_t)device_prm.deceleration << 16); 01306 if (((device_prm.commandExecuted == SOFT_STOP_CMD)&&(speed <= device_prm.minSpeed))|| 01307 ((device_prm.commandExecuted != RUN_CMD)&& 01308 (relativePos >= device_prm.stepsToTake))) 01309 { 01310 /* Motion process complete */ 01311 L6474_HardStop(); 01312 } 01313 else if ((device_prm.commandExecuted == RUN_CMD)&& 01314 (speed <= device_prm.maxSpeed)) 01315 { 01316 device_prm.motionState = STEADY; 01317 } 01318 else 01319 { 01320 /* Go on decelerating */ 01321 if (speed > device_prm.minSpeed) 01322 { 01323 bool speedUpdated = FALSE; 01324 if (speed == 0) speed =1; 01325 device_prm.accu += deceleration / speed; 01326 while (device_prm.accu >= (0X10000L)) 01327 { 01328 device_prm.accu -= (0X10000L); 01329 if (speed > 1) 01330 { 01331 speed -=1; 01332 } 01333 speedUpdated = TRUE; 01334 } 01335 01336 if (speedUpdated) 01337 { 01338 if (speed < device_prm.minSpeed) 01339 { 01340 speed = device_prm.minSpeed; 01341 } 01342 device_prm.speed = speed; 01343 L6474_ApplySpeed(device_prm.speed); 01344 } 01345 } 01346 } 01347 break; 01348 } 01349 default: 01350 { 01351 break; 01352 } 01353 } 01354 /* Set isr flag */ 01355 isr_flag = FALSE; 01356 } 01357 01358 /********************************************************** 01359 * @brief Converts current in mA to values for TVAL register 01360 * @param[in] current_mA current in mA 01361 * @retval value for TVAL register 01362 **********************************************************/ 01363 float L6474::L6474_Tval_Current_to_Par(float current_mA) 01364 { 01365 return ((float)(((current_mA - 31.25f) / 31.25f) + 0.5f)); 01366 } 01367 01368 /********************************************************** 01369 * @brief Converts values from TVAL register to mA 01370 * @param[in] Tval value from TVAL register 01371 * @retval current in mA 01372 **********************************************************/ 01373 float L6474::L6474_Par_to_Tval_Current(float Tval) 01374 { 01375 return ((float)((Tval - 0.5f) * 31.25f + 31.25f)); 01376 } 01377 01378 /********************************************************** 01379 * @brief Convert time in us to values for TON_MIN register 01380 * @param[in] ton_min_us time in us 01381 * @retval value for TON_MIN register 01382 **********************************************************/ 01383 float L6474::L6474_Tmin_Time_to_Par(float ton_min_us) 01384 { 01385 return ((float)(((ton_min_us - 0.5f) * 2.0f) + 0.5f)); 01386 } 01387 01388 /********************************************************** 01389 * @brief Convert values for TON_MIN register to time in us 01390 * @param[in] Tmin value from TON_MIN register 01391 * @retval time in us 01392 **********************************************************/ 01393 float L6474::L6474_Par_to_Tmin_Time(float Tmin) 01394 { 01395 return ((float)(((Tmin - 0.5f) / 2.0f) + 0.5f)); 01396 } 01397 01398 /********************************************************** 01399 * @brief Write and receive a byte via SPI 01400 * @param[in] pByteToTransmit pointer to the byte to transmit 01401 * @param[in] pReceivedByte pointer to the received byte 01402 * @retval None 01403 **********************************************************/ 01404 void L6474::L6474_WriteBytes(uint8_t *pByteToTransmit, uint8_t *pReceivedByte) 01405 { 01406 if (L6474_SpiWriteBytes(pByteToTransmit, pReceivedByte) != 0) 01407 { 01408 L6474_ErrorHandler(L6474_ERROR_1); 01409 } 01410 01411 if (isr_flag) 01412 { 01413 spi_preemtion_by_isr = TRUE; 01414 } 01415 } 01416 01417 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 20:40:40 by
1.7.2
