Added ST_INTERFACES library.
Fork of X-NUCLEO-IHM05A1 by
Embed:
(wiki syntax)
Show/hide line numbers
l6208_class.cpp
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file l6208_class.cpp 00004 * @author IPC Rennes 00005 * @version V1.1.0 00006 * @date February 11th, 2016 00007 * @brief L6208 product related routines 00008 * @note (C) COPYRIGHT 2016 STMicroelectronics 00009 ****************************************************************************** 00010 * @attention 00011 * 00012 * <h2><center>© COPYRIGHT(c) 2016 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 /* Includes ------------------------------------------------------------------*/ 00040 #include "l6208_class.h" 00041 00042 /* Definitions ---------------------------------------------------------------*/ 00043 /// Bridge A 00044 #define BRIDGE_A (0) 00045 /// Bridge B 00046 #define BRIDGE_B (1) 00047 00048 /// Bitmaps for system flags 00049 #define EN_A_set 0x00000001 ///< EN_A pin status 00050 #define HiZstop 0x00000002 ///< motor has to be left in HiZ after stopping 00051 #define busy 0x00000004 ///< stepper position command executing flag 00052 #define running 0x00000008 ///< running motor flag 00053 #define velocitymode 0x00000010 ///< velocity controlled stepper motor 00054 #define positionmode 0x00000020 ///< position controlled stepper motor 00055 #define fullstep 0x00000040 ///< full step mode controlled 00056 #define halfstep 0x00000080 ///< half step mode controlled 00057 #define microstep 0x00000100 ///< micro step mode controlled 00058 #define forward 0x00000200 ///< forward running motor 00059 #define dir2change 0x00000400 ///< direction has to be changed while the motor is running 00060 #define fastdecaymode 0x00000800 ///< decay mode is fast 00061 #define wavestep 0x00001000 ///< wave step mode controlled 00062 00063 /* Variables ----------------------------------------------------------------*/ 00064 /* Number of devices. */ 00065 uint8_t L6208::numberOfDevices = 0; 00066 00067 /// RefMicroTable values are 2^L6208_SINE_WAVEFORM_POWER_OF_TWO_MAX_VALUE*|sin(n/16*PI/2)| 00068 /// where n is the index in the table 00069 const uint16_t L6208::RefMicroTable[L6208_USTEPS_PER_QUARTER_PERIOD*3] = 00070 { 00071 0,3212,6393,9512,12540,15447,18205,20788,23170,25330,27246,28899,30274,31357,32138,32610, 00072 32768,32610,32138,31357,30274,28899,27246,25330,23170,20788,18205,15447,12540,9512,6393,3212, 00073 0,3212,6393,9512,12540,15447,18205,20788,23170,25330,27246,28899,30274,31357,32138,32610 00074 }; 00075 00076 /* Methods -------------------------------------------------------------------*/ 00077 /******************************************************//** 00078 * @brief Start the L6208 library 00079 * @param[in] pInit pointer to the initialization data 00080 * @retval COMPONENT_OK in case of success. 00081 **********************************************************/ 00082 Status_t L6208::L6208_Init(void* pInit) 00083 { 00084 if (pInit == NULL) 00085 { 00086 /* Set context variables to the predefined values from l6208_target_config.h */ 00087 /* Set GPIO according to these values */ 00088 L6208_SetDeviceParamsToPredefinedValues(); 00089 } 00090 else 00091 { 00092 L6208_SetDeviceParamsToGivenValues((l6208_Init_t*) pInit); 00093 } 00094 00095 /* Initialise the PWMs */ 00096 L6208_Board_VrefPwmInit(BRIDGE_A, devicePrm.vrefPwmPeriod); 00097 L6208_Board_VrefPwmInit(BRIDGE_B, devicePrm.vrefPwmPeriod); 00098 00099 /* Initialise the tick */ 00100 L6208_Board_TickInit(); 00101 00102 /* Reset L6208 */ 00103 L6208_ResetDevice(); 00104 00105 /* Align motor mechanical position to driver position */ 00106 L6208_Board_VrefPwmStart(BRIDGE_A, devicePrm.vrefPwmPeriod); 00107 L6208_Board_VrefPwmStart(BRIDGE_B, devicePrm.vrefPwmPeriod); 00108 //L6208_Enable(); 00109 00110 return COMPONENT_OK; 00111 } 00112 00113 /********************************************************** 00114 * @brief Read id 00115 * @param id pointer to the identifier to be read. 00116 * @retval COMPONENT_OK in case of success. 00117 **********************************************************/ 00118 Status_t L6208::L6208_ReadID(uint8_t *id) 00119 { 00120 *id = deviceInstance; 00121 00122 return COMPONENT_OK; 00123 } 00124 00125 /********************************************************** 00126 * @brief Attaches a user callback to the error Handler. 00127 * The call back will be then called each time the library 00128 * detects an error 00129 * @param[in] callback Name of the callback to attach 00130 * to the error Hanlder 00131 * @retval None 00132 **********************************************************/ 00133 void L6208::L6208_AttachErrorHandler(void (*callback)(uint16_t error)) 00134 { 00135 errorHandlerCallback = (void (*)(uint16_t error)) callback; 00136 } 00137 00138 /******************************************************//** 00139 * @brief Disable the power bridges (leave the output bridges HiZ) 00140 * @retval None 00141 **********************************************************/ 00142 void L6208::L6208_Disable(void) 00143 { 00144 L6208_Board_Disable(); 00145 L6208_ClearSysFlag(EN_A_set); 00146 } 00147 00148 /******************************************************//** 00149 * @brief Error handler which calls the user callback (if defined) 00150 * @param[in] error Number of the error 00151 * @retval None 00152 **********************************************************/ 00153 void L6208::L6208_ErrorHandler(uint16_t error) 00154 { 00155 if (errorHandlerCallback != 0) 00156 { 00157 errorHandlerCallback(error); 00158 } 00159 else 00160 { 00161 while(1) 00162 { 00163 /* Infinite loop */ 00164 } 00165 } 00166 } 00167 00168 /******************************************************//** 00169 * @brief Enable the power bridges 00170 * @retval None 00171 **********************************************************/ 00172 void L6208::L6208_Enable(void) 00173 { 00174 L6208_Board_Enable(); 00175 L6208_SetSysFlag(EN_A_set); 00176 } 00177 00178 /******************************************************//** 00179 * @brief Get the stepper acceleration rate 00180 * in step/s^2 for full, half and wave modes 00181 * in microsteps/s^2 for microstep modes 00182 * @retval the stepper acceleration rate in step/s^2 or microstep/s^2 00183 * @note 00184 **********************************************************/ 00185 uint16_t L6208::L6208_GetAcceleration(void) 00186 { 00187 return devicePrm.accelerationSps2; 00188 } 00189 00190 /******************************************************//** 00191 * @brief Get the current speed 00192 * in step/s for full, half and wave modes 00193 * in microsteps/s for microstep modes 00194 * @retval return the current speed in step/s or microstep/s 00195 * @note 00196 **********************************************************/ 00197 uint16_t L6208::L6208_GetCurrentSpeed(void) 00198 { 00199 uint64_t tmp64 = (uint64_t) devicePrm.speedSpt * L6208_Board_TickGetFreq(); 00200 00201 devicePrm.speedSps = (uint16_t)(tmp64 >> 23); 00202 if (devicePrm.speedSps & 0x1) 00203 { 00204 devicePrm.speedSps = (devicePrm.speedSps >> 1) + 1; 00205 } 00206 else 00207 { 00208 devicePrm.speedSps = devicePrm.speedSps >> 1; 00209 } 00210 return devicePrm.speedSps; 00211 } 00212 00213 /******************************************************//** 00214 * @brief Get the motor decay mode 00215 * @retval decay mode 00216 **********************************************************/ 00217 motorDecayMode_t L6208::L6208_GetDecayMode(void) 00218 { 00219 if (L6208_IsSysFlag(fastdecaymode)) return (FAST_DECAY); 00220 else return (SLOW_DECAY); 00221 } 00222 00223 /******************************************************//** 00224 * @brief Get the stepper deceleration rate 00225 * in step/s^2 for full, half and wave modes 00226 * in microsteps/s^2 for microstep modes 00227 * @retval the stepper deceleration rate in step/s^2 or microstep/s^2 00228 * @note 00229 **********************************************************/ 00230 uint16_t L6208::L6208_GetDeceleration(void) 00231 { 00232 return devicePrm.decelerationSps2; 00233 } 00234 00235 /******************************************************//** 00236 * @brief Get the motor current direction 00237 * @retval direction 00238 **********************************************************/ 00239 motorDir_t L6208::L6208_GetDirection(void) 00240 { 00241 if (L6208_IsSysFlag(forward)) 00242 { 00243 return FORWARD; 00244 } 00245 else 00246 { 00247 return BACKWARD; 00248 } 00249 } 00250 00251 /******************************************************//** 00252 * @brief Return the FW version. 00253 * @retval FW version 00254 **********************************************************/ 00255 uint32_t L6208::L6208_GetFwVersion(void) 00256 { 00257 return L6208_FW_VERSION; 00258 } 00259 00260 /******************************************************//** 00261 * @brief Get the mark position (32b signed) 00262 * @retval mark position 00263 **********************************************************/ 00264 int32_t L6208::L6208_GetMark(void) 00265 { 00266 return devicePrm.markPos; 00267 } 00268 00269 /******************************************************//** 00270 * @brief Get the max speed 00271 * in step/s for full, half and wave modes 00272 * in microsteps/s for microstep modes 00273 * @retval return the max speed in step/s or microstep/s 00274 * @note 00275 **********************************************************/ 00276 uint16_t L6208::L6208_GetMaxSpeed(void) 00277 { 00278 return devicePrm.maxSpeedSps; 00279 } 00280 00281 /******************************************************//** 00282 * @brief Get the min speed 00283 * in step/s for full, half and wave modes 00284 * in microsteps/s for microstep modes 00285 * @retval return the min speed in step/s or microstep/s 00286 * @note 00287 **********************************************************/ 00288 uint16_t L6208::L6208_GetMinSpeed(void) 00289 { 00290 return devicePrm.minSpeedSps; 00291 } 00292 00293 /******************************************************//** 00294 * @brief Get the stepper state machine index 00295 * @retval one of the stepper state machine index in the motorState_t enum 00296 **********************************************************/ 00297 motorState_t L6208::L6208_GetMotionState(void) 00298 { 00299 // gets the new stepper state machine index 00300 return devicePrm.motionState; 00301 } 00302 00303 /******************************************************//** 00304 * @brief Get the current position (32b signed) 00305 * @retval current absoulte position 00306 **********************************************************/ 00307 int32_t L6208::L6208_GetPosition(void) 00308 { 00309 return devicePrm.absolutePos; 00310 } 00311 00312 /******************************************************//** 00313 * @brief Get the motor step mode 00314 * @retval step mode 00315 **********************************************************/ 00316 motorStepMode_t L6208::L6208_GetStepMode(void) 00317 { 00318 return devicePrm.stepMode; 00319 } 00320 00321 /******************************************************//** 00322 * @brief Get the selected stop mode 00323 * @retval the selected stop mode 00324 **********************************************************/ 00325 motorStopMode_t L6208::L6208_GetStopMode(void) 00326 { 00327 if (L6208_IsSysFlag(HiZstop) == FALSE) 00328 { 00329 return (HOLD_MODE); 00330 } 00331 else 00332 { 00333 return (HIZ_MODE); 00334 } 00335 } 00336 00337 /******************************************************//** 00338 * @brief Go to the home position 00339 * @retval None 00340 **********************************************************/ 00341 void L6208::L6208_GoHome(void) 00342 { 00343 L6208_GoTo(0); 00344 } 00345 00346 /******************************************************//** 00347 * @brief Go to the Mark position 00348 * @retval None 00349 **********************************************************/ 00350 void L6208::L6208_GoMark(void) 00351 { 00352 L6208_GoTo(devicePrm.markPos); 00353 } 00354 00355 /******************************************************//** 00356 * @brief Move the motor to the absolute position using the shortest path 00357 * @param[in] abs_pos 32 bit signed value position 00358 * @retval None 00359 * @note The position is at the resolution corresponding to the 00360 * selected step mode. 00361 * STEP_MODE_FULL or STEP_MODE_WAVE : step 00362 * STEP_MODE_HALF : 1/2 step 00363 * STEP_MODE_1_4 : 1/4 step 00364 * STEP_MODE_1_8 : 1/8 step 00365 * STEP_MODE_1_16 : 1/16 step 00366 **********************************************************/ 00367 void L6208::L6208_GoTo(int32_t abs_pos) 00368 { 00369 uint32_t steps = 0; 00370 00371 if(L6208_IsSysFlag(running)) 00372 { 00373 L6208_HardStop(); 00374 } 00375 00376 if (abs_pos > devicePrm.absolutePos) 00377 { 00378 steps = abs_pos - devicePrm.absolutePos; 00379 if (steps < (L6208_POSITION_RANGE>>1)) 00380 { 00381 L6208_Move(FORWARD, steps); 00382 } 00383 else 00384 { 00385 L6208_Move(BACKWARD, (L6208_POSITION_RANGE - steps)); 00386 } 00387 } 00388 else 00389 { 00390 steps = devicePrm.absolutePos - abs_pos; 00391 if (steps < (L6208_POSITION_RANGE>>1)) 00392 { 00393 L6208_Move(BACKWARD, steps); 00394 } 00395 else 00396 { 00397 L6208_Move(FORWARD, (L6208_POSITION_RANGE - steps)); 00398 } 00399 } 00400 } 00401 00402 /******************************************************//** 00403 * @brief Move the motor to the absolute position 00404 * @param[in] direction FORWARD or BACKWARD 00405 * @param[in] abs_pos 32 bit signed value position 00406 * @retval None 00407 * @note The position is at the resolution corresponding to the 00408 * selected step mode. 00409 * STEP_MODE_FULL or STEP_MODE_WAVE : step 00410 * STEP_MODE_HALF : 1/2 step 00411 * STEP_MODE_1_4 : 1/4 step 00412 * STEP_MODE_1_8 : 1/8 step 00413 * STEP_MODE_1_16 : 1/16 step 00414 **********************************************************/ 00415 void L6208::L6208_GoToDir(motorDir_t direction, int32_t abs_pos) 00416 { 00417 uint32_t steps = 0; 00418 00419 if(L6208_IsSysFlag(running)) 00420 { 00421 L6208_HardStop(); 00422 } 00423 00424 if (direction != BACKWARD) 00425 { 00426 if (abs_pos > devicePrm.absolutePos) 00427 { 00428 steps = abs_pos - devicePrm.absolutePos; 00429 } 00430 else 00431 { 00432 steps = L6208_POSITION_RANGE + (abs_pos - devicePrm.absolutePos); 00433 } 00434 } 00435 else 00436 { 00437 if (abs_pos > devicePrm.absolutePos) 00438 { 00439 steps = L6208_POSITION_RANGE + (devicePrm.absolutePos - abs_pos); 00440 } 00441 else 00442 { 00443 steps = devicePrm.absolutePos - abs_pos; 00444 } 00445 } 00446 L6208_Move(direction, steps); 00447 } 00448 00449 /******************************************************//** 00450 * @brief Immediately stop the motor and disables the power bridges 00451 * @retval None 00452 **********************************************************/ 00453 void L6208::L6208_HardHiZ(void) 00454 { 00455 /* Disables power stage */ 00456 L6208_Disable(); 00457 00458 /* Sets inactive state */ 00459 L6208_SetMotionState(INACTIVE); 00460 00461 /* Clears the running motor and the position */ 00462 L6208_ClearSysFlag(running); 00463 00464 /* Disables PWMs */ 00465 L6208_Board_VrefPwmStop(BRIDGE_A); 00466 L6208_Board_VrefPwmStop(BRIDGE_B); 00467 00468 /* Disables tick timer */ 00469 L6208_Board_TickStop(); 00470 } 00471 00472 /******************************************************//** 00473 * @brief Immediately stop the motor and keeps holding torque 00474 * @retval None 00475 **********************************************************/ 00476 void L6208::L6208_HardStop(void) 00477 { 00478 /* Sets inactive state */ 00479 L6208_SetMotionState(INACTIVE); 00480 00481 /* Clears the running motor and the position */ 00482 L6208_ClearSysFlag(running); 00483 L6208_VectorCalc(devicePrm.holdTorque); 00484 00485 /* Disables tick timer */ 00486 L6208_Board_TickStop(); 00487 } 00488 00489 /******************************************************//** 00490 * @brief Move the motor by the specified number of steps 00491 * in the specified direction 00492 * @param[in] direction FORWARD or BACKWARD 00493 * @param[in] stepCount 32 bit unsigned step count 00494 * @retval None 00495 * @note The step count resolution is corresponding to the 00496 * selected step mode. 00497 * STEP_MODE_FULL or STEP_MODE_WAVE : step 00498 * STEP_MODE_HALF : 1/2 step 00499 * STEP_MODE_1_4 : 1/4 step 00500 * STEP_MODE_1_8 : 1/8 step 00501 * STEP_MODE_1_16 : 1/16 step 00502 **********************************************************/ 00503 void L6208::L6208_Move(motorDir_t direction, uint32_t stepCount) 00504 { 00505 if(L6208_IsSysFlag(running)) 00506 { 00507 L6208_HardStop(); 00508 } 00509 00510 /* clear the velocity driving mode flag */ 00511 L6208_ClearSysFlag(velocitymode); 00512 00513 /* Set the indexing driving mode flag */ 00514 /* and the user command executing flag */ 00515 L6208_SetSysFlag(positionmode); 00516 00517 /* store relative number of steps to move */ 00518 devicePrm.positionTarget = stepCount; 00519 00520 L6208_SetDirection(direction); 00521 00522 /* Motor activation */ 00523 L6208_StartMovement(); 00524 } 00525 00526 /******************************************************//** 00527 * @brief Release the L6208 reset (Reset pin set to high level) 00528 * @retval None 00529 **********************************************************/ 00530 void L6208::L6208_ReleaseReset(void) 00531 { 00532 L6208_Board_ReleaseReset(); 00533 } 00534 00535 /******************************************************//** 00536 * @brief Reset the L6208 (Reset pin set to low level) 00537 * @retval None 00538 **********************************************************/ 00539 void L6208::L6208_Reset(void) 00540 { 00541 L6208_Board_Reset(); 00542 } 00543 00544 00545 /******************************************************//** 00546 * @brief Call L6208_SetStepMode with current step mode, 00547 * the L6208_SetStepMode function along with setting the step mode resets 00548 * the L6208 device 00549 * @retval None 00550 **********************************************************/ 00551 void L6208::L6208_ResetDevice(void) 00552 { 00553 L6208_SetStepMode(L6208_GetStepMode()); 00554 } 00555 00556 /******************************************************//** 00557 * @brief Run the motor in the specified direction 00558 * according to the speed profile defined by the minimum speed, 00559 * maximum speed, and acceleration parameters. 00560 * The device accelerates from the minimum speed up to the maximum 00561 * speed by using the device acceleration. 00562 * @param[in] direction FORWARD or BACKWARD 00563 * @retval None 00564 **********************************************************/ 00565 void L6208::L6208_Run(motorDir_t direction) 00566 { 00567 if(L6208_IsSysFlag(running)) 00568 { 00569 L6208_HardStop(); 00570 } 00571 L6208_SetDirection(direction); 00572 /* Clear the indexing driving mode flag */ 00573 L6208_ClearSysFlag(positionmode); 00574 /* Set the velocity driving mode flag */ 00575 L6208_SetSysFlag(velocitymode); 00576 /* Motor activation */ 00577 L6208_StartMovement(); 00578 } 00579 00580 /******************************************************//** 00581 * @brief Set the stepper acceleration rate 00582 * in step/s^2 and step/tick^2 for full, half and wave modes 00583 * in microsteps/s^2 and microsteps/tick^2 for microstep modes 00584 * @param[in] newAcc new acceleration rate in step/s^2 or microstep/s^2 00585 * @retval TRUE 00586 * @note 00587 **********************************************************/ 00588 bool L6208::L6208_SetAcceleration(uint16_t newAcc) 00589 { 00590 uint16_t newAccSpt2 = L6208_ConvertAcceDecelRateValue(newAcc); 00591 if (newAccSpt2) 00592 { 00593 devicePrm.accelerationSps2 = newAcc; 00594 devicePrm.accelerationSpt2 = newAccSpt2; 00595 } 00596 else 00597 { 00598 L6208_ErrorHandler(L6208_ERROR_SET_ACCELERATION); 00599 } 00600 return TRUE; 00601 } 00602 00603 /******************************************************//** 00604 * @brief Select the motor decay mode 00605 * @param[in] decayMode (SLOW_DECAY or FAST_DECAY) 00606 * @retval None 00607 **********************************************************/ 00608 void L6208::L6208_SetDecayMode(motorDecayMode_t decayMode) 00609 { 00610 if ((decayMode & L6208_FAST_DECAY_MODE_MASK) == L6208_FAST_DECAY_MODE_MASK) 00611 { 00612 L6208_Board_CONTROL_PIN_Set(); 00613 L6208_SetSysFlag(fastdecaymode); 00614 } 00615 else 00616 { 00617 L6208_Board_CONTROL_PIN_Reset(); 00618 L6208_ClearSysFlag(fastdecaymode); 00619 } 00620 } 00621 00622 /******************************************************//** 00623 * @brief Set the stepper deceleration rate 00624 * in step/s^2 and step/tick^2 for full, half and wave modes 00625 * in microsteps/s^2 and microsteps/tick^2 for microstep modes 00626 * @param[in] newDec new deceleration rate in step/s^2 or microstep/s^2 00627 * @retval TRUE 00628 * @note 00629 **********************************************************/ 00630 bool L6208::L6208_SetDeceleration(uint16_t newDec) 00631 { 00632 uint16_t newDecSpt2 = L6208_ConvertAcceDecelRateValue(newDec); 00633 if (newDecSpt2) 00634 { 00635 devicePrm.decelerationSps2 = newDec; 00636 devicePrm.decelerationSpt2 = newDecSpt2; 00637 } 00638 else 00639 { 00640 L6208_ErrorHandler(L6208_ERROR_SET_DECELERATION); 00641 } 00642 return TRUE; 00643 } 00644 00645 /******************************************************//** 00646 * @brief Specify the direction 00647 * @param[in] dir FORWARD or BACKWARD 00648 * @note In velocity mode a direction change forces the device to stop and 00649 * then run in the new direction. In position mode, if the device is 00650 * running, a direction change will generate an error. 00651 * @retval None 00652 **********************************************************/ 00653 void L6208::L6208_SetDirection(motorDir_t dir) 00654 { 00655 L6208_ClearSysFlag(dir2change); 00656 if (dir == FORWARD) 00657 { 00658 if (!L6208_IsSysFlag(forward)) 00659 { 00660 if (L6208_IsSysFlag(running)) 00661 { 00662 /* motor is running */ 00663 if (L6208_IsSysFlag(positionmode)) 00664 { 00665 L6208_ErrorHandler(L6208_ERROR_SET_DIRECTION); 00666 } 00667 else 00668 { 00669 /* set the rotation direction to change flag */ 00670 L6208_SetSysFlag(dir2change); 00671 } 00672 } 00673 else /* the motor is stopped, cw direction selected */ 00674 { 00675 L6208_SetSysFlag(forward); 00676 L6208_Board_DIR_PIN_Set(); 00677 } 00678 } 00679 } 00680 else 00681 { 00682 if (L6208_IsSysFlag(forward)) 00683 { 00684 if (L6208_IsSysFlag(running)) 00685 { 00686 /* motor is running */ 00687 if (L6208_IsSysFlag(positionmode)) 00688 { 00689 L6208_ErrorHandler(L6208_ERROR_SET_DIRECTION); 00690 } 00691 else 00692 { 00693 /* set the rotation direction to change flag */ 00694 L6208_SetSysFlag(dir2change); 00695 } 00696 } 00697 else /* the motor is stopped, ccw direction selected */ 00698 { 00699 L6208_ClearSysFlag(forward); 00700 L6208_Board_DIR_PIN_Reset(); 00701 } 00702 } 00703 } 00704 if(L6208_IsSysFlag(dir2change)) 00705 { 00706 L6208_VectorCalc(devicePrm.decelTorque); 00707 L6208_SetMotionState(DECELERATINGTOSTOP); 00708 } 00709 } 00710 00711 /******************************************************//** 00712 * @brief Set current position to be the home position 00713 * @retval None 00714 **********************************************************/ 00715 void L6208::L6208_SetHome(void) 00716 { 00717 if (!L6208_IsSysFlag(running)) 00718 { 00719 devicePrm.absolutePos = 0; 00720 } 00721 else 00722 { 00723 L6208_ErrorHandler(L6208_ERROR_SET_HOME); 00724 } 00725 } 00726 00727 /******************************************************//** 00728 * @brief Set current position to be the mark position 00729 * @retval None 00730 **********************************************************/ 00731 void L6208::L6208_SetMark(void) 00732 { 00733 devicePrm.markPos = devicePrm.absolutePos; 00734 } 00735 00736 /******************************************************//** 00737 * @brief Set the user selected maximum speed 00738 * in step/s and step/tick for full, half and wave modes 00739 * in microsteps/s and microsteps/tick for microstep modes 00740 * @param[in] newSpeed speed value (step/s or microstep/s) 00741 * @retval TRUE 00742 * @note One microstep is 1/16 step 00743 **********************************************************/ 00744 bool L6208::L6208_SetMaxSpeed(uint16_t newSpeed) 00745 { 00746 if (L6208_SetSpeed(newSpeed, &devicePrm.maxSpeedSpt)) 00747 { 00748 devicePrm.maxSpeedSps = newSpeed; 00749 } 00750 else 00751 { 00752 L6208_ErrorHandler(L6208_ERROR_SET_MAX_SPEED); 00753 } 00754 return TRUE; 00755 } 00756 00757 /******************************************************//** 00758 * @brief Set the user selected minimum speed 00759 * in step/s and step/tick for full, half and wave modes 00760 * in microsteps/s and microsteps/tick for microstep modes 00761 * @param[in] newSpeed speed value (step/s or microstep/s) 00762 * @retval TRUE 00763 * @note One microstep is 1/16 step 00764 **********************************************************/ 00765 bool L6208::L6208_SetMinSpeed(uint16_t newSpeed) 00766 { 00767 if (L6208_SetSpeed(newSpeed, &devicePrm.minSpeedSpt)) 00768 { 00769 devicePrm.minSpeedSps = newSpeed; 00770 } 00771 else 00772 { 00773 L6208_ErrorHandler(L6208_ERROR_SET_MIN_SPEED); 00774 } 00775 return TRUE; 00776 } 00777 00778 /******************************************************//** 00779 * @brief Set the step mode 00780 * @param[in] stepMode 00781 * @retval true if the command is successfully executed, else false 00782 * @note Every time the step mode is changed, the step state machine is reset 00783 **********************************************************/ 00784 bool L6208::L6208_SetStepMode(motorStepMode_t stepMode) 00785 { 00786 devicePrm.stepMode = stepMode; 00787 L6208_ClearSysFlag(fullstep | halfstep | microstep | wavestep); 00788 switch (stepMode) 00789 { 00790 case STEP_MODE_HALF: 00791 /* Set the Half/Full pin low and Reset and the set the Half/Full pin high*/ 00792 L6208_Board_HALF_FULL_PIN_Reset(); 00793 L6208_Board_Reset(); 00794 L6208_Board_HALF_FULL_PIN_Set(); 00795 /* Set system flag */ 00796 L6208_SetSysFlag(halfstep); 00797 break; 00798 case STEP_MODE_FULL: 00799 /* Set the Half/Full pin low and Reset */ 00800 L6208_Board_HALF_FULL_PIN_Reset(); 00801 L6208_Board_Reset(); 00802 /* Set system flag */ 00803 L6208_SetSysFlag(fullstep); 00804 break; 00805 case STEP_MODE_WAVE: 00806 /* Set the Half/Full pin low and Reset and the set the Half/Full pin high*/ 00807 L6208_Board_CLOCK_PIN_Reset(); 00808 L6208_Board_HALF_FULL_PIN_Reset(); 00809 L6208_Board_Reset(); 00810 L6208_Board_CLOCK_PIN_Set(); 00811 L6208_Board_HALF_FULL_PIN_Set(); 00812 L6208_Board_Delay(2); 00813 L6208_Board_CLOCK_PIN_Reset(); 00814 L6208_Board_Delay(2); 00815 L6208_Board_HALF_FULL_PIN_Reset(); 00816 /* Set system flag */ 00817 L6208_SetSysFlag(wavestep); 00818 break; 00819 case STEP_MODE_1_4: 00820 /* Set the Half/Full pin low and Reset */ 00821 L6208_Board_HALF_FULL_PIN_Reset(); 00822 L6208_Board_Reset(); 00823 /* Set system flag */ 00824 L6208_SetSysFlag(microstep); 00825 devicePrm.uStepInc = 4; 00826 break; 00827 case STEP_MODE_1_8: 00828 /* Set the Half/Full pin low and Reset */ 00829 L6208_Board_HALF_FULL_PIN_Reset(); 00830 L6208_Board_Reset(); 00831 /* Set system flag */ 00832 L6208_SetSysFlag(microstep); 00833 devicePrm.uStepInc = 2; 00834 break; 00835 case STEP_MODE_1_16: 00836 /* Set the Half/Full pin low and Reset */ 00837 L6208_Board_HALF_FULL_PIN_Reset(); 00838 L6208_Board_Reset(); 00839 /* Set system flag */ 00840 L6208_SetSysFlag(microstep); 00841 devicePrm.uStepInc = 1; 00842 break; 00843 default: 00844 return FALSE; 00845 } 00846 L6208_Board_Delay(2); 00847 L6208_Board_ReleaseReset(); 00848 L6208_ResetSteps(); 00849 return TRUE; 00850 } 00851 00852 /******************************************************//** 00853 * @brief Select the mode to stop the motor. When the motor 00854 * is stopped, if autoHiZ is TRUE, the power bridges are disabled 00855 * if autoHiZ is FALSE, the power bridges are kept enabled. 00856 * @param[in] stopMode HOLD_MODE to let power bridge enabled 00857 * @retval None 00858 **********************************************************/ 00859 void L6208::L6208_SetStopMode(motorStopMode_t stopMode) 00860 { 00861 if (stopMode == HOLD_MODE) 00862 { 00863 L6208_ClearSysFlag(HiZstop); 00864 } 00865 else 00866 { 00867 L6208_SetSysFlag(HiZstop); 00868 } 00869 } 00870 00871 /******************************************************//** 00872 * @brief Stop the motor by using the device deceleration and set deceleration torque 00873 * @retval true if the command is successfully executed, else false 00874 * @note . 00875 **********************************************************/ 00876 bool L6208::L6208_SoftStop(void) 00877 { 00878 L6208_VectorCalc(devicePrm.decelTorque); 00879 L6208_SetMotionState(DECELERATINGTOSTOP); 00880 return TRUE; 00881 } 00882 00883 /******************************************************//** 00884 * @brief Handle the device state machine at each tick timer pulse end. 00885 * @retval None 00886 **********************************************************/ 00887 void L6208::L6208_TickHandler(void) 00888 { 00889 uint32_t locMaxSpeedSpt = devicePrm.maxSpeedSpt; 00890 uint32_t locMinSpeedSpt = devicePrm.minSpeedSpt; 00891 00892 /* Update state, target speed, acceleration and deceleration rates */ 00893 L6208_Board_CLOCK_PIN_Reset(); 00894 00895 switch(L6208_GetMotionState()) 00896 { 00897 /* ============ Velocity control mode states ======================== */ 00898 case ACCELERATING: 00899 /* velocity mode: acceleration phase */ 00900 /* Increase Speed and update position */ 00901 L6208_DoAccel(); 00902 if(locMaxSpeedSpt < devicePrm.speedSpt) 00903 { 00904 /*Target speed reached */ 00905 devicePrm.speedSpt = locMaxSpeedSpt; 00906 L6208_VectorCalc(devicePrm.runTorque); 00907 L6208_SetMotionState(STEADY); 00908 } 00909 break; 00910 case STEADY: 00911 /* velocity mode: constant speed phase */ 00912 /* Update position */ 00913 L6208_DoRun(); 00914 if(locMaxSpeedSpt != devicePrm.speedSpt) 00915 { 00916 /* targeted speed has changed */ 00917 if(locMaxSpeedSpt< devicePrm.speedSpt) 00918 { 00919 /* Slow down the motor */ 00920 L6208_VectorCalc(devicePrm.decelTorque); 00921 L6208_SetMotionState(DECELERATING); 00922 } 00923 else 00924 { 00925 /* speed up the motor */ 00926 L6208_VectorCalc(devicePrm.accelTorque); 00927 L6208_SetMotionState(ACCELERATING); 00928 } 00929 } 00930 break; 00931 case DECELERATING: 00932 /* velocity mode: running motor deceleration phase */ 00933 /* Decrease Speed and update position */ 00934 L6208_DoDecel(); 00935 if(locMaxSpeedSpt > devicePrm.speedSpt) 00936 { 00937 /*Target speed reached but motor has still to be run*/ 00938 devicePrm.speedSpt = locMaxSpeedSpt; 00939 L6208_VectorCalc(devicePrm.runTorque); 00940 L6208_SetMotionState(STEADY); 00941 } 00942 break; 00943 case DECELERATINGTOSTOP: 00944 /* velocity mode: decelerate to stopped phase */ 00945 /* Decrease current speed */ 00946 L6208_DoDecel(); 00947 if(devicePrm.speedSpt == locMinSpeedSpt) 00948 { 00949 if (L6208_IsSysFlag(dir2change)) 00950 { 00951 L6208_ClearSysFlag(running); 00952 /* Change direction */ 00953 if (L6208_IsSysFlag(forward)) 00954 { 00955 /* switch to reverse rotation */ 00956 L6208_SetDirection(BACKWARD); 00957 } 00958 else 00959 { 00960 /* switch to forward rotation */ 00961 L6208_SetDirection(FORWARD); 00962 } 00963 L6208_SetSysFlag(running); 00964 L6208_SetMotionState(ACCELERATING); 00965 /* Set VRefA and VRefB to the selected acceleration torque */ 00966 L6208_VectorCalc(devicePrm.accelTorque); 00967 } 00968 else 00969 { 00970 if (L6208_IsSysFlag(HiZstop)) 00971 { 00972 L6208_HardHiZ(); 00973 } 00974 else 00975 { 00976 L6208_HardStop(); 00977 } 00978 } 00979 } 00980 break; 00981 00982 /* ============ Position (indexed) control mode states ======================== */ 00983 00984 case INDEX_ACCEL: 00985 /* position mode: acceleration state*/ 00986 00987 /* Increase Speed and update position */ 00988 L6208_DoAccel(); 00989 00990 if(devicePrm.positionTarget1 <= devicePrm.step) 00991 { 00992 /* End of acceleration phase */ 00993 L6208_VectorCalc(devicePrm.runTorque); 00994 L6208_SetMotionState(INDEX_RUN); 00995 } 00996 break; 00997 00998 case INDEX_RUN: 00999 /* position mode: constant speed phase */ 01000 01001 /* Update position */ 01002 L6208_DoRun(); 01003 01004 if(devicePrm.positionTarget2 <= devicePrm.step) 01005 { 01006 /* reach position targeted for constant speed */ 01007 L6208_VectorCalc(devicePrm.decelTorque); 01008 L6208_SetMotionState(INDEX_DECEL); 01009 } 01010 break; 01011 01012 case INDEX_DECEL: 01013 /* position mode: deceleration phase */ 01014 01015 /* Decrease Speed and update position */ 01016 L6208_DoDecel(); 01017 01018 if(devicePrm.positionTarget3 <= devicePrm.step) 01019 { 01020 /* reach position targeted for deceleration phase */ 01021 /* the motor terminated its run */ 01022 /* the torque will be the deceleration one */ 01023 devicePrm.step = devicePrm.positionTarget3; 01024 L6208_SetMotionState(INDEX_DWELL); 01025 } 01026 break; 01027 01028 case INDEX_DWELL: 01029 /* position mode: dwelling state */ 01030 if(devicePrm.dwellCounter > 0) 01031 { 01032 /* decrease the dwelling wait tick counter */ 01033 devicePrm.dwellCounter--; 01034 } 01035 if(devicePrm.dwellCounter == 0) 01036 { 01037 /* dwelling wait time is elapsed */ 01038 /* so stop the motor */ 01039 if (L6208_IsSysFlag(HiZstop)) 01040 { 01041 L6208_HardHiZ(); 01042 } 01043 else 01044 { 01045 L6208_HardStop(); 01046 } 01047 } 01048 break; 01049 01050 /* ============ stopped state ======================== */ 01051 case INACTIVE: 01052 { 01053 if(L6208_IsSysFlag(running)) 01054 { 01055 /* clear the user move command executing */ 01056 /* and the motor running flags */ 01057 L6208_ClearSysFlag(running); 01058 } 01059 break; 01060 } 01061 default: 01062 break; 01063 } /* switch(L6208_GetMotionState()) */ 01064 if(L6208_GetMotionState() != INACTIVE) 01065 { 01066 if (L6208_IsSysFlag(microstep)) 01067 { 01068 /* Microstep handling */ 01069 switch(devicePrm.uStepInc) 01070 { 01071 default: 01072 case 1: 01073 /* 1 microstep increment */ 01074 devicePrm.lsbTicks = (uint8_t)(devicePrm.ticks>>16); 01075 break; 01076 01077 case 2: 01078 /* 2 microsteps increment */ 01079 devicePrm.lsbTicks = (uint8_t)(devicePrm.ticks>>17); 01080 break; 01081 01082 case 4: 01083 /* 4 microsteps increment */ 01084 devicePrm.lsbTicks = (uint8_t)(devicePrm.ticks>>18); 01085 break; 01086 } 01087 devicePrm.lsbTicks &= 0x01; 01088 if(devicePrm.lsbOldUSteppingTicks != devicePrm.lsbTicks) 01089 { 01090 /* waveform sample to update */ 01091 devicePrm.lsbOldUSteppingTicks = devicePrm.lsbTicks; 01092 devicePrm.step++; 01093 if(L6208_IsSysFlag(forward)) 01094 { 01095 /* the motor is going forward */ 01096 devicePrm.absolutePos++; 01097 /* Reset the absolute motor position in step/microsteps */ 01098 /* Get next microstep sample */ 01099 devicePrm.uStepSample += devicePrm.uStepInc; 01100 if(devicePrm.uStepSample > 31) 01101 { 01102 devicePrm.uStepSample = 0; 01103 } 01104 } 01105 else 01106 { 01107 /* the motor is going backward */ 01108 devicePrm.absolutePos--; 01109 if(devicePrm.uStepSample >= devicePrm.uStepInc) 01110 { 01111 /* Get previous microstep sample */ 01112 devicePrm.uStepSample -= devicePrm.uStepInc; 01113 } 01114 else 01115 { 01116 devicePrm.uStepSample = 32 - devicePrm.uStepInc; 01117 } 01118 } 01119 /* set the PWM to update VRefs */ 01120 L6208_VrefPwmComputePulseWidth(BRIDGE_A, pMicroTable2[devicePrm.uStepSample], FALSE); 01121 L6208_VrefPwmComputePulseWidth(BRIDGE_B, microTable1[devicePrm.uStepSample], FALSE); 01122 if(devicePrm.uStepsample2update > 0) 01123 { 01124 /* the waveform samples table has been recalculated 01125 so update the waveform scanning table */ 01126 L6208_UpdateScanWaveformTable(); 01127 devicePrm.uStepsample2update = 0; 01128 } 01129 } 01130 /* Microstep: use the bit4 toggling as step clock */ 01131 /* this bit is used because there are 16 microstep samples per quarter period */ 01132 devicePrm.lsbTicks = (uint8_t)((devicePrm.uStepSample>>4) & 0x01); 01133 if(devicePrm.lsbOldTicks != devicePrm.lsbTicks) 01134 { 01135 /* the selected bit status changed ==> get the next motor step 01136 save the current masked motor tick position for step setting scope ... */ 01137 devicePrm.lsbOldTicks = devicePrm.lsbTicks; 01138 L6208_Board_CLOCK_PIN_Set(); 01139 } 01140 } 01141 else 01142 { 01143 /* Full and half step handling code */ 01144 if(!L6208_IsSysFlag(halfstep)) 01145 { 01146 /* Full step: use the bit 16 toggling as step clock */ 01147 devicePrm.lsbTicks = (uint8_t)((devicePrm.ticks>>16) & 0x00000001); 01148 } 01149 else 01150 { 01151 /* half step: use the bit 15 toggling as step clock */ 01152 devicePrm.lsbTicks = (uint8_t)((devicePrm.ticks>>15) & 0x00000001); 01153 } 01154 if(devicePrm.lsbOldTicks != devicePrm.lsbTicks) 01155 { 01156 /* the selected bit status changed ==> get the next motor step */ 01157 devicePrm.step++; 01158 if(L6208_IsSysFlag(forward)) 01159 { 01160 /* the motor is going forward */ 01161 devicePrm.absolutePos++; 01162 } 01163 else 01164 { 01165 /* the motor is going backward */ 01166 devicePrm.absolutePos--; 01167 } 01168 /* save the current masked motor tick position for step setting scope ... */ 01169 devicePrm.lsbOldTicks = devicePrm.lsbTicks; 01170 L6208_Board_CLOCK_PIN_Set(); 01171 } 01172 } 01173 } 01174 L6208_UstepWaveformHandling(); 01175 L6208_VrefPwmUpdatePulseWidth(); 01176 } 01177 01178 /******************************************************//** 01179 * @brief Get the frequency of VREFA and VREFB PWM 01180 * @retval the frequency of VREFA and VREFB PWM in Hz 01181 * @note 01182 **********************************************************/ 01183 uint32_t L6208::L6208_VrefPwmGetFreq(void) 01184 { 01185 return devicePrm.vrefPwmFreq; 01186 } 01187 01188 /******************************************************//** 01189 * @brief Set the frequency of the VREFA and VREFB PWM 01190 * @param[in] newFreq in Hz 01191 * @retval None 01192 * @note 01193 **********************************************************/ 01194 void L6208::L6208_VrefPwmSetFreq(uint32_t newFreq) 01195 { 01196 devicePrm.vrefPwmFreq = newFreq; 01197 /* Compute the pwm period in 1/256th of a microsecond */ 01198 devicePrm.vrefPwmPeriod = (uint16_t)((1000000<<8)/newFreq); 01199 /* Re-Initialise the PWMs -----------------------------------------------------*/ 01200 L6208_Board_VrefPwmInit(BRIDGE_A, devicePrm.vrefPwmPeriod); 01201 L6208_Board_VrefPwmInit(BRIDGE_B, devicePrm.vrefPwmPeriod); 01202 /* Recompute the waveform samples according to the new PWM frequency */ 01203 L6208_ScaleWaveformTable(); 01204 /* Update the waveform scanning table */ 01205 L6208_UpdateScanWaveformTable(); 01206 if (L6208_IsSysFlag(running)) 01207 { 01208 L6208_Board_VrefPwmStart(BRIDGE_A, devicePrm.vrefPwmPeriod); 01209 L6208_Board_VrefPwmStart(BRIDGE_B, devicePrm.vrefPwmPeriod); 01210 } 01211 } 01212 01213 /******************************************************//** 01214 * @brief Lock while motor is running 01215 * @retval None 01216 **********************************************************/ 01217 void L6208::L6208_WaitWhileActive(void) 01218 { 01219 /* Wait while motor is running */ 01220 while (L6208_IsSysFlag(running)); 01221 } 01222 01223 /* ------------------------------------------------------------------------- */ 01224 /* Private functions ------------------------------------------------------- */ 01225 /* ------------------------------------------------------------------------- */ 01226 /******************************************************//** 01227 * @brief Clear the bit/s of flags according to the specified mask 01228 * @param[in] mask flag bit mask 01229 * @retval None 01230 **********************************************************/ 01231 inline void L6208::L6208_ClearSysFlag(uint32_t mask) 01232 { 01233 devicePrm.flags &= ~mask; 01234 } 01235 01236 /******************************************************//** 01237 * @brief Compute the number of steps at the end of the accereration/deceleration phase 01238 * P = position in steps at the end of the acceleration/deceleration phase 01239 * T = acceleration/deceleration time in seconds 01240 * A = acceleration/deceleration rate in steps per second per second (steps/sec^2) 01241 * V = peak velocity during acceleration/deceleration phase 01242 * V1 = average velocity during acceleration/deceleration phase 01243 * T = V/A 01244 * V1 = V/2 01245 * P = V1*T 01246 * P = V^2/2A 01247 * @param accOrDecRate acceleration/deceleration rate in steps per second per second (steps/sec^2) 01248 * @retval end position or 0xFFFFFFFF on error 01249 **********************************************************/ 01250 uint32_t L6208::L6208_ComputeNbAccOrDecSteps(uint16_t accOrDecRate) 01251 { 01252 uint32_t nbAccOrDecSteps; 01253 uint32_t locMaxSpeedSps = (uint32_t)devicePrm.maxSpeedSps; 01254 01255 if (L6208_IsSysFlag(microstep)) 01256 { 01257 switch(devicePrm.uStepInc) 01258 { 01259 case 1: 01260 locMaxSpeedSps = (uint32_t)devicePrm.maxSpeedSps; 01261 break; 01262 case 2: 01263 locMaxSpeedSps = ((uint32_t)devicePrm.maxSpeedSps)>>1; 01264 accOrDecRate >>= 1; 01265 break; 01266 case 4: 01267 locMaxSpeedSps = ((uint32_t)devicePrm.maxSpeedSps)>>2; 01268 accOrDecRate >>= 2; 01269 break; 01270 default: 01271 break; 01272 } 01273 } 01274 else if (L6208_IsSysFlag(halfstep)) 01275 { 01276 locMaxSpeedSps = ((uint32_t)devicePrm.maxSpeedSps)<<1; 01277 accOrDecRate <<= 1; 01278 } 01279 01280 if(accOrDecRate == 0) 01281 { 01282 /* division by 0 error */ 01283 return 0xFFFFFFFF; 01284 } 01285 nbAccOrDecSteps = locMaxSpeedSps * locMaxSpeedSps; 01286 nbAccOrDecSteps /= (uint32_t)accOrDecRate; 01287 nbAccOrDecSteps /= 2; 01288 01289 return nbAccOrDecSteps; 01290 } 01291 01292 /******************************************************//** 01293 * @brief Compute the acceleration/deceleration speed increment value 01294 * @param[in] newAccOrDecRate acceleration or deceleration value (steps/s^2) greater or equal than 24 01295 * @retval the speed (step/tick) increment value 01296 * LSB = 2^-24 step/tick^2 or 2^-20 microstep/tick^2 01297 * @note return 0 if the rate is too low or if the tick frequency is too small 01298 * or if the device is running in position mode 01299 **********************************************************/ 01300 uint16_t L6208::L6208_ConvertAcceDecelRateValue(uint16_t newAccOrDecRate) 01301 { 01302 uint64_t tmp64; 01303 uint32_t tmp32; 01304 01305 if (((L6208_IsSysFlag(running))&&(L6208_IsSysFlag(positionmode)))||\ 01306 (newAccOrDecRate < L6208_MIN_ACC_DEC_RATE)) 01307 { 01308 return 0; 01309 } 01310 /* Compute (tick frequency)^2 */ 01311 tmp32 = (uint32_t)L6208_Board_TickGetFreq(); 01312 tmp32 *= tmp32; 01313 /* Return 0 if the (tick frequency)^2 is too small */ 01314 if ( tmp32 < (uint32_t)newAccOrDecRate ) 01315 { 01316 return 0; 01317 } 01318 /* Compute the decimal number of microstep or step per tick^2 */ 01319 /* Decimal part is on 32 bits */ 01320 tmp64 = (uint64_t)newAccOrDecRate << 32; 01321 tmp64 /= ((uint64_t)tmp32); 01322 01323 return (uint16_t)((tmp64 & 0x00000000FFFFFFFF)>>8); 01324 } 01325 01326 /******************************************************//** 01327 * @brief Compute next position and speed according to the acceleration rate 01328 * @retval None 01329 **********************************************************/ 01330 void L6208::L6208_DoAccel(void) 01331 { 01332 /* Increase speed by acceleration rate */ 01333 uint32_t locAccelerationSpt2 = (uint32_t)devicePrm.accelerationSpt2; 01334 uint32_t locMinSpeedSpt = devicePrm.minSpeedSpt; 01335 if ((devicePrm.speedSpt + locAccelerationSpt2) < locMinSpeedSpt) 01336 { 01337 devicePrm.speedSpt = locMinSpeedSpt; 01338 } 01339 else 01340 { 01341 devicePrm.speedSpt += locAccelerationSpt2; 01342 } 01343 /* Compute next position */ 01344 L6208_DoRun(); 01345 } 01346 01347 /******************************************************//** 01348 * @brief Compute next position and speed according to the deceleration rate 01349 * @retval None 01350 **********************************************************/ 01351 void L6208::L6208_DoDecel(void) 01352 { 01353 /* Decrease current speed by deceleration rate */ 01354 uint32_t locDecelerationSpt2 = (uint32_t)devicePrm.decelerationSpt2; 01355 uint32_t locMinSpeedSpt = devicePrm.minSpeedSpt; 01356 if((devicePrm.speedSpt - locMinSpeedSpt) > (uint32_t)locDecelerationSpt2) 01357 { 01358 devicePrm.speedSpt -= (uint32_t)locDecelerationSpt2; 01359 } 01360 else 01361 { 01362 /* Set minimum speed */ 01363 devicePrm.speedSpt = locMinSpeedSpt; 01364 } 01365 /* Compute next position */ 01366 L6208_DoRun(); 01367 } 01368 01369 /******************************************************//** 01370 * @brief Compute next position by adding current speed 01371 * @retval None 01372 **********************************************************/ 01373 void L6208::L6208_DoRun(void) 01374 { 01375 devicePrm.ticks += (devicePrm.speedSpt >> 8) & 0x0000FFFF; 01376 } 01377 01378 /******************************************************//** 01379 * @brief Get number of samples to rescale 01380 * @retval uStepsample2scale the number of micro stepping waveform samples to rescale 01381 **********************************************************/ 01382 uint8_t L6208::L6208_GetMicrostepSample2Scale(void) 01383 { 01384 return devicePrm.uStepsample2scale; 01385 } 01386 01387 /******************************************************//** 01388 * @brief Initialize the system for position mode motor moving command 01389 * P = total move distance in steps 01390 * P1 = steps required to accel from 0 to V 01391 * P2 = steps required to decel from V to 0 01392 * V = peak velocity in steps per second (steps/sec) 01393 * V1 = average velocity during accel or decel* 01394 * A = required accel rate in steps per second per second (steps/sec2) 01395 * D = required decel rate in steps per second per second (steps/sec2) 01396 * T1 = acceleration time in seconds 01397 * T2 = deceleration time in seconds* 01398 * 01399 * 1) T1 = V / A 01400 * 2) V1 = V / 2 01401 * 3) P1 = V1 T1 01402 * Substituting 1 and 2 into 3 yields: 01403 * 4) P1 = V2 / 2A 01404 * In the same manner we have: 01405 * 5) P2 = V2 / 2D 01406 * 01407 * P1 = PD/(D+A) 01408 * 01409 * \sa Application Note: AN2044 01410 * @retval None 01411 **********************************************************/ 01412 void L6208::L6208_Indexmodeinit(void) 01413 { 01414 uint32_t tmpVal0; 01415 uint32_t tmpVal1; 01416 uint32_t locAccelSteps; 01417 uint32_t locDecSteps; 01418 01419 /* calculate the number of steps to get the running speed */ 01420 locAccelSteps = L6208_ComputeNbAccOrDecSteps(devicePrm.accelerationSps2); 01421 /* calculate the number of steps to get the motor stopped */ 01422 locDecSteps = L6208_ComputeNbAccOrDecSteps(devicePrm.decelerationSps2); 01423 if(( locAccelSteps + locDecSteps ) > devicePrm.positionTarget) 01424 { 01425 /* Triangular move needed */ 01426 /* accelsteps = P1 = PD/(D+A) */ 01427 tmpVal0 = devicePrm.positionTarget * devicePrm.decelerationSps2; 01428 tmpVal1 = (uint32_t)devicePrm.decelerationSps2; 01429 tmpVal1 += (uint32_t)devicePrm.accelerationSps2; 01430 locAccelSteps = tmpVal0 / tmpVal1; 01431 devicePrm.positionTarget1 = locAccelSteps; 01432 devicePrm.positionTarget2 = devicePrm.positionTarget1 + 1; 01433 devicePrm.positionTarget3 = devicePrm.positionTarget; 01434 if(devicePrm.positionTarget1 == 0) 01435 { 01436 devicePrm.positionTarget1 = 1; 01437 } 01438 } 01439 else 01440 { 01441 /* trapezoidal move needed */ 01442 /* P1 = V^2/2A */ 01443 /* P2 = P - V^2/2D */ 01444 devicePrm.positionTarget1 = locAccelSteps; 01445 devicePrm.positionTarget2 = devicePrm.positionTarget - locDecSteps; 01446 devicePrm.positionTarget3 = devicePrm.positionTarget; 01447 } 01448 L6208_SetMotionState(INDEX_ACCEL); 01449 } 01450 01451 /******************************************************//** 01452 * @brief Check the bit/s of flags according to the specified mask 01453 * @param[in] mask flag bit mask 01454 * @retval TRUE if the bit of the mask are set 01455 **********************************************************/ 01456 inline bool L6208::L6208_IsSysFlag(uint32_t mask) 01457 { 01458 return (bool)((devicePrm.flags & mask) == mask); 01459 } 01460 01461 /******************************************************//** 01462 * @brief Stepper driver device step state reset subroutine 01463 * @retval None 01464 **********************************************************/ 01465 void L6208::L6208_ResetSteps(void) 01466 { 01467 devicePrm.speedSpt = 0; // reset the current speed value 01468 devicePrm.ticks = 0; // reset the current ticks counter value 01469 devicePrm.step = 0; // reset the current step counter value 01470 devicePrm.lsbOldTicks = 0; // reset copy of the previous position (tick) 01471 devicePrm.lsbOldUSteppingTicks = 0; // reset copy of the previous position (tick) ( micro stepping ) 01472 devicePrm.lsbTicks = 0; // reset copy of the current position (tick) 01473 devicePrm.absolutePos = 0; // reset the absolute motor position in step/microsteps 01474 devicePrm.uStepSample = 0; // reset the microstepping waveform sample index 01475 } 01476 01477 /******************************************************//** 01478 * @brief Compute the specified micro stepping waveform sample with the 01479 * current selected torque and pwm period 01480 * @param[in] sampleIndex sample Index 01481 * @retval scaled sample value 01482 **********************************************************/ 01483 uint32_t L6208::L6208_ScaleWaveformSample(uint8_t sampleIndex) 01484 { 01485 uint32_t sample; 01486 01487 sample = (uint32_t)RefMicroTable[sampleIndex]; 01488 sample *= devicePrm.vrefPwmPeriod; 01489 sample >>= (uint32_t)L6208_SINE_WAVEFORM_POWER_OF_TWO_MAX_VALUE; 01490 01491 sample *= (uint32_t)devicePrm.curTorqueScaler; // torque val (%) 01492 sample /= (uint32_t)100; 01493 01494 return sample; 01495 } 01496 01497 /******************************************************//** 01498 * @brief Compute the micro stepping waveform sample table samples with the 01499 * current selected torque and pwm period 01500 * @retval None 01501 **********************************************************/ 01502 void L6208::L6208_ScaleWaveformTable(void) 01503 { 01504 uint8_t index; 01505 for(index=0; index<=L6208_USTEPS_PER_QUARTER_PERIOD; index++) 01506 { 01507 /* Calculate the scaled sample and save its value into the waveform to update table */ 01508 updatedMicroTable[index] = (uint16_t)L6208_ScaleWaveformSample(index); 01509 } 01510 } 01511 01512 /******************************************************//** 01513 * @brief Set the parameters of the device to values of the structure pointed 01514 * by pInitDevicePrm. Set GPIO according to these values. 01515 * @param pInitDevicePrm pointer onto the structure containing values to 01516 * initialize the device parameters. 01517 * @retval None 01518 **********************************************************/ 01519 void L6208::L6208_SetDeviceParamsToGivenValues(l6208_Init_t* pInitDevicePrm) 01520 { 01521 memset(&devicePrm, 0, sizeof(devicePrm)); 01522 L6208_SetAcceleration(pInitDevicePrm->accelerationSps2); 01523 L6208_SetDeceleration(pInitDevicePrm->decelerationSps2); 01524 L6208_SetMaxSpeed(pInitDevicePrm->maxSpeedSps); 01525 L6208_SetMinSpeed(L6208_MIN_SPEED); 01526 devicePrm.accelTorque = pInitDevicePrm->accelTorque; 01527 devicePrm.decelTorque = pInitDevicePrm->decelTorque; 01528 devicePrm.runTorque = pInitDevicePrm->runTorque; 01529 devicePrm.holdTorque = pInitDevicePrm->holdTorque; 01530 /* Only once acceleration, deceleration, min speed and max speed have been */ 01531 /* initialized, set the step mode */ 01532 devicePrm.stepMode = pInitDevicePrm->stepMode; 01533 L6208_SetDecayMode(pInitDevicePrm->decayMode); 01534 devicePrm.moveDwellTime = pInitDevicePrm->moveDwellTime; 01535 if (L6208_CONF_PARAM_AUTO_HIZ_STOP) L6208_SetSysFlag(pInitDevicePrm->autoHiZstop); 01536 devicePrm.vrefPwmFreq = pInitDevicePrm->vrefPwmFreq; 01537 devicePrm.vrefPwmPeriod = (uint16_t)((1000000<<8)/pInitDevicePrm->vrefPwmFreq); 01538 /* Initialize current stepper state machine index */ 01539 L6208_SetMotionState(INACTIVE); 01540 } 01541 01542 /******************************************************//** 01543 * @brief Set the parameters of the device to predefined values 01544 * Set GPIO according to these values 01545 * from l6208_target_config.h 01546 * @retval None 01547 **********************************************************/ 01548 void L6208::L6208_SetDeviceParamsToPredefinedValues(void) 01549 { 01550 memset(&devicePrm, 0, sizeof(devicePrm)); 01551 L6208_SetAcceleration(L6208_CONF_PARAM_ACC_RATE); 01552 L6208_SetDeceleration(L6208_CONF_PARAM_DEC_RATE); 01553 L6208_SetMaxSpeed(L6208_CONF_PARAM_RUNNING_SPEED); 01554 L6208_SetMinSpeed(L6208_MIN_SPEED); 01555 devicePrm.accelTorque = L6208_CONF_PARAM_ACC_CURRENT; 01556 devicePrm.decelTorque = L6208_CONF_PARAM_DEC_CURRENT; 01557 devicePrm.runTorque = L6208_CONF_PARAM_RUNNING_CURRENT; 01558 devicePrm.holdTorque = L6208_CONF_PARAM_HOLDING_CURRENT; 01559 /* Only once acceleration, deceleration, min speed and max speed have been */ 01560 /* initialized, set the step mode */ 01561 devicePrm.stepMode = (motorStepMode_t) L6208_CONF_PARAM_STEP_MODE; 01562 L6208_SetDecayMode(L6208_CONF_PARAM_DECAY_MODE); 01563 devicePrm.moveDwellTime = L6208_CONF_PARAM_DWELL_TIME; 01564 if (L6208_CONF_PARAM_AUTO_HIZ_STOP) L6208_SetSysFlag(HiZstop); 01565 devicePrm.vrefPwmFreq = L6208_CONF_VREF_PWM_FREQUENCY; 01566 devicePrm.vrefPwmPeriod = (uint16_t)((1000000<<8)/L6208_CONF_VREF_PWM_FREQUENCY); 01567 /* Initialize current stepper state machine index */ 01568 L6208_SetMotionState(INACTIVE); 01569 } 01570 01571 /******************************************************//** 01572 * @brief Set the number of micro stepping waveform samples to rescale 01573 * @param[in] value number of micro stepping waveform samples 01574 * @retval None 01575 **********************************************************/ 01576 void L6208::L6208_SetMicrostepSample2Scale(uint8_t value) 01577 { 01578 if(value > L6208_USTEPS_PER_QUARTER_PERIOD) 01579 { 01580 value = L6208_USTEPS_PER_QUARTER_PERIOD; // clamp to maximum number of samples per period/4 01581 } 01582 devicePrm.uStepsample2scale = value; 01583 } 01584 01585 /******************************************************//** 01586 * @brief Set the number of micro stepping waveform samples to update into scanning 01587 * @param[in] value number of micro stepping waveform samples 01588 * @retval None 01589 **********************************************************/ 01590 void L6208::L6208_SetMicrostepSample2Update(uint8_t value) 01591 { 01592 // clamp to maximum number of samples per period/4 01593 if(value > L6208_USTEPS_PER_QUARTER_PERIOD) 01594 { 01595 value = L6208_USTEPS_PER_QUARTER_PERIOD; 01596 } 01597 // copy the stepper acceleration rate 01598 devicePrm.uStepsample2update = value; 01599 } 01600 01601 /******************************************************//** 01602 * @brief Set the stepper state machine index 01603 * @param[in] newMotionState 01604 * @retval None 01605 **********************************************************/ 01606 void L6208::L6208_SetMotionState(motorState_t newMotionState) 01607 { 01608 // sets the new stepper state machine index 01609 devicePrm.motionState = newMotionState; 01610 } 01611 01612 /******************************************************//** 01613 * @brief Set the user selected speed in step/tick 01614 * @param[in] newSpeed speed value (step/s) 01615 * @param[in] pSpeed pointer to the selected speed field 01616 * @retval return FALSE if the speed is too low or too high 01617 * or if the device is running in position mode, else TRUE 01618 **********************************************************/ 01619 bool L6208::L6208_SetSpeed(uint16_t newSpeed, uint32_t volatile *pSpeed) 01620 { 01621 uint64_t tmp64; 01622 uint32_t tmp32; 01623 01624 if (((L6208_IsSysFlag(running))&&(L6208_IsSysFlag(positionmode)))||\ 01625 (newSpeed < L6208_MIN_SPEED)) 01626 { 01627 return FALSE; 01628 } 01629 tmp32 = (uint32_t)L6208_Board_TickGetFreq(); 01630 if (tmp32 < newSpeed) 01631 { 01632 return FALSE; 01633 } 01634 /* Compute the decimal number of microstep or step per tick */ 01635 /* Decimal part is on 32 bits */ 01636 tmp64 = (uint64_t)newSpeed << 32; 01637 tmp64 /= ((uint64_t)tmp32); 01638 /* set the running constant speed value (step/tick) */ 01639 *pSpeed = (uint32_t)((tmp64 & 0x00000000FFFFFFFF)>>8); 01640 01641 return TRUE; 01642 } 01643 01644 /******************************************************//** 01645 * @brief Set the bit/s of flags according to the specified mask 01646 * @param[in] mask flag bit mask 01647 * @retval None 01648 **********************************************************/ 01649 inline void L6208::L6208_SetSysFlag(uint32_t mask) 01650 { 01651 devicePrm.flags |= mask; 01652 } 01653 01654 /******************************************************//** 01655 * @brief Stepper motor start command 01656 * @retval true on correct command execution 01657 **********************************************************/ 01658 bool L6208::L6208_StartMovement(void) 01659 { 01660 uint32_t tmp; 01661 if (L6208_IsSysFlag(running)) 01662 { 01663 /* Motor is already running ==> quit */ 01664 return FALSE; 01665 } 01666 if (!L6208_IsSysFlag(positionmode)) 01667 { 01668 /* Set the VREFA and VREFB to the selected acc. torque */ 01669 L6208_VectorCalc(devicePrm.accelTorque); 01670 01671 /* If the speed control mode is selected */ 01672 /* setup the motor acceleration for velocity mode driving */ 01673 L6208_SetMotionState(ACCELERATING); 01674 } 01675 else 01676 { 01677 /* if position control mode is selected, reset the current step counter */ 01678 devicePrm.step = 0; 01679 if(devicePrm.uStepSample > 31) 01680 { 01681 /* check the micro stepping waveform sample index */ 01682 devicePrm.uStepSample = 0; 01683 } 01684 /* Set the position dwelling wait time */ 01685 /* compute number of ticks per millisecond */ 01686 tmp = (uint32_t)L6208_Board_TickGetFreq() / 1000; 01687 /* Compute the dwelling time in ticks => dwellCounter (ticks) */ 01688 devicePrm.dwellCounter = tmp * (uint32_t)devicePrm.moveDwellTime; 01689 if (devicePrm.positionTarget == 0) 01690 { 01691 /* if the position to go is 0 (no move) */ 01692 /* Set the deceleration torque */ 01693 L6208_VectorCalc(devicePrm.decelTorque); 01694 /* Set the dwelling delay state index */ 01695 L6208_SetMotionState(INDEX_DWELL); 01696 } 01697 else 01698 { 01699 /* Set the VREFA and VREFB to the selected acc. torque */ 01700 L6208_VectorCalc(devicePrm.accelTorque); 01701 /* go to the selected position */ 01702 L6208_Indexmodeinit(); 01703 L6208_SetMotionState(INDEX_ACCEL); 01704 } 01705 } 01706 /* Sets the motor running flag */ 01707 L6208_SetSysFlag(running); 01708 /* Start the VREFA and VREFB PWMs */ 01709 L6208_Board_VrefPwmStart(BRIDGE_A, devicePrm.vrefPwmPeriod); 01710 L6208_Board_VrefPwmStart(BRIDGE_B, devicePrm.vrefPwmPeriod); 01711 if (!(L6208_IsSysFlag(EN_A_set))) 01712 { 01713 /* Enable power bridges */ 01714 L6208_Enable(); 01715 } 01716 /* Start the tick */ 01717 L6208_Board_TickStart(L6208::tickFreq); 01718 01719 return TRUE; 01720 } 01721 01722 /******************************************************//** 01723 * @brief Update the micro stepping waveform samples table with the 01724 * values previously scaled with current selected torque and tick period 01725 * @retval None 01726 **********************************************************/ 01727 void L6208::L6208_UpdateScanWaveformTable(void) 01728 { 01729 uint8_t index; 01730 01731 for(index=0; index<=L6208_USTEPS_PER_QUARTER_PERIOD; index++) 01732 { 01733 microTable1[index] = updatedMicroTable[index]; 01734 microTable1[L6208_USTEPS_PER_QUARTER_PERIOD*2 - index] = microTable1[index]; 01735 microTable1[index + L6208_USTEPS_PER_QUARTER_PERIOD*2] = updatedMicroTable[index]; 01736 } 01737 /* clear the number of samples to update */ 01738 L6208_SetMicrostepSample2Update(0); 01739 } 01740 01741 /******************************************************//** 01742 * @brief Check if there are waveform samples to rescale and if so, perform the rescaling 01743 * @retval None 01744 **********************************************************/ 01745 void L6208::L6208_UstepWaveformHandling(void) 01746 { 01747 /* micro stepper waveform samples rescaling ... and updating */ 01748 uint8_t nbSamplesToRescale = L6208_GetMicrostepSample2Scale(); 01749 if(nbSamplesToRescale > 0) 01750 { 01751 /* Current torque value has been changed, so recalculate the waveform table */ 01752 L6208_ScaleWaveformTable(); 01753 01754 /* Set the number of samples to update */ 01755 L6208_SetMicrostepSample2Update(L6208_USTEPS_PER_QUARTER_PERIOD); 01756 01757 /* Reset the number of samples to rescaled afer rescaling */ 01758 L6208_SetMicrostepSample2Scale(0); 01759 } 01760 } 01761 01762 /******************************************************//** 01763 * @brief Set the current torque value (Vref) 01764 * @param[in] newTorque Selected torque value 01765 * @retval always TRUE 01766 **********************************************************/ 01767 bool L6208::L6208_VectorCalc(uint8_t newTorque) 01768 { 01769 /* save current selected torque value */ 01770 devicePrm.curTorqueScaler = (uint16_t)newTorque; 01771 01772 if(!L6208_IsSysFlag(microstep)) 01773 { 01774 /* full/half step mode or the motor is not running */ 01775 /* set the PWM duty cycle according to the current torque value (%). */ 01776 /* The TON value will be calculated inside the TIMx_PWM_duty_setup f(). */ 01777 L6208_VrefPwmComputePulseWidth(BRIDGE_A, devicePrm.curTorqueScaler, TRUE); 01778 L6208_VrefPwmComputePulseWidth(BRIDGE_B, devicePrm.curTorqueScaler, TRUE); 01779 devicePrm.vRefAVal = devicePrm.curTorqueScaler; // save current VREFA value 01780 devicePrm.vRefBVal = devicePrm.curTorqueScaler; // save current VREFB value 01781 } 01782 else 01783 { 01784 /* microstep mode */ 01785 if(L6208_IsSysFlag(running)) 01786 { 01787 /* set the number of waveform sample to rescale according current selected */ 01788 /* torque value */ 01789 L6208_SetMicrostepSample2Scale(L6208_USTEPS_PER_QUARTER_PERIOD); 01790 } 01791 else 01792 { 01793 /* micro stepping mode motor stopped */ 01794 L6208_ScaleWaveformTable(); 01795 L6208_UpdateScanWaveformTable(); 01796 /* Set the VREF timer PWM TON to update VREFA and VREFB */ 01797 L6208_VrefPwmComputePulseWidth(BRIDGE_A, pMicroTable2[devicePrm.uStepSample], FALSE); 01798 L6208_VrefPwmComputePulseWidth(BRIDGE_B, microTable1[devicePrm.uStepSample], FALSE); 01799 } 01800 } 01801 return TRUE; 01802 } 01803 01804 /******************************************************//** 01805 * @brief Compute the pulse width of VREFA or VREFB PWM 01806 * @param[in] bridgeId 01807 * 0 for BRIDGE_A 01808 * 1 for BRIDGE_B 01809 * @param[in] value pulse length in 1/256th of microsecond 01810 * or PWM duty cycle: 0 - 100 % 01811 * @param[in] valueIsPwmDutyCycle must be TRUE if value is a PWM duty cycle 01812 * @retval FALSE if wrong timer handle is used, else TRUE 01813 **********************************************************/ 01814 bool L6208::L6208_VrefPwmComputePulseWidth(uint8_t bridgeId, uint16_t value, bool valueIsPwmDutyCycle) 01815 { 01816 if(valueIsPwmDutyCycle) 01817 { 01818 if (value > 100) value = 100; 01819 value = (uint16_t)(((uint32_t)devicePrm.vrefPwmPeriod * (uint32_t)value) / 100); 01820 } 01821 if (bridgeId == 0) 01822 { 01823 devicePrm.vrefPwmPulseWidthTargetA = value; 01824 devicePrm.vrefPwmPulseWidthToBeGeneratedA = 0; 01825 } 01826 else if (bridgeId == 1) 01827 { 01828 devicePrm.vrefPwmPulseWidthTargetB = value; 01829 devicePrm.vrefPwmPulseWidthToBeGeneratedB = 0; 01830 } 01831 else 01832 { 01833 return FALSE; 01834 } 01835 return TRUE; 01836 } 01837 01838 /******************************************************//** 01839 * @brief Update the pulse width of VREFA or VREFB PWM 01840 * @param None 01841 * @retval None 01842 **********************************************************/ 01843 void L6208::L6208_VrefPwmUpdatePulseWidth(void) 01844 { 01845 uint16_t pulseWidthUs; 01846 01847 devicePrm.vrefPwmPulseWidthToBeGeneratedA += devicePrm.vrefPwmPulseWidthTargetA; 01848 pulseWidthUs = devicePrm.vrefPwmPulseWidthToBeGeneratedA>>8; 01849 if (pulseWidthUs!=0) 01850 { 01851 L6208_Board_VrefPwmSetPulseWidthA(pulseWidthUs); 01852 devicePrm.vrefPwmPulseWidthToBeGeneratedA -= (pulseWidthUs<<8); 01853 } 01854 else 01855 { 01856 L6208_Board_VrefPwmSetPulseWidthA(0); 01857 } 01858 01859 devicePrm.vrefPwmPulseWidthToBeGeneratedB += devicePrm.vrefPwmPulseWidthTargetB; 01860 pulseWidthUs = devicePrm.vrefPwmPulseWidthToBeGeneratedB>>8; 01861 if (pulseWidthUs!=0) 01862 { 01863 L6208_Board_VrefPwmSetPulseWidthB(pulseWidthUs); 01864 devicePrm.vrefPwmPulseWidthToBeGeneratedB -= (pulseWidthUs<<8); 01865 } 01866 else 01867 { 01868 L6208_Board_VrefPwmSetPulseWidthB(0); 01869 } 01870 } 01871 01872 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Thu Jul 21 2022 19:36:08 by 1.7.2