Expansion SW library to control high power stepper motor(s) using IHM03A1 expansion board(s) with Powerstep01 driver.
Dependencies: X_NUCLEO_COMMON ST_INTERFACES
Dependents: IHM03A1_ExampleFor1Motor HelloWorld_IHM03A1 IHM03A1_ExampleFor3Motors KYPHOS_Stepper_Motor_Control
Fork of X_NUCLEO_IHM03A1 by
Motor Control Library
Library to handle the X-NUCLEO-IHM03A1 Motor Control Expansion Board based on the Powerstep01 component.
It features the:
- read and write of Powerstep01 registers
- Nucleo and expansion board configuration (GPIOs, PWMs, IRQs, etc.)
- Powerstep01 application commands handling
- FLAG and BUSY interrupt handling (alarm reporting)
- Daisy chain handling
The API allows to easily:
- perform various positioning, moves and stops
- get/set or monitor the motor positions
- set home position and mark another position
- get/set minimum and maximum speed
- get current speed
- get/set acceleration and deceleration
- get/set the step mode (up to 1/128)
- get/set the control method
- get/set parameters for voltage mode driving
- get/set parameters for current mode driving
- get/set parameters for gate driving
- configure various protections such as overcurrent detection
- enable/disable alarms
- handle step-clock
- get system status
Daisy-Chain Configuration
The IHM03A1 board can be stacked up to three times so that the Powerstep01 components will be connected in daisy-chain configuration. For this purpose, some resistors must be correctly connected on the boards as depicted here below:
Platform compatibility
Compatible platforms have been tested with the default configuration provided by the HelloWorld_IHM03A1 example.
Components/PowerStep01/PowerStep01.cpp
- Committer:
- Davidroid
- Date:
- 2017-03-24
- Revision:
- 5:e7dca8c6ae9f
- Parent:
- Components/powerstep01/PowerStep01.cpp@ 4:f48e8d87553e
- Child:
- 7:9d772e2a9dbe
File content as of revision 5:e7dca8c6ae9f:
/** ****************************************************************************** * @file PowerStep01.cpp * @author IPC Rennes * @version V1.0.0 * @date March 18th, 2016 * @brief Powerstep01 motor driver (Microstepping controller with power MOSFETs) * @note (C) COPYRIGHT 2016 STMicroelectronics ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "PowerStep01.h" /* Definitions ---------------------------------------------------------------*/ /* Error of bad SPI transaction. */ #define POWERSTEP01_ERROR_1 (POWERSTEP01_ERROR_BASE|0x0001) /* Variables ----------------------------------------------------------------*/ /* Number of devices. */ uint8_t PowerStep01::numberOfDevices = 0; /* ISR flags used to restart an interrupted SPI transfer when an error is reported. */ bool PowerStep01::spiPreemptionByIsr = FALSE; bool PowerStep01::isrFlag = FALSE; /* SPI Transmission for Daisy-Chain Configuration. */ uint8_t PowerStep01::spiTxBursts[POWERSTEP01_CMD_ARG_MAX_NB_BYTES][MAX_NUMBER_OF_DEVICES]; uint8_t PowerStep01::spiRxBursts[POWERSTEP01_CMD_ARG_MAX_NB_BYTES][MAX_NUMBER_OF_DEVICES]; /* Methods -------------------------------------------------------------------*/ /********************************************************** * @brief Starts the Powerstep01 library * @param[in] pInit pointer to the initialization data * @retval COMPONENT_OK in case of success. **********************************************************/ status_t PowerStep01::Powerstep01_Init(void* pInit) { /* configure the step clock */ Powerstep01_Board_StepClockInit(); /* Standby-reset deactivation */ Powerstep01_Board_ReleaseReset(); /* Let a delay after reset */ Powerstep01_Board_Delay(1); if (pInit == 0) { // Set all registers to their predefined values // from powerstep01_target_config.h Powerstep01_SetRegisterToPredefinedValues(); } else { Powerstep01_SetDeviceParamsToGivenValues((powerstep01_init_u_t*) pInit); } // Put the Powerstep01 in HiZ state Powerstep01_CmdHardHiZ(); Powerstep01_FetchAndClearAllStatus(); return COMPONENT_OK; } /********************************************************** * @brief Read id * @param[in] id pointer to the identifier to be read. * @retval COMPONENT_OK in case of success. **********************************************************/ status_t PowerStep01::Powerstep01_ReadID(uint8_t *id) { *id = deviceInstance; return COMPONENT_OK; } /********************************************************** * @brief Attaches a user callback to the error Handler. * The call back will be then called each time the library * detects an error * @param[in] callback Name of the callback to attach * to the error Hanlder * @retval None **********************************************************/ void PowerStep01::Powerstep01_AttachErrorHandler(void (*callback)(uint16_t error)) { errorHandlerCallback = (void (*)(uint16_t error)) callback; } /********************************************************** * @brief Issues the get_status command to the Powerstep01 device * @retval Status Register value * @note Once the get_status command is performed, the flags of the * status register are reset. * This is not the case when the status register is read with the * GetParam command (via the functions Powerstep01_ReadStatusRegister * or Powerstep01_CmdGetParam). **********************************************************/ uint16_t PowerStep01::Powerstep01_CmdGetStatus(void) { uint16_t status = 0; uint32_t loop; uint8_t spiIndex = numberOfDevices - deviceInstance - 1; bool itDisable = FALSE; do { spiPreemptionByIsr = FALSE; if (itDisable) { /* re-enable Powerstep01_Board_EnableIrq if disable in previous iteration */ Powerstep01_Board_EnableIrq(); itDisable = FALSE; } for (loop = 0; loop < numberOfDevices; loop++) { spiTxBursts[0][loop] = POWERSTEP01_NOP; spiTxBursts[1][loop] = POWERSTEP01_NOP; spiTxBursts[2][loop] = POWERSTEP01_NOP; spiTxBursts[3][loop] = POWERSTEP01_NOP; spiRxBursts[0][loop] = 0; spiRxBursts[1][loop] = 0; spiRxBursts[2][loop] = 0; spiRxBursts[3][loop] = 0; } spiTxBursts[0][spiIndex] = POWERSTEP01_GET_STATUS; /* Disable interruption before checking */ /* pre-emption by ISR and SPI transfers*/ Powerstep01_Board_DisableIrq(); itDisable = TRUE; } while (spiPreemptionByIsr); // check pre-emption by ISR for (loop = 0; loop < POWERSTEP01_CMD_ARG_NB_BYTES_GET_STATUS + POWERSTEP01_RSP_NB_BYTES_GET_STATUS; loop++) { Powerstep01_WriteBytes(&spiTxBursts[loop][0], &spiRxBursts[loop][0]); } status = (spiRxBursts[1][spiIndex] << 8) | (spiRxBursts[2][spiIndex]); /* re-enable Powerstep01_Board_EnableIrq after SPI transfers*/ Powerstep01_Board_EnableIrq(); return (status); } /********************************************************** * @brief Requests the motor to move to the home position (ABS_POSITION = 0) * @retval None **********************************************************/ void PowerStep01::Powerstep01_CmdGoHome(void) { Powerstep01_SendCommand(POWERSTEP01_GO_HOME, 0); } /********************************************************** * @brief Requests the motor to move to the mark position * @retval None **********************************************************/ void PowerStep01::Powerstep01_CmdGoMark(void) { Powerstep01_SendCommand(POWERSTEP01_GO_MARK, 0); } /********************************************************** * @brief Requests the motor to move to the specified position * @param[in] targetPosition absolute position in steps * @retval None **********************************************************/ void PowerStep01::Powerstep01_CmdGoTo(int32_t targetPosition) { Powerstep01_SendCommand(POWERSTEP01_GO_TO, targetPosition); } /******************************************************//** * @brief Issues PowerStep01 Go To Dir command * @param[in] direction movement direction * @param[in] abs_pos absolute position where requested to move * @retval None *********************************************************/ void PowerStep01::Powerstep01_CmdGoToDir(motorDir_t direction, int32_t abs_pos) { Powerstep01_SendCommand((uint8_t)POWERSTEP01_GO_TO_DIR| (uint8_t)direction, abs_pos); } /******************************************************//** * @brief Issues PowerStep01 Go Until command * @param[in] action ACTION_RESET or ACTION_COPY * @param[in] direction movement direction * @param[in] speed in steps/tick * @retval None *********************************************************/ void PowerStep01::Powerstep01_CmdGoUntil(motorAction_t action, motorDir_t direction, uint32_t speed) { Powerstep01_SendCommand( (uint8_t)POWERSTEP01_GO_UNTIL|(uint8_t)action|(uint8_t)direction, speed); } /********************************************************** * @brief Immediatly stops the motor and disable the power bridge * @retval None * @note The hard_hiz command immediately disables the power bridges * (high impedance state) and raises the HiZ flag. * When the motor is stopped, a hard_hiz command forces the bridges * to enter high impedance state. * This command can be given anytime and is immediately executed. *********************************************************/ void PowerStep01::Powerstep01_CmdHardHiZ(void) { Powerstep01_SendCommand(POWERSTEP01_HARD_HIZ, 0); } /********************************************************** * @brief Immediatly stops the motor and disable the power bridge * @retval None * @note The hard_stop command causes an immediate motor stop with * infinite deceleration. * When the motor is in high impedance state, a hard_stop command * forces the bridges to exit high impedance state; no motion is performed. * This command can be given anytime and is immediately executed. * This command keeps the BUSY flag low until the motor is stopped. **********************************************************/ void PowerStep01::Powerstep01_CmdHardStop(void) { Powerstep01_SendCommand(POWERSTEP01_HARD_STOP, 0); } /********************************************************** * @brief Moves the motor of the specified number of steps * @param[in] direction FORWARD or BACKWARD * @param[in] stepCount Number of steps to perform * @retval None **********************************************************/ void PowerStep01::Powerstep01_CmdMove(motorDir_t direction, uint32_t stepCount) { Powerstep01_SendCommand((uint8_t)POWERSTEP01_MOVE|(uint8_t)direction, stepCount); } /********************************************************** * @brief Issues the Nop command to the Powerstep01 device * @retval None **********************************************************/ void PowerStep01::Powerstep01_CmdNop(void) { Powerstep01_SendCommand(POWERSTEP01_NOP, 0); } /******************************************************//** * @brief Issues PowerStep01 Release SW command * @param[in] action type of action to undertake when the SW * input is forced high * @param[in] direction movement direction * @retval None *********************************************************/ void PowerStep01::Powerstep01_CmdReleaseSw(motorAction_t action, motorDir_t direction) { Powerstep01_SendCommand((uint8_t)POWERSTEP01_RELEASE_SW| (uint8_t)action| (uint8_t)direction, 0); } /******************************************************//** * @brief Issues PowerStep01 Reset Device command * @param[in] deviceId (from 0 to MAX_NUMBER_OF_DEVICES-1 ) * @retval None *********************************************************/ void PowerStep01::Powerstep01_CmdResetDevice(void) { Powerstep01_SendCommand(POWERSTEP01_RESET_DEVICE, 0); } /******************************************************//** * @brief Issues PowerStep01 Reset Pos command * @param[in] deviceId (from 0 to MAX_NUMBER_OF_DEVICES-1 ) * @retval None *********************************************************/ void PowerStep01::Powerstep01_CmdResetPos(void) { Powerstep01_SendCommand(POWERSTEP01_RESET_POS, 0); } /********************************************************** * @brief Runs the motor. It will accelerate from the min * speed up to the max speed by using the device acceleration. * @param[in] direction FORWARD or BACKWARD * @param[in] speed in steps/s * @retval None **********************************************************/ void PowerStep01::Powerstep01_CmdRun(motorDir_t direction, uint32_t speed) { Powerstep01_SendCommand((uint8_t)POWERSTEP01_RUN|(uint8_t)direction, speed); } /********************************************************** * @brief Stops the motor by using the device deceleration * and disables the power bridges * @retval None * @note The soft_hiz command disables the power bridges * (high impedance state) after a deceleration to zero. * The deceleration value used is the one stored in the DEC register. * When bridges are disabled, the HiZ flag is raised. * When the motor is stopped, a soft_hiz command forces the bridges * to enter high impedance state. * This command can be given anytime and is immediately executed. * This command keeps the BUSY flag low until the motor is stopped. *********************************************************/ void PowerStep01::Powerstep01_CmdSoftHiZ(void) { Powerstep01_SendCommand(POWERSTEP01_SOFT_HIZ, 0); } /********************************************************** * @brief Stops the motor by using the device deceleration * @retval None * @note The soft_stop command causes an immediate deceleration * to zero speed and a consequent motor stop. * The deceleration value used is the one stored in the DEC register. * When the motor is in high impedance state, a soft_stop * command forces the bridges to exit from high impedance state. * No motion is performed. * This command can be given anytime and is immediately executed. * This command keeps the BUSY flag low until the motor is stopped. **********************************************************/ void PowerStep01::Powerstep01_CmdSoftStop(void) { Powerstep01_SendCommand(POWERSTEP01_SOFT_STOP, 0); } /******************************************************//** * @brief Issues PowerStep01 Step Clock command * @param[in] direction Movement direction (FORWARD, BACKWARD) * @retval None *********************************************************/ void PowerStep01::Powerstep01_CmdStepClock(motorDir_t direction) { Powerstep01_SendCommand((uint8_t)POWERSTEP01_STEP_CLOCK|(uint8_t)direction, 0); } /********************************************************** * @brief Error handler which calls the user callback (if defined) * @param[in] error Number of the error * @retval None **********************************************************/ void PowerStep01::Powerstep01_ErrorHandler(uint16_t error) { if (errorHandlerCallback != 0) { (void) errorHandlerCallback(error); } else { /* Aborting the program. */ exit(EXIT_FAILURE); } } /******************************************************//** * @brief Fetch and clear status flags of all devices * by issuing a GET_STATUS command simultaneously * to all devices. * Then, the fetched status of each device can be retrieved * by using the Powerstep01_GetFetchedStatus function * provided there is no other calls to functions which * use the SPI in between. * @retval None *********************************************************/ void PowerStep01::Powerstep01_FetchAndClearAllStatus(void) { uint8_t loop; for (loop = 0; loop < numberOfDevices; loop++) { spiTxBursts[0][loop] = POWERSTEP01_GET_STATUS; spiTxBursts[1][loop] = POWERSTEP01_NOP; spiTxBursts[2][loop] = POWERSTEP01_NOP; spiTxBursts[3][loop] = POWERSTEP01_NOP; spiRxBursts[0][loop] = 0; spiRxBursts[1][loop] = 0; spiRxBursts[2][loop] = 0; spiRxBursts[3][loop] = 0; } for (loop = 0; loop < POWERSTEP01_CMD_ARG_NB_BYTES_GET_STATUS + POWERSTEP01_RSP_NB_BYTES_GET_STATUS; loop++) { Powerstep01_WriteBytes(&spiTxBursts[loop][0], &spiRxBursts[loop][0]); } } /******************************************************//** * @brief Get the value of the STATUS register which was * fetched by using Powerstep01_FetchAndClearAllStatus. * The fetched values are available as long as there * no other calls to functions which use the SPI. * @retval Last fetched value of the STATUS register *********************************************************/ uint16_t PowerStep01::Powerstep01_GetFetchedStatus(void) { uint16_t status = 0; if (numberOfDevices > deviceInstance) { uint8_t spiIndex = numberOfDevices - deviceInstance - 1; status = (spiRxBursts[1][spiIndex] << 8) | (spiRxBursts[2][spiIndex]); } return (status); } /********************************************************** * @brief Returns the FW version of the library * @retval POWERSTEP01_FW_VERSION **********************************************************/ uint32_t PowerStep01::Powerstep01_GetFwVersion(void) { return (POWERSTEP01_FW_VERSION); } /********************************************************** * @brief Returns the mark position device * @retval Mark register value converted in a 32b signed integer **********************************************************/ int32_t PowerStep01::Powerstep01_GetMark(void) { return Powerstep01_ConvertPosition(Powerstep01_CmdGetParam(POWERSTEP01_MARK)); } /********************************************************** * @brief Returns the ABS_POSITION device * @retval ABS_POSITION register value converted in a 32b signed integer **********************************************************/ int32_t PowerStep01::Powerstep01_GetPosition(void) { return Powerstep01_ConvertPosition( Powerstep01_CmdGetParam(POWERSTEP01_ABS_POS)); } /********************************************************** * @brief Checks if the device is busy * by reading the Busy flag bit of its status Register * This operation clears the status register * @retval true if device is busy, false zero *********************************************************/ bool PowerStep01::Powerstep01_IsDeviceBusy(void) { if(!(Powerstep01_CmdGetStatus() & POWERSTEP01_STATUS_BUSY)) { return TRUE; } else { return FALSE; } } /********************************************************** * @brief Reads the Status Register value * @retval Status register value * @note The status register flags are not cleared * at the difference with Powerstep01_CmdGetStatus() **********************************************************/ uint16_t PowerStep01::Powerstep01_ReadStatusRegister(void) { return (Powerstep01_CmdGetParam(POWERSTEP01_STATUS)); } /********************************************************** * @brief Set the stepping mode * @param[in] stepMode from full step to 1/128 microstep * as specified in enum motorStepMode_t * @retval None **********************************************************/ bool PowerStep01::Powerstep01_SelectStepMode(motorStepMode_t stepMode) { uint8_t stepModeRegister; powerstep01_StepSel_t powerstep01StepMode; switch (stepMode) { case STEP_MODE_FULL: powerstep01StepMode = POWERSTEP01_STEP_SEL_1; break; case STEP_MODE_HALF: powerstep01StepMode = POWERSTEP01_STEP_SEL_1_2; break; case STEP_MODE_1_4: powerstep01StepMode = POWERSTEP01_STEP_SEL_1_4; break; case STEP_MODE_1_8: powerstep01StepMode = POWERSTEP01_STEP_SEL_1_8; break; case STEP_MODE_1_16: powerstep01StepMode = POWERSTEP01_STEP_SEL_1_16; break; case STEP_MODE_1_32: powerstep01StepMode = POWERSTEP01_STEP_SEL_1_32; break; case STEP_MODE_1_64: powerstep01StepMode = POWERSTEP01_STEP_SEL_1_64; break; case STEP_MODE_1_128: powerstep01StepMode = POWERSTEP01_STEP_SEL_1_128; break; default: return false; } /* Set the powerstep01 in HiZ state */ Powerstep01_CmdHardHiZ(); /* Read Step mode register and clear STEP_SEL field */ stepModeRegister = (uint8_t)(0xF8 & Powerstep01_CmdGetParam(POWERSTEP01_STEP_MODE)) ; /* Apply new step mode */ Powerstep01_CmdSetParam(POWERSTEP01_STEP_MODE, stepModeRegister | (uint8_t)powerstep01StepMode); /* Reset abs pos register */ Powerstep01_CmdResetPos(); return true; } /********************************************************** * @brief Set current position to be the Home position (ABS pos set to 0) * @retval None **********************************************************/ void PowerStep01::Powerstep01_SetHome(void) { Powerstep01_CmdSetParam(POWERSTEP01_ABS_POS, 0); } /********************************************************** * @brief Sets current position to be the Mark position * @retval None **********************************************************/ void PowerStep01::Powerstep01_SetMark(void) { Powerstep01_CmdSetParam(POWERSTEP01_MARK, Powerstep01_CmdGetParam(POWERSTEP01_ABS_POS)); } /********************************************************** * @brief Locks until the device state becomes Inactive * @retval None **********************************************************/ void PowerStep01::Powerstep01_WaitWhileActive(void) { /* Wait while motor is running */ while (Powerstep01_IsDeviceBusy() != 0); } /** * @brief To and from register parameter conversion functions */ /********************************************************** * @brief Converts the ABS_POSITION register value to a 32b signed integer * @param[in] abs_position_reg value of the ABS_POSITION register * @retval operation_result 32b signed integer corresponding to the absolute position **********************************************************/ int32_t PowerStep01::Powerstep01_ConvertPosition(uint32_t abs_position_reg) { int32_t operation_result; if (abs_position_reg & POWERSTEP01_ABS_POS_SIGN_BIT_MASK) { /* Negative register value */ abs_position_reg = ~abs_position_reg; abs_position_reg += 1; operation_result = (int32_t) (abs_position_reg & POWERSTEP01_ABS_POS_VALUE_MASK); operation_result = -operation_result; } else { operation_result = (int32_t) abs_position_reg; } return operation_result; } /** * @brief Functions to initialize the registers */ /********************************************************** * @brief Set the parameters of the device to values of initPrm structure * @param[in] initPrm structure containing values to initialize the device * parameters * @retval None. **********************************************************/ void PowerStep01::Powerstep01_SetDeviceParamsToGivenValues( powerstep01_init_u_t *initPrm) { Powerstep01_CmdSetParam(POWERSTEP01_ABS_POS, 0); Powerstep01_CmdSetParam(POWERSTEP01_EL_POS, 0); Powerstep01_CmdSetParam(POWERSTEP01_MARK, 0); Powerstep01_CmdSetParam(POWERSTEP01_ACC, acc_dec_steps_s2_to_reg_val(initPrm->cm.cp.acceleration)); Powerstep01_CmdSetParam(POWERSTEP01_DEC, acc_dec_steps_s2_to_reg_val(initPrm->cm.cp.deceleration)); Powerstep01_CmdSetParam(POWERSTEP01_MAX_SPEED, max_spd_steps_s_to_reg_val(initPrm->cm.cp.maxSpeed)); Powerstep01_CmdSetParam(POWERSTEP01_MIN_SPEED, initPrm->cm.cp.lowSpeedOptimization| max_spd_steps_s_to_reg_val(initPrm->cm.cp.minSpeed)); Powerstep01_CmdSetParam(POWERSTEP01_FS_SPD, initPrm->cm.cp.boostMode| fs_spd_steps_s_to_reg_val(initPrm->cm.cp.fullStepSpeed)); Powerstep01_CmdSetParam(POWERSTEP01_OCD_TH, stall_ocd_th_to_reg_val(initPrm->cm.cp.ocdThreshold)); Powerstep01_CmdSetParam(POWERSTEP01_STEP_MODE, (uint8_t)initPrm->cm.cp.syncClockSelection| (uint8_t)initPrm->cm.cp.cmVmSelection| (uint8_t)(uint8_t)initPrm->cm.cp.stepMode); Powerstep01_CmdSetParam(POWERSTEP01_ALARM_EN, initPrm->cm.cp.alarmsSelection); Powerstep01_CmdSetParam(POWERSTEP01_GATECFG1, (uint16_t)initPrm->cm.cp.iGate| (uint16_t)initPrm->cm.cp.tcc| (uint16_t)initPrm->cm.cp.tBoost| (uint16_t)initPrm->cm.cp.wdEn); Powerstep01_CmdSetParam(POWERSTEP01_GATECFG2, (uint16_t)initPrm->cm.cp.tBlank| (uint16_t)initPrm->cm.cp.tdt); if (initPrm->cm.cp.cmVmSelection == POWERSTEP01_CM_VM_VOLTAGE) { //Voltage mode Powerstep01_CmdSetParam(POWERSTEP01_INT_SPD, int_spd_steps_s_to_reg_val( initPrm->vm.intersectSpeed)); Powerstep01_CmdSetParam(POWERSTEP01_K_THERM, k_therm_comp_to_reg_val( initPrm->vm.thermalCompensationFactor)); Powerstep01_CmdSetParam(POWERSTEP01_STALL_TH, stall_ocd_th_to_reg_val( initPrm->vm.stallThreshold)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_HOLD, k_val_perc_to_reg_val( initPrm->vm.kvalHold)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_RUN, k_val_perc_to_reg_val( initPrm->vm.kvalRun)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_ACC, k_val_perc_to_reg_val( initPrm->vm.kvalAcc)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_DEC, k_val_perc_to_reg_val( initPrm->vm.kvalDec)); Powerstep01_CmdSetParam(POWERSTEP01_ST_SLP, bemf_slope_perc_to_reg_val( initPrm->vm.startSlope)); Powerstep01_CmdSetParam(POWERSTEP01_FN_SLP_ACC, bemf_slope_perc_to_reg_val( initPrm->vm.accelerationFinalSlope)); Powerstep01_CmdSetParam(POWERSTEP01_FN_SLP_DEC, bemf_slope_perc_to_reg_val( initPrm->vm.decelerationFinalSlope)); Powerstep01_CmdSetParam(POWERSTEP01_CONFIG, (uint16_t)initPrm->vm.oscClkSel| (uint16_t)initPrm->vm.swMode | (uint16_t)initPrm->vm.enVsComp| (uint16_t)initPrm->vm.ocSd| (uint16_t)initPrm->vm.uvloVal| (uint16_t)initPrm->vm.vccVal| (uint16_t)initPrm->vm.fPwmInt| (uint16_t)initPrm->vm.fPwmDec); } else { // Current mode Powerstep01_CmdSetParam(POWERSTEP01_TVAL_HOLD, t_val_ref_voltage_to_reg_val( initPrm->cm.tvalHold)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_RUN, t_val_ref_voltage_to_reg_val( initPrm->cm.tvalRun)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_ACC, t_val_ref_voltage_to_reg_val( initPrm->cm.tvalAcc)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_DEC, t_val_ref_voltage_to_reg_val( initPrm->cm.tvalDec)); Powerstep01_CmdSetParam(POWERSTEP01_T_FAST, (uint8_t)initPrm->cm.toffFast| (uint8_t)initPrm->cm.fastStep); Powerstep01_CmdSetParam(POWERSTEP01_TON_MIN, t_min_time_to_reg_val( initPrm->cm.tonMin)); Powerstep01_CmdSetParam(POWERSTEP01_TOFF_MIN, t_min_time_to_reg_val( initPrm->cm.toffMin)); Powerstep01_CmdSetParam(POWERSTEP01_CONFIG, (uint16_t)initPrm->cm.oscClkSel| (uint16_t)initPrm->cm.swMode| (uint16_t)initPrm->cm.tqReg| (uint16_t)initPrm->cm.ocSd| (uint16_t)initPrm->cm.uvloVal| (uint16_t)initPrm->cm.vccVal| (uint16_t)initPrm->cm.tsw| (uint16_t)initPrm->cm.predEn); } } /********************************************************** * @brief Sets the registers of the Powerstep01 to their predefined values * from powerstep01_target_config.h * @retval None **********************************************************/ void PowerStep01::Powerstep01_SetRegisterToPredefinedValues(void) { powerstep01_CmVm_t cmVm; Powerstep01_CmdSetParam( POWERSTEP01_ABS_POS, 0); Powerstep01_CmdSetParam( POWERSTEP01_EL_POS, 0); Powerstep01_CmdSetParam( POWERSTEP01_MARK, 0); switch (deviceInstance) { case 0: cmVm = POWERSTEP01_CONF_PARAM_CM_VM_DEVICE_0; Powerstep01_CmdSetParam(POWERSTEP01_ACC, acc_dec_steps_s2_to_reg_val( POWERSTEP01_CONF_PARAM_ACC_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_DEC, acc_dec_steps_s2_to_reg_val( POWERSTEP01_CONF_PARAM_DEC_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_MAX_SPEED, max_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_MAX_SPEED_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_MIN_SPEED, POWERSTEP01_CONF_PARAM_LSPD_BIT_DEVICE_0| min_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_MIN_SPEED_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_FS_SPD, POWERSTEP01_CONF_PARAM_BOOST_MODE_DEVICE_0| fs_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_FS_SPD_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_OCD_TH, (uint8_t)POWERSTEP01_CONF_PARAM_OCD_TH_DEVICE_0); Powerstep01_CmdSetParam(POWERSTEP01_STEP_MODE, (uint8_t)POWERSTEP01_CONF_PARAM_SYNC_MODE_DEVICE_0 | (uint8_t)POWERSTEP01_CONF_PARAM_CM_VM_DEVICE_0| (uint8_t)POWERSTEP01_CONF_PARAM_STEP_MODE_DEVICE_0); Powerstep01_CmdSetParam(POWERSTEP01_ALARM_EN, POWERSTEP01_CONF_PARAM_ALARM_EN_DEVICE_0); Powerstep01_CmdSetParam(POWERSTEP01_GATECFG1, (uint16_t)POWERSTEP01_CONF_PARAM_IGATE_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_TCC_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_TBOOST_DEVICE_0| (uint16_t)POWERSTEP01_CONF_PARAM_WD_EN_DEVICE_0); Powerstep01_CmdSetParam(POWERSTEP01_GATECFG2, (uint16_t)POWERSTEP01_CONF_PARAM_TBLANK_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_TDT_DEVICE_0); // Voltage mode if (cmVm == POWERSTEP01_CM_VM_VOLTAGE) { Powerstep01_CmdSetParam(POWERSTEP01_INT_SPD, int_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_INT_SPD_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_K_THERM, k_therm_comp_to_reg_val( POWERSTEP01_CONF_PARAM_K_THERM_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_STALL_TH, stall_ocd_th_to_reg_val( POWERSTEP01_CONF_PARAM_STALL_TH_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_HOLD, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_HOLD_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_RUN, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_RUN_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_ACC, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_ACC_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_DEC, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_DEC_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_ST_SLP, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_ST_SLP_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_FN_SLP_ACC, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_FN_SLP_ACC_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_FN_SLP_DEC, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_FN_SLP_DEC_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_CONFIG, (uint16_t)POWERSTEP01_CONF_PARAM_CLOCK_SETTING_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_SW_MODE_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_VS_COMP_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_OC_SD_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_UVLOVAL_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_VCCVAL_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_PWM_DIV_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_PWM_MUL_DEVICE_0); } else { // Current mode Powerstep01_CmdSetParam(POWERSTEP01_TVAL_HOLD, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_HOLD_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_RUN, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_RUN_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_ACC, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_ACC_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_DEC, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_DEC_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_T_FAST, (uint8_t)POWERSTEP01_CONF_PARAM_TOFF_FAST_DEVICE_0 | (uint8_t)POWERSTEP01_CONF_PARAM_FAST_STEP_DEVICE_0); Powerstep01_CmdSetParam(POWERSTEP01_TON_MIN, t_min_time_to_reg_val( POWERSTEP01_CONF_PARAM_TON_MIN_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_TOFF_MIN, t_min_time_to_reg_val( POWERSTEP01_CONF_PARAM_TOFF_MIN_DEVICE_0)); Powerstep01_CmdSetParam(POWERSTEP01_CONFIG, (uint16_t)POWERSTEP01_CONF_PARAM_CLOCK_SETTING_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_SW_MODE_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_TQ_REG_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_OC_SD_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_UVLOVAL_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_VCCVAL_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_TSW_DEVICE_0 | (uint16_t)POWERSTEP01_CONF_PARAM_PRED_DEVICE_0); } break; #if (MAX_NUMBER_OF_DEVICES > 1) case 1: cmVm = POWERSTEP01_CONF_PARAM_CM_VM_DEVICE_1; Powerstep01_CmdSetParam(POWERSTEP01_ACC, acc_dec_steps_s2_to_reg_val( POWERSTEP01_CONF_PARAM_ACC_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_DEC, acc_dec_steps_s2_to_reg_val( POWERSTEP01_CONF_PARAM_DEC_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_MAX_SPEED, max_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_MAX_SPEED_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_MIN_SPEED, POWERSTEP01_CONF_PARAM_LSPD_BIT_DEVICE_1| min_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_MIN_SPEED_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_FS_SPD, POWERSTEP01_CONF_PARAM_BOOST_MODE_DEVICE_1| fs_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_FS_SPD_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_OCD_TH, (uint8_t)POWERSTEP01_CONF_PARAM_OCD_TH_DEVICE_1); Powerstep01_CmdSetParam(POWERSTEP01_STEP_MODE, (uint8_t)POWERSTEP01_CONF_PARAM_SYNC_MODE_DEVICE_1 | (uint8_t)POWERSTEP01_CONF_PARAM_CM_VM_DEVICE_1| (uint8_t)POWERSTEP01_CONF_PARAM_STEP_MODE_DEVICE_1); Powerstep01_CmdSetParam(POWERSTEP01_ALARM_EN, POWERSTEP01_CONF_PARAM_ALARM_EN_DEVICE_1); Powerstep01_CmdSetParam(POWERSTEP01_GATECFG1, (uint16_t)POWERSTEP01_CONF_PARAM_IGATE_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_TCC_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_TBOOST_DEVICE_1| (uint16_t)POWERSTEP01_CONF_PARAM_WD_EN_DEVICE_1); Powerstep01_CmdSetParam(POWERSTEP01_GATECFG2, (uint16_t)POWERSTEP01_CONF_PARAM_TBLANK_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_TDT_DEVICE_1); // Voltage mode if (cmVm == POWERSTEP01_CM_VM_VOLTAGE) { Powerstep01_CmdSetParam(POWERSTEP01_INT_SPD, int_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_INT_SPD_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_K_THERM, k_therm_comp_to_reg_val( POWERSTEP01_CONF_PARAM_K_THERM_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_STALL_TH, stall_ocd_th_to_reg_val( POWERSTEP01_CONF_PARAM_STALL_TH_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_HOLD, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_HOLD_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_RUN, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_RUN_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_ACC, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_ACC_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_DEC, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_DEC_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_ST_SLP, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_ST_SLP_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_FN_SLP_ACC, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_FN_SLP_ACC_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_FN_SLP_DEC, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_FN_SLP_DEC_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_CONFIG, (uint16_t)POWERSTEP01_CONF_PARAM_CLOCK_SETTING_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_SW_MODE_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_VS_COMP_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_OC_SD_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_UVLOVAL_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_VCCVAL_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_PWM_DIV_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_PWM_MUL_DEVICE_1); } else { // Current mode Powerstep01_CmdSetParam(POWERSTEP01_TVAL_HOLD, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_HOLD_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_RUN, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_RUN_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_ACC, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_ACC_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_DEC, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_DEC_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_T_FAST, (uint8_t)POWERSTEP01_CONF_PARAM_TOFF_FAST_DEVICE_1 | (uint8_t)POWERSTEP01_CONF_PARAM_FAST_STEP_DEVICE_1); Powerstep01_CmdSetParam(POWERSTEP01_TON_MIN, t_min_time_to_reg_val( POWERSTEP01_CONF_PARAM_TON_MIN_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_TOFF_MIN, t_min_time_to_reg_val( POWERSTEP01_CONF_PARAM_TOFF_MIN_DEVICE_1)); Powerstep01_CmdSetParam(POWERSTEP01_CONFIG, (uint16_t)POWERSTEP01_CONF_PARAM_CLOCK_SETTING_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_SW_MODE_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_TQ_REG_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_OC_SD_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_UVLOVAL_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_VCCVAL_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_TSW_DEVICE_1 | (uint16_t)POWERSTEP01_CONF_PARAM_PRED_DEVICE_1); } break; #endif #if (MAX_NUMBER_OF_DEVICES > 2) case 2: cmVm = POWERSTEP01_CONF_PARAM_CM_VM_DEVICE_2; Powerstep01_CmdSetParam(POWERSTEP01_ACC, acc_dec_steps_s2_to_reg_val( POWERSTEP01_CONF_PARAM_ACC_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_DEC, acc_dec_steps_s2_to_reg_val( POWERSTEP01_CONF_PARAM_DEC_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_MAX_SPEED, max_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_MAX_SPEED_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_MIN_SPEED, POWERSTEP01_CONF_PARAM_LSPD_BIT_DEVICE_2| min_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_MIN_SPEED_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_FS_SPD, POWERSTEP01_CONF_PARAM_BOOST_MODE_DEVICE_2| fs_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_FS_SPD_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_OCD_TH, (uint8_t)POWERSTEP01_CONF_PARAM_OCD_TH_DEVICE_2); Powerstep01_CmdSetParam(POWERSTEP01_STEP_MODE, (uint8_t)POWERSTEP01_CONF_PARAM_SYNC_MODE_DEVICE_2 | (uint8_t)POWERSTEP01_CONF_PARAM_CM_VM_DEVICE_2| (uint8_t)POWERSTEP01_CONF_PARAM_STEP_MODE_DEVICE_2); Powerstep01_CmdSetParam(POWERSTEP01_ALARM_EN, POWERSTEP01_CONF_PARAM_ALARM_EN_DEVICE_2); Powerstep01_CmdSetParam(POWERSTEP01_GATECFG1, (uint16_t)POWERSTEP01_CONF_PARAM_IGATE_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_TCC_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_TBOOST_DEVICE_2| (uint16_t)POWERSTEP01_CONF_PARAM_WD_EN_DEVICE_2); Powerstep01_CmdSetParam(POWERSTEP01_GATECFG2, (uint16_t)POWERSTEP01_CONF_PARAM_TBLANK_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_TDT_DEVICE_2); // Voltage mode if (cmVm == POWERSTEP01_CM_VM_VOLTAGE) { Powerstep01_CmdSetParam(POWERSTEP01_INT_SPD, int_spd_steps_s_to_reg_val( POWERSTEP01_CONF_PARAM_INT_SPD_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_K_THERM, k_therm_comp_to_reg_val( POWERSTEP01_CONF_PARAM_K_THERM_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_STALL_TH, stall_ocd_th_to_reg_val( POWERSTEP01_CONF_PARAM_STALL_TH_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_HOLD, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_HOLD_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_RUN, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_RUN_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_ACC, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_ACC_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_KVAL_DEC, k_val_perc_to_reg_val( POWERSTEP01_CONF_PARAM_KVAL_DEC_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_ST_SLP, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_ST_SLP_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_FN_SLP_ACC, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_FN_SLP_ACC_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_FN_SLP_DEC, bemf_slope_perc_to_reg_val( POWERSTEP01_CONF_PARAM_FN_SLP_DEC_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_CONFIG, (uint16_t)POWERSTEP01_CONF_PARAM_CLOCK_SETTING_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_SW_MODE_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_VS_COMP_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_OC_SD_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_UVLOVAL_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_VCCVAL_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_PWM_DIV_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_PWM_MUL_DEVICE_2); } else { // Current mode Powerstep01_CmdSetParam(POWERSTEP01_TVAL_HOLD, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_HOLD_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_RUN, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_RUN_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_ACC, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_ACC_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_TVAL_DEC, t_val_ref_voltage_to_reg_val( POWERSTEP01_CONF_PARAM_TVAL_DEC_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_T_FAST, (uint8_t)POWERSTEP01_CONF_PARAM_TOFF_FAST_DEVICE_2 | (uint8_t)POWERSTEP01_CONF_PARAM_FAST_STEP_DEVICE_2); Powerstep01_CmdSetParam(POWERSTEP01_TON_MIN, t_min_time_to_reg_val( POWERSTEP01_CONF_PARAM_TON_MIN_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_TOFF_MIN, t_min_time_to_reg_val( POWERSTEP01_CONF_PARAM_TOFF_MIN_DEVICE_2)); Powerstep01_CmdSetParam(POWERSTEP01_CONFIG, (uint16_t)POWERSTEP01_CONF_PARAM_CLOCK_SETTING_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_SW_MODE_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_TQ_REG_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_OC_SD_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_UVLOVAL_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_VCCVAL_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_TSW_DEVICE_2 | (uint16_t)POWERSTEP01_CONF_PARAM_PRED_DEVICE_2); } break; #endif default: ; } } /** * @brief Functions to get and set parameters using digital or analog values */ /********************************************************** * @brief Issues the GetParam command to the Powerstep01 device * @param[in] parameter Register adress (POWERSTEP01_ABS_POS, * POWERSTEP01_MARK,...) * @retval Register value **********************************************************/ uint32_t PowerStep01::Powerstep01_CmdGetParam(powerstep01_Registers_t param) { uint32_t spiRxData; uint32_t loop; uint8_t maxArgumentNbBytes = 0; uint8_t spiIndex = numberOfDevices - deviceInstance - 1; bool itDisable = FALSE; do { spiPreemptionByIsr = FALSE; if (itDisable) { /* re-enable Powerstep01_Board_EnableIrq if disable in previous iteration */ Powerstep01_Board_EnableIrq(); itDisable = FALSE; } for (loop = 0; loop < numberOfDevices; loop++) { spiTxBursts[0][loop] = POWERSTEP01_NOP; spiTxBursts[1][loop] = POWERSTEP01_NOP; spiTxBursts[2][loop] = POWERSTEP01_NOP; spiTxBursts[3][loop] = POWERSTEP01_NOP; spiRxBursts[0][loop] = 0; spiRxBursts[1][loop] = 0; spiRxBursts[2][loop] = 0; spiRxBursts[3][loop] = 0; } switch (param) { case POWERSTEP01_ABS_POS: case POWERSTEP01_MARK: case POWERSTEP01_SPEED: spiTxBursts[0][spiIndex] = ((uint8_t)POWERSTEP01_GET_PARAM )| (param); maxArgumentNbBytes = 3; break; case POWERSTEP01_EL_POS: case POWERSTEP01_ACC: case POWERSTEP01_DEC: case POWERSTEP01_MAX_SPEED: case POWERSTEP01_MIN_SPEED: case POWERSTEP01_FS_SPD: case POWERSTEP01_INT_SPD: case POWERSTEP01_CONFIG: case POWERSTEP01_GATECFG1: case POWERSTEP01_STATUS: spiTxBursts[1][spiIndex] = ((uint8_t)POWERSTEP01_GET_PARAM )| (param); maxArgumentNbBytes = 2; break; default: spiTxBursts[2][spiIndex] = ((uint8_t)POWERSTEP01_GET_PARAM )| (param); maxArgumentNbBytes = 1; } /* Disable interruption before checking */ /* pre-emption by ISR and SPI transfers*/ Powerstep01_Board_DisableIrq(); itDisable = TRUE; } while (spiPreemptionByIsr); // check pre-emption by ISR for (loop = POWERSTEP01_CMD_ARG_MAX_NB_BYTES-1-maxArgumentNbBytes; loop < POWERSTEP01_CMD_ARG_MAX_NB_BYTES; loop++) { Powerstep01_WriteBytes(&spiTxBursts[loop][0], &spiRxBursts[loop][0]); } spiRxData = ((uint32_t)spiRxBursts[1][spiIndex] << 16)| (spiRxBursts[2][spiIndex] << 8) | (spiRxBursts[3][spiIndex]); /* re-enable Powerstep01_Board_EnableIrq after SPI transfers*/ Powerstep01_Board_EnableIrq(); return (spiRxData); } /********************************************************** * @brief Issues the SetParam command to the PowerStep01 device * @param[in] parameter Register adress (POWERSTEP01_ABS_POS, * POWERSTEP01_MARK,...) * @param[in] value Value to set in the register * @retval None **********************************************************/ void PowerStep01::Powerstep01_CmdSetParam(powerstep01_Registers_t param, uint32_t value) { uint32_t loop; uint8_t maxArgumentNbBytes = 0; uint8_t spiIndex = numberOfDevices - deviceInstance - 1; bool itDisable = FALSE; do { spiPreemptionByIsr = FALSE; if (itDisable) { /* re-enable Powerstep01_Board_EnableIrq if disable in previous iteration */ Powerstep01_Board_EnableIrq(); itDisable = FALSE; } for (loop = 0;loop < numberOfDevices; loop++) { spiTxBursts[0][loop] = POWERSTEP01_NOP; spiTxBursts[1][loop] = POWERSTEP01_NOP; spiTxBursts[2][loop] = POWERSTEP01_NOP; spiTxBursts[3][loop] = POWERSTEP01_NOP; } switch (param) { case POWERSTEP01_ABS_POS: ; case POWERSTEP01_MARK: spiTxBursts[0][spiIndex] = ((uint8_t)POWERSTEP01_SET_PARAM )| (param); spiTxBursts[1][spiIndex] = (uint8_t)(value >> 16); spiTxBursts[2][spiIndex] = (uint8_t)(value >> 8); maxArgumentNbBytes = 3; break; case POWERSTEP01_EL_POS: case POWERSTEP01_ACC: case POWERSTEP01_DEC: case POWERSTEP01_MAX_SPEED: case POWERSTEP01_MIN_SPEED: case POWERSTEP01_FS_SPD: case POWERSTEP01_INT_SPD: case POWERSTEP01_CONFIG: case POWERSTEP01_GATECFG1: spiTxBursts[1][spiIndex] = ((uint8_t)POWERSTEP01_SET_PARAM )| (param); spiTxBursts[2][spiIndex] = (uint8_t)(value >> 8); maxArgumentNbBytes = 2; break; default: spiTxBursts[2][spiIndex] = ((uint8_t)POWERSTEP01_SET_PARAM )| (param); maxArgumentNbBytes = 1; } spiTxBursts[3][spiIndex] = (uint8_t)(value); /* Disable interruption before checking */ /* pre-emption by ISR and SPI transfers*/ Powerstep01_Board_DisableIrq(); itDisable = TRUE; } while (spiPreemptionByIsr); // check pre-emption by ISR /* SPI transfer */ for (loop = POWERSTEP01_CMD_ARG_MAX_NB_BYTES - 1 - maxArgumentNbBytes; loop < POWERSTEP01_CMD_ARG_MAX_NB_BYTES; loop++) { Powerstep01_WriteBytes(&spiTxBursts[loop][0],&spiRxBursts[loop][0]); } /* re-enable Powerstep01_Board_EnableIrq after SPI transfers*/ Powerstep01_Board_EnableIrq(); } /********************************************************** * @brief Issues PowerStep01 Get Parameter command and convert the result to * float value * @param[in] param PowerStep01 register address * @retval The parameter's float value. *********************************************************/ float PowerStep01::Powerstep01_GetAnalogValue(powerstep01_Registers_t param) { bool voltageMode = ((POWERSTEP01_CM_VM_CURRENT&Powerstep01_CmdGetParam(POWERSTEP01_STEP_MODE))==0); uint32_t registerValue = Powerstep01_CmdGetParam((powerstep01_Registers_t) param); float value; switch (param) { case POWERSTEP01_ABS_POS: case POWERSTEP01_MARK: value = (float) Powerstep01_ConvertPosition(registerValue); break; case POWERSTEP01_ACC: case POWERSTEP01_DEC: value = acc_dec_reg_val_to_steps_s2(registerValue); break; case POWERSTEP01_SPEED: value = speed_reg_val_to_steps_s(registerValue); break; case POWERSTEP01_MAX_SPEED: value = max_spd_reg_val_to_steps_s(registerValue); break; case POWERSTEP01_MIN_SPEED: registerValue &= POWERSTEP01_MIN_SPEED_MASK; value = min_spd_reg_val_to_steps_s(registerValue); break; case POWERSTEP01_FS_SPD: registerValue &= POWERSTEP01_FS_SPD_MASK; value = fs_spd_reg_val_to_steps_s(registerValue); break; case POWERSTEP01_INT_SPD: value = int_spd_reg_val_to_steps_s(registerValue); break; case POWERSTEP01_K_THERM: value = k_therm_reg_val_to_comp(registerValue); break; case POWERSTEP01_OCD_TH: case POWERSTEP01_STALL_TH: value = stall_ocd_reg_val_to_th(registerValue); break; case POWERSTEP01_KVAL_HOLD: //POWERSTEP01_TVAL_HOLD case POWERSTEP01_KVAL_RUN: //POWERSTEP01_TVAL_RUN case POWERSTEP01_KVAL_ACC: //POWERSTEP01_TVAL_ACC case POWERSTEP01_KVAL_DEC: //POWERSTEP01_TVAL_DEC if (voltageMode!=FALSE) value = k_val_reg_val_to_perc(registerValue); else value = k_val_reg_val_to_perc(registerValue); break; case POWERSTEP01_ST_SLP: if (voltageMode==FALSE) { break; } case POWERSTEP01_FN_SLP_ACC: //POWERSTEP01_TON_MIN case POWERSTEP01_FN_SLP_DEC: //POWERSTEP01_TOFF_MIN if (voltageMode!=FALSE) value = bemf_slope_reg_val_to_perc(registerValue); else value = t_min_reg_val_to_time(registerValue); break; default: value = (float) registerValue; } return value; } /******************************************************//** * @brief Put commands in queue before synchronous sending * done by calling Powerstep01_SendQueuedCommands. * Any call to functions that use the SPI between the calls of * Powerstep01_QueueCommands and Powerstep01_SendQueuedCommands * will corrupt the queue. * A command for each device of the daisy chain must be * specified before calling Powerstep01_SendQueuedCommands. * @param[in] command Command to queue (all Powerstep01 commmands * except POWERSTEP01_SET_PARAM, POWERSTEP01_GET_PARAM, * POWERSTEP01_GET_STATUS) * @param[in] value argument of the command to queue * @retval None *********************************************************/ void PowerStep01::Powerstep01_QueueCommands(uint8_t command, int32_t value) { if (numberOfDevices > deviceInstance) { uint8_t spiIndex = numberOfDevices - deviceInstance - 1; switch (command & DAISY_CHAIN_COMMAND_MASK) { case POWERSTEP01_RUN: ; case POWERSTEP01_MOVE: ; case POWERSTEP01_GO_TO: ; case POWERSTEP01_GO_TO_DIR: ; case POWERSTEP01_GO_UNTIL: ; case POWERSTEP01_GO_UNTIL_ACT_CPY: spiTxBursts[0][spiIndex] = command; spiTxBursts[1][spiIndex] = (uint8_t)(value >> 16); spiTxBursts[2][spiIndex] = (uint8_t)(value >> 8); spiTxBursts[3][spiIndex] = (uint8_t)(value); break; default: spiTxBursts[0][spiIndex] = POWERSTEP01_NOP; spiTxBursts[1][spiIndex] = POWERSTEP01_NOP; spiTxBursts[2][spiIndex] = POWERSTEP01_NOP; spiTxBursts[3][spiIndex] = command; } } } /********************************************************** * @brief Sends a command to the device via the SPI * @param[in] command Command to send (all Powerstep01 commmands * except POWERSTEP01_SET_PARAM, POWERSTEP01_GET_PARAM, * POWERSTEP01_GET_STATUS) * @param[in] value arguments to send on 32 bits * @retval None **********************************************************/ void PowerStep01::Powerstep01_SendCommand(uint8_t command, uint32_t value) { uint32_t loop; uint8_t maxArgumentNbBytes = 0; bool itDisable = FALSE; uint8_t spiIndex = numberOfDevices - deviceInstance - 1; do { spiPreemptionByIsr = FALSE; if (itDisable) { /* re-enable Powerstep01_Board_EnableIrq if disable in previous iteration */ Powerstep01_Board_EnableIrq(); itDisable = FALSE; } for (loop = 0; loop < numberOfDevices; loop++) { spiTxBursts[0][loop] = POWERSTEP01_NOP; spiTxBursts[1][loop] = POWERSTEP01_NOP; spiTxBursts[2][loop] = POWERSTEP01_NOP; spiTxBursts[3][loop] = POWERSTEP01_NOP; } switch (command & DAISY_CHAIN_COMMAND_MASK) { case POWERSTEP01_GO_TO: case POWERSTEP01_GO_TO_DIR: value = value & POWERSTEP01_ABS_POS_VALUE_MASK; case POWERSTEP01_RUN: case POWERSTEP01_MOVE: case POWERSTEP01_GO_UNTIL: case POWERSTEP01_GO_UNTIL_ACT_CPY: spiTxBursts[0][spiIndex] = command; spiTxBursts[1][spiIndex] = (uint8_t)(value >> 16); spiTxBursts[2][spiIndex] = (uint8_t)(value >> 8); spiTxBursts[3][spiIndex] = (uint8_t)(value); maxArgumentNbBytes = 3; break; default: spiTxBursts[0][spiIndex] = POWERSTEP01_NOP; spiTxBursts[1][spiIndex] = POWERSTEP01_NOP; spiTxBursts[2][spiIndex] = POWERSTEP01_NOP; spiTxBursts[3][spiIndex] = command; } /* Disable interruption before checking */ /* pre-emption by ISR and SPI transfers*/ Powerstep01_Board_DisableIrq(); itDisable = TRUE; } while (spiPreemptionByIsr); // check pre-emption by ISR for (loop = POWERSTEP01_CMD_ARG_MAX_NB_BYTES - 1 - maxArgumentNbBytes; loop < POWERSTEP01_CMD_ARG_MAX_NB_BYTES; loop++) { Powerstep01_WriteBytes(&spiTxBursts[loop][0], &spiRxBursts[loop][0]); } /* re-enable Powerstep01_Board_EnableIrq after SPI transfers*/ Powerstep01_Board_EnableIrq(); } /******************************************************//** * @brief Sends commands stored previously in the queue by * Powerstep01_QueueCommands * @retval None *********************************************************/ void PowerStep01::Powerstep01_SendQueuedCommands(void) { uint8_t loop; for (loop = 0; loop < POWERSTEP01_CMD_ARG_MAX_NB_BYTES; loop++) { Powerstep01_WriteBytes(&spiTxBursts[loop][0], &spiRxBursts[loop][0]); } } /********************************************************** * @brief Issues the SetParam command to the PowerStep01 * @param[in] param PowerStep01 Register address * @param[in] value Float value to convert and set into the register * @retval TRUE if param is valid, FALSE otherwise *********************************************************/ bool PowerStep01::Powerstep01_SetAnalogValue(powerstep01_Registers_t param, float value) { uint32_t registerValue; bool result = TRUE; bool voltageMode = ((POWERSTEP01_CM_VM_CURRENT&Powerstep01_CmdGetParam(POWERSTEP01_STEP_MODE))==0); if ((value < 0)&&((param != POWERSTEP01_ABS_POS)&&(param != POWERSTEP01_MARK))) { result = FALSE; } switch (param) { case POWERSTEP01_EL_POS: if ((value > (POWERSTEP01_ELPOS_STEP_MASK|POWERSTEP01_ELPOS_MICROSTEP_MASK))|| ((value!=0)&&(value < (1<<(7-(POWERSTEP01_STEP_MODE_STEP_SEL&Powerstep01_CmdGetParam(POWERSTEP01_STEP_MODE))))))) result = FALSE; else registerValue = ((uint32_t) value)&(POWERSTEP01_ELPOS_STEP_MASK|POWERSTEP01_ELPOS_MICROSTEP_MASK); break; case POWERSTEP01_ABS_POS: case POWERSTEP01_MARK: if (value < 0) { value=-value; if (((uint32_t)value)<=(POWERSTEP01_MAX_POSITION+1)) registerValue = (POWERSTEP01_ABS_POS_VALUE_MASK+1-(uint32_t)value)&POWERSTEP01_ABS_POS_VALUE_MASK; else result = FALSE; } else { if (((uint32_t)value)<=POWERSTEP01_MAX_POSITION) registerValue = ((uint32_t) value)&POWERSTEP01_ABS_POS_VALUE_MASK; else result = FALSE; } break; case POWERSTEP01_ACC: case POWERSTEP01_DEC: if (value > POWERSTEP01_ACC_DEC_MAX_VALUE) result = FALSE; else registerValue = acc_dec_steps_s2_to_reg_val(value); break; case POWERSTEP01_MAX_SPEED: if (value > POWERSTEP01_MAX_SPEED_MAX_VALUE) result = FALSE; else registerValue = max_spd_steps_s_to_reg_val(value); break; case POWERSTEP01_MIN_SPEED: if (value > POWERSTEP01_MIN_SPEED_MAX_VALUE) result = FALSE; else registerValue = (POWERSTEP01_LSPD_OPT&Powerstep01_CmdGetParam(param))|min_spd_steps_s_to_reg_val(value); break; case POWERSTEP01_FS_SPD: if (value > POWERSTEP01_FS_SPD_MAX_VALUE) result = FALSE; else registerValue = (POWERSTEP01_BOOST_MODE&Powerstep01_CmdGetParam(param))|fs_spd_steps_s_to_reg_val(value); break; case POWERSTEP01_INT_SPD: if (value > POWERSTEP01_INT_SPD_MAX_VALUE) result = FALSE; else registerValue = int_spd_steps_s_to_reg_val(value); break; case POWERSTEP01_K_THERM: if ((value < POWERSTEP01_K_THERM_MIN_VALUE)|| (value > POWERSTEP01_K_THERM_MAX_VALUE)) result = FALSE; else registerValue = k_therm_comp_to_reg_val(value); break; case POWERSTEP01_OCD_TH: case POWERSTEP01_STALL_TH: if (value > POWERSTEP01_STALL_OCD_TH_MAX_VALUE) result = FALSE; else registerValue = stall_ocd_th_to_reg_val(value); break; case POWERSTEP01_KVAL_HOLD: //POWERSTEP01_TVAL_HOLD case POWERSTEP01_KVAL_RUN: //POWERSTEP01_TVAL_RUN case POWERSTEP01_KVAL_ACC: //POWERSTEP01_TVAL_ACC case POWERSTEP01_KVAL_DEC: //POWERSTEP01_TVAL_DEC if (voltageMode==FALSE) { if (value > POWERSTEP01_TVAL_MAX_VALUE) result = FALSE; else registerValue = t_val_ref_voltage_to_reg_val(value); } else { if (value > POWERSTEP01_KVAL_MAX_VALUE) result = FALSE; else registerValue = k_val_perc_to_reg_val(value); } break; case POWERSTEP01_ST_SLP: if (voltageMode==FALSE) { result = FALSE; break; } case POWERSTEP01_FN_SLP_ACC: //POWERSTEP01_TON_MIN case POWERSTEP01_FN_SLP_DEC: //POWERSTEP01_TOFF_MIN if (voltageMode==FALSE) { if (value>POWERSTEP01_TOFF_TON_MIN_MAX_VALUE) result = FALSE; else registerValue = t_min_time_to_reg_val(value); } else { if (value > POWERSTEP01_SLP_MAX_VALUE) result = FALSE; else registerValue = bemf_slope_perc_to_reg_val(value); } break; default: result = FALSE; } if (result!=FALSE) { Powerstep01_CmdSetParam(param, registerValue); } return result; } /********************************************************** * @brief Write and receive a byte via SPI * @param[in] pByteToTransmit pointer to the byte to transmit * @param[in] pReceivedByte pointer to the received byte * @retval None *********************************************************/ void PowerStep01::Powerstep01_WriteBytes(uint8_t *pByteToTransmit, uint8_t *pReceivedByte) { if (Powerstep01_Board_SpiWriteBytes(pByteToTransmit, pReceivedByte) != 0) { Powerstep01_ErrorHandler(POWERSTEP01_ERROR_1); } if (isrFlag) { spiPreemptionByIsr = TRUE; } } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/