/** ****************************************************************************** * @file dspin.c * @author IPC Rennes * @version V2.0 * @date October 4, 2013 * @brief dSPIN (L6470 and L6472) product related routines * @note (C) COPYRIGHT 2013 STMicroelectronics ****************************************************************************** * @copy * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2013 STMicroelectronics

*/ /* Includes ------------------------------------------------------------------*/ #include "dspin.h" #include "dspin_config.h" #include "stm32f10x_spi.h" /** @addtogroup dSPIN FW library interface * @{ */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ static GPIO_InitTypeDef GPIO_InitStructure; static SPI_InitTypeDef SPI_InitStructure; static uint8_t spiTxBursts[dSPIN_CMD_ARG_MAX_NB_BYTES][NUMBER_OF_SLAVES]; static uint8_t spiRxBursts[dSPIN_CMD_ARG_MAX_NB_BYTES][NUMBER_OF_SLAVES]; static uint8_t arrayTxBytes[NUMBER_OF_SLAVES]; static uint32_t arrayValues[NUMBER_OF_SLAVES]; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** * @brief Inserts a delay time. * @param nCount specifies the delay time length. * @retval None */ void dSPIN_Delay(__IO uint32_t nCount) { for (; nCount != 0; nCount--); } /** * @brief Resets DSPIN and puts it into standby mode * @param None * @retval None */ void dSPIN_Reset_And_Standby(void) { #if (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) GPIO_ResetBits(dSPIN_STBY_RESET_Port, dSPIN_STBY_RESET_Pin); dSPIN_Delay(10000); GPIO_SetBits(dSPIN_STBY_RESET_Port, dSPIN_STBY_RESET_Pin); #endif /* (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) */ } /** * @brief Toggles a GPIO output * @param GPIOx gpio port * @param GPIO_Pin pin number of the Gpio to toggle * @retval None */ void dSPIN_Gpio_Toggle(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { if (GPIO_ReadOutputDataBit(GPIOx, GPIO_Pin) != Bit_RESET) { GPIO_ResetBits(GPIOx, GPIO_Pin); } else { GPIO_SetBits(GPIOx, GPIO_Pin); } } /** * @brief Initializes uC peripherals, GPIOs, clocks, interrupts channels used by dSPIN. * @param None * @retval None */ void dSPIN_Peripherals_Init(void) { /* Used peripherals clock enable -------------------------------------------*/ RCC_APB1PeriphClockCmd(dSPIN_PERIPHERAL_CLKs_APB1, ENABLE); RCC_APB2PeriphClockCmd(dSPIN_PERIPHERAL_CLKs_APB2, ENABLE); /* Configure pins used by dSPIN --------------------------------------------*/ #if (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) /* Configure on-board power LED ------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = POWER_LED_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(POWER_LED_Port, &GPIO_InitStructure); // GPIO_SetBits(POWER_LED_Port, POWER_LED_Pin); /* Configure on-board status LED -----------------------------------------*/ GPIO_InitStructure.GPIO_Pin = STATUS_LED_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(STATUS_LED_Port, &GPIO_InitStructure); /* Configure STBY_RESET GPIO connected to dSPIN STBY_RESET pin*/ GPIO_InitStructure.GPIO_Pin = dSPIN_STBY_RESET_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(dSPIN_STBY_RESET_Port, &GPIO_InitStructure); #endif /* (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) */ #ifdef STEVAL_PCC009V2 /* Only if PCC009V2 evalboard is used ---------------*/ /* Configure Port C GPIO pin 2 connected to keypad button "*" */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Configure Port C GPIO pin 3 connected to keypad button "7" */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Configure Port C GPIO pin 6 connected to keypad button "4" */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOC, &GPIO_InitStructure); #endif /* STEVAL_PCC009V2 */ #ifdef ST_DSPIN_6470H_DISCOVERY /* Only if DISCOVERY board is used -----------*/ /* Configure on-board busy LED -----------------------------------------*/ GPIO_InitStructure.GPIO_Pin = LED_BUSY_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(LED_BUSY_Port, &GPIO_InitStructure); /* Configure on-board spare LED --------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = LED_SPARE_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(LED_SPARE_Port, &GPIO_InitStructure); /* Configure GPIO connected to S1 button via BUTTON_A wire */ GPIO_InitStructure.GPIO_Pin = BUTTON_A_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(BUTTON_A_Port, &GPIO_InitStructure); /* Configure GPIO connected to S3 button via BUTTON_B wire */ GPIO_InitStructure.GPIO_Pin = BUTTON_B_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(BUTTON_B_Port, &GPIO_InitStructure); /* Configure SW_MOTOR GPIO connected to J8 jumper */ GPIO_InitStructure.GPIO_Pin = SW_MOTOR_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(SW_MOTOR_Port, &GPIO_InitStructure); /* Configure SW GPIO connected to dSPIN SW pin*/ GPIO_InitStructure.GPIO_Pin = dSPIN_SW_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(dSPIN_SW_Port, &GPIO_InitStructure); GPIO_SetBits(dSPIN_SW_Port, dSPIN_SW_Pin); #endif /* ST_DSPIN_6470H_DISCOVERY */ /* Configure SPI pin: SCK --------------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = dSPIN_SCK_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(dSPIN_SCK_Port, &GPIO_InitStructure); /* Configure SPI pin: MOSI -------------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = dSPIN_MOSI_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(dSPIN_MOSI_Port, &GPIO_InitStructure); /* Configure SPI pin: nSS --------------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = dSPIN_nSS_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(dSPIN_nSS_Port, &GPIO_InitStructure); /* Configure SPI pin: MISO -------------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = dSPIN_MISO_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(dSPIN_MISO_Port, &GPIO_InitStructure); /* Configure dSPIN - Busy pin ----------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = dSPIN_BUSY_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(dSPIN_BUSY_Port, &GPIO_InitStructure); /* Configure dSPIN - Flag pin ----------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = dSPIN_FLAG_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(dSPIN_FLAG_Port, &GPIO_InitStructure); /* Configure PWM connected to dSPin STCK -----------------------------------*/ GPIO_InitStructure.GPIO_Pin = dSPIN_PWM1_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(dSPIN_PWM1_Port, &GPIO_InitStructure); /* SPI configuration ------------------------------------------------------*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(dSPIN_SPI, &SPI_InitStructure); /* Enable SPI */ SPI_Cmd(dSPIN_SPI, ENABLE); /* Interrupt Channel configuration and enable */ dSPIN_Interrupt_Channel_Config(); } /** * @brief Interrupt channel configuration and enable * @param None * @retval None */ void dSPIN_Interrupt_Channel_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; #if (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif /* (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) */ #if defined(STEVAL_PCC009V2) NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif /* defined(STEVAL_PCC009V2) */ #if defined(ST_DSPIN_6470H_DISCOVERY) NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif /* defined(ST_DSPIN_6470H_DISCOVERY) */ } /** * @brief Led On and Off * @param None * @retval None */ void dSPIN_Led_Check(void) { #ifdef STEVAL_PCC009V2 /* Only if PCC009V2 evalboard is used ---------------*/ dSPIN_Delay(0x00100000); GPIO_SetBits(STATUS_LED_Port, STATUS_LED_Pin); dSPIN_Delay(0x00100000); GPIO_ResetBits(STATUS_LED_Port, STATUS_LED_Pin); dSPIN_Delay(0x00100000); #endif /* STEVAL_PCC009V2 */ #ifdef ST_DSPIN_6470H_DISCOVERY /* Only if DISCOVERY board is used -----------*/ dSPIN_Delay(0x00100000); GPIO_SetBits(STATUS_LED_Port, STATUS_LED_Pin); dSPIN_Delay(0x00100000); GPIO_SetBits(LED_BUSY_Port, LED_BUSY_Pin); dSPIN_Delay(0x00100000); GPIO_SetBits(LED_SPARE_Port, LED_SPARE_Pin); dSPIN_Delay(0x00100000); GPIO_ResetBits(STATUS_LED_Port, STATUS_LED_Pin); GPIO_ResetBits(LED_BUSY_Port, LED_BUSY_Pin); GPIO_ResetBits(LED_SPARE_Port, LED_SPARE_Pin); dSPIN_Delay(0x00100000); #endif /* ST_DSPIN_6470H_DISCOVERY */ } /** * @brief GPIO config to manage FLAG signal as an interrupt * @param None * @retval None */ void dSPIN_Flag_Interrupt_GPIO_Config(void) { EXTI_InitTypeDef EXTI_InitStructure; #if defined(STEVAL_PCC009V2) /* Selects the GPIO pin 11 to be used as an EXTI Line */ /* STM32F10X PB11 pin connected to L6470 FLAG pin */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11); /* Configure EXTI Line11 to generate an interrupt on rising and falling edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line11; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line11); #endif /* defined(STEVAL_PCC009V2) */ #if defined(ST_DSPIN_6470H_DISCOVERY) /* Selects the GPIO pin 10 to be used as an EXTI Line */ /* STM32F10X PB10 pin connected to L6470 BUSY\SYNC pin */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource10); /* Configure EXTI Line10 to generate an interrupt on falling edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line10; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line10); #endif /* defined(ST_DSPIN_6470H_DISCOVERY) */ } /** * @brief GPIO config to manage BUSY signal as an interrupt * @param None * @retval None */ void dSPIN_Busy_Interrupt_GPIO_Config(void) { EXTI_InitTypeDef EXTI_InitStructure; #if defined(STEVAL_PCC009V2) /* Selects the GPIO pin 10 to be used as an EXTI Line */ /* STM32F10X PB10 pin connected to L6470 BUSY\SYNC pin */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource10); /* Configure EXTI Line10 to generate an interrupt on falling edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line10; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line10); #endif /* defined(STEVAL_PCC009V2) */ #if defined(ST_DSPIN_6470H_DISCOVERY) /* Selects the GPIO pin 11 to be used as an EXTI Line */ /* STM32F10X PB11 pin connected to L6470 BUSY\SYNC pin */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11); /* Configure EXTI Line11 to generate an interrupt on rising and falling edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line11; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line11); #endif /* defined(ST_DSPIN_6470H_DISCOVERY) */ } /** * @brief Disabling of external line interrupt corresponding to BUSY\SYNC GPIO * @param None * @retval None */ void dSPIN_Busy_Interrupt_GPIO_DeConfig(void) { EXTI_InitTypeDef EXTI_InitStructure; #if defined(STEVAL_PCC009V2) /* Disable EXTI Line10 interrupt */ EXTI_InitStructure.EXTI_Line = EXTI_Line10; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_LineCmd = DISABLE; EXTI_Init(&EXTI_InitStructure); #endif /* defined(STEVAL_PCC009V2) */ #if defined(ST_DSPIN_6470H_DISCOVERY) /* Disable EXTI Line11 interrupt */ EXTI_InitStructure.EXTI_Line = EXTI_Line11; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_LineCmd = DISABLE; EXTI_Init(&EXTI_InitStructure); #endif /* defined(ST_DSPIN_6470H_DISCOVERY) */ } /** * @brief Board buttons GPIO configuration to be used as EXTI lines * and config of the EXTI lines. * @param None * @retval None */ void dSPIN_Buttons_Interrupts_GPIO_Config(void) { EXTI_InitTypeDef EXTI_InitStructure; #if defined(STEVAL_PCC009V2) /* Selects the Port C GPIO pins 2, 3 and 6 to be used as EXTI Lines */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2); GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3); GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource6); /* Configure EXTI Line2 to generate an interrupt on rising edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line2; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line2); /* Configure EXTI Line3 to generate an interrupt on rising edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line3; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line3); /* Configure EXTI Line6 to generate an interrupt on rising edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line6; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line6); #endif /* defined(STEVAL_PCC009V2) */ #if defined(ST_DSPIN_6470H_DISCOVERY) /* Select the Port A GPIO pins 1 and 2 to be used as EXTI Lines */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2); /* Configure EXTI Line1 to generate an interrupt on rising edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line1; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line1); /* Configure EXTI Line2 to generate an interrupt on rising edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line2; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line2); #endif /* defined(ST_DSPIN_6470H_DISCOVERY) */ } /** * @brief Switch motor GPIO configuration to be used as EXTI line * and config of the EXTI line. * @param None * @retval None */ void dSPIN_Switch_Motor_Interrupt_Config(void) { #if defined(ST_DSPIN_6470H_DISCOVERY) EXTI_InitTypeDef EXTI_InitStructure; /* Select the Port A GPIO pin 0 as EXTI Line */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); /* Configure EXTI Line0 to generate an interrupt on falling and rising edge */ EXTI_InitStructure.EXTI_Line = EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); EXTI_ClearITPendingBit(EXTI_Line0); #endif /* defined(ST_DSPIN_6470H_DISCOVERY) */ } /** * @brief Enable a PWM on the STCK pin from STM32 * @param Period to be set (PWM Freq = 1MHZ/Period) * @retval None */ void dSPIN_PWM_Enable(uint16_t Period) { #if (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; RCC_ClocksTypeDef RCC_Clocks; /*Get System Clock frequency */ RCC_GetClocksFreq(&RCC_Clocks); /* Time base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct); /* Set Prescaler to have a timer clock of 1MHZ */ TIM_TimeBaseInitStruct.TIM_Prescaler = (RCC_Clocks.SYSCLK_Frequency / 1000000) - 1; /* PWM Frequency will be equal to 1MHZ/Period */ TIM_TimeBaseInitStruct.TIM_Period = Period - 1; TIM_TimeBaseInit(TIM_PWM, &TIM_TimeBaseInitStruct); /* PWM1 Mode configuration */ TIM_OCStructInit(&TIM_OCInitStruct); TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_Pulse = Period / 2; //range from 0 to TIM_Period, //50% duty cycle is equal to Period/2 #if defined(STEVAL_PCC009V2) /* Channel 3 */ TIM_OC3Init(TIM_PWM, &TIM_OCInitStruct); #endif #if defined(ST_DSPIN_6470H_DISCOVERY) /* Channel 4 */ TIM_OC4Init(TIM_PWM, &TIM_OCInitStruct); #endif /* TIM_PWM enable or disable counter */ TIM_Cmd(TIM_PWM, ENABLE); #endif /* (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) */ } /** * @brief Disable PWM on the STCK pin from STM32 * @param None * @retval None */ void dSPIN_PWM_DISABLE(void) { #if (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) /* TIM_PWM disable counter */ TIM_Cmd(TIM_PWM, DISABLE); #endif /* (defined(STEVAL_PCC009V2) || defined(ST_DSPIN_6470H_DISCOVERY)) */ } /** * @brief Fills-in dSPIN configuration structure with default values. * @param dSPIN_RegsStruct structure address (pointer to struct) * @retval None */ void dSPIN_Regs_Struct_Reset(dSPIN_RegsStruct_TypeDef* dSPIN_RegsStruct) { dSPIN_RegsStruct->ABS_POS = 0; dSPIN_RegsStruct->EL_POS = 0; dSPIN_RegsStruct->MARK = 0; dSPIN_RegsStruct->ACC = 0x08A; dSPIN_RegsStruct->DEC = 0x08A; dSPIN_RegsStruct->MAX_SPEED = 0x041; dSPIN_RegsStruct->MIN_SPEED = 0; dSPIN_RegsStruct->FS_SPD = 0x027; #if defined(L6470) dSPIN_RegsStruct->KVAL_HOLD = 0x29; dSPIN_RegsStruct->KVAL_RUN = 0x29; dSPIN_RegsStruct->KVAL_ACC = 0x29; dSPIN_RegsStruct->KVAL_DEC = 0x29; dSPIN_RegsStruct->INT_SPD = 0x0408; dSPIN_RegsStruct->ST_SLP = 0x19; dSPIN_RegsStruct->FN_SLP_ACC = 0x29; dSPIN_RegsStruct->FN_SLP_DEC = 0x29; dSPIN_RegsStruct->K_THERM = 0; dSPIN_RegsStruct->STALL_TH = 0x40; #endif /* defined(L6470) */ #if defined(L6472) dSPIN_RegsStruct->TVAL_HOLD = 0x29; dSPIN_RegsStruct->TVAL_RUN = 0x29; dSPIN_RegsStruct->TVAL_ACC = 0x29; dSPIN_RegsStruct->TVAL_DEC = 0x29; dSPIN_RegsStruct->T_FAST = 0x19; dSPIN_RegsStruct->TON_MIN = 0x29; dSPIN_RegsStruct->TOFF_MIN = 0x29; #endif /* defined(L6472) */ dSPIN_RegsStruct->OCD_TH = 0x8; dSPIN_RegsStruct->STEP_MODE = 0x7; dSPIN_RegsStruct->ALARM_EN = 0xFF; dSPIN_RegsStruct->CONFIG = 0x2E88; } /** * @brief Configures dSPIN internal registers with values in the config structure. * @param dSPIN_RegsStruct Configuration structure address (pointer to configuration structure) * @retval None */ void dSPIN_Registers_Set(dSPIN_RegsStruct_TypeDef* dSPIN_RegsStruct) { dSPIN_Set_Param(dSPIN_ABS_POS, dSPIN_RegsStruct->ABS_POS); dSPIN_Set_Param(dSPIN_EL_POS, dSPIN_RegsStruct->EL_POS); dSPIN_Set_Param(dSPIN_MARK, dSPIN_RegsStruct->MARK); dSPIN_Set_Param(dSPIN_ACC, dSPIN_RegsStruct->ACC); dSPIN_Set_Param(dSPIN_DEC, dSPIN_RegsStruct->DEC); dSPIN_Set_Param(dSPIN_MAX_SPEED, dSPIN_RegsStruct->MAX_SPEED); dSPIN_Set_Param(dSPIN_MIN_SPEED, dSPIN_RegsStruct->MIN_SPEED); dSPIN_Set_Param(dSPIN_FS_SPD, dSPIN_RegsStruct->FS_SPD); #if defined(L6470) dSPIN_Set_Param(dSPIN_KVAL_HOLD, dSPIN_RegsStruct->KVAL_HOLD); dSPIN_Set_Param(dSPIN_KVAL_RUN, dSPIN_RegsStruct->KVAL_RUN); dSPIN_Set_Param(dSPIN_KVAL_ACC, dSPIN_RegsStruct->KVAL_ACC); dSPIN_Set_Param(dSPIN_KVAL_DEC, dSPIN_RegsStruct->KVAL_DEC); dSPIN_Set_Param(dSPIN_INT_SPD, dSPIN_RegsStruct->INT_SPD); dSPIN_Set_Param(dSPIN_ST_SLP, dSPIN_RegsStruct->ST_SLP); dSPIN_Set_Param(dSPIN_FN_SLP_ACC, dSPIN_RegsStruct->FN_SLP_ACC); dSPIN_Set_Param(dSPIN_FN_SLP_DEC, dSPIN_RegsStruct->FN_SLP_DEC); dSPIN_Set_Param(dSPIN_K_THERM, dSPIN_RegsStruct->K_THERM); dSPIN_Set_Param(dSPIN_STALL_TH, dSPIN_RegsStruct->STALL_TH); #endif /* defined(L6470) */ #if defined(L6472) dSPIN_Set_Param(dSPIN_TVAL_HOLD, dSPIN_RegsStruct->TVAL_HOLD); dSPIN_Set_Param(dSPIN_TVAL_RUN, dSPIN_RegsStruct->TVAL_RUN); dSPIN_Set_Param(dSPIN_TVAL_ACC, dSPIN_RegsStruct->TVAL_ACC); dSPIN_Set_Param(dSPIN_TVAL_DEC, dSPIN_RegsStruct->TVAL_DEC); dSPIN_Set_Param(dSPIN_T_FAST, dSPIN_RegsStruct->T_FAST); dSPIN_Set_Param(dSPIN_TON_MIN, dSPIN_RegsStruct->TON_MIN); dSPIN_Set_Param(dSPIN_TOFF_MIN, dSPIN_RegsStruct->TOFF_MIN); #endif /* defined(L6472) */ dSPIN_Set_Param(dSPIN_OCD_TH, dSPIN_RegsStruct->OCD_TH); dSPIN_Set_Param(dSPIN_STEP_MODE, dSPIN_RegsStruct->STEP_MODE); dSPIN_Set_Param(dSPIN_ALARM_EN, dSPIN_RegsStruct->ALARM_EN); dSPIN_Set_Param(dSPIN_CONFIG, dSPIN_RegsStruct->CONFIG); } /** * @brief Issues dSPIN NOP command. * @param None * @retval None */ void dSPIN_Nop(void) { /* Send NOP operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_NOP); } /** * @brief Issues dSPIN Set Param command. * @param param dSPIN register address * @param value to be set * @retval None */ void dSPIN_Set_Param(dSPIN_Registers_TypeDef param, uint32_t value) { /* Send SetParam operation code to dSPIN */ dSPIN_Write_Byte((uint8_t)dSPIN_SET_PARAM | (uint8_t)param); switch (param) { case dSPIN_ABS_POS: ; case dSPIN_MARK: ; /* Send parameter - byte 2 to dSPIN */ dSPIN_Write_Byte((uint8_t)(value >> 16)); case dSPIN_EL_POS: ; case dSPIN_ACC: ; case dSPIN_DEC: ; case dSPIN_MAX_SPEED: ; case dSPIN_MIN_SPEED: ; case dSPIN_FS_SPD: ; #if defined(L6470) case dSPIN_INT_SPD: ; #endif /* defined(L6470) */ case dSPIN_CONFIG: ; case dSPIN_STATUS: /* Send parameter - byte 1 to dSPIN */ dSPIN_Write_Byte((uint8_t)(value >> 8)); default: /* Send parameter - byte 0 to dSPIN */ dSPIN_Write_Byte((uint8_t)(value)); } } /** * @brief Issues dSPIN Get Param command. * @param param dSPIN register address * @retval Register value - 1 to 3 bytes (depends on register) */ uint32_t dSPIN_Get_Param(dSPIN_Registers_TypeDef param) { uint32_t temp = 0; uint32_t rx = 0; /* Send GetParam operation code to dSPIN */ temp = dSPIN_Write_Byte((uint8_t)dSPIN_GET_PARAM | (uint8_t)param); /* MSB which should be 0 */ temp = temp << 24; rx |= temp; switch (param) { case dSPIN_ABS_POS: ; case dSPIN_MARK: ; case dSPIN_SPEED: temp = dSPIN_Write_Byte((uint8_t)(0x00)); temp = temp << 16; rx |= temp; case dSPIN_EL_POS: ; case dSPIN_ACC: ; case dSPIN_DEC: ; case dSPIN_MAX_SPEED: ; case dSPIN_MIN_SPEED: ; case dSPIN_FS_SPD: ; #if defined(L6470) case dSPIN_INT_SPD: ; #endif /* defined(L6470) */ case dSPIN_CONFIG: ; case dSPIN_STATUS: temp = dSPIN_Write_Byte((uint8_t)(0x00)); temp = temp << 8; rx |= temp; default: temp = dSPIN_Write_Byte((uint8_t)(0x00)); rx |= temp; } return rx; } /** * @brief Issues dSPIN Run command. * @param direction Movement direction (FWD, REV) * @param speed over 3 bytes * @retval None */ void dSPIN_Run(dSPIN_Direction_TypeDef direction, uint32_t speed) { /* Send RUN operation code to dSPIN */ dSPIN_Write_Byte((uint8_t)dSPIN_RUN | (uint8_t)direction); /* Send speed - byte 2 data dSPIN */ dSPIN_Write_Byte((uint8_t)(speed >> 16)); /* Send speed - byte 1 data dSPIN */ dSPIN_Write_Byte((uint8_t)(speed >> 8)); /* Send speed - byte 0 data dSPIN */ dSPIN_Write_Byte((uint8_t)(speed)); } /** * @brief Issues dSPIN Step Clock command. * @param direction Movement direction (FWD, REV) * @retval None */ void dSPIN_Step_Clock(dSPIN_Direction_TypeDef direction) { /* Send StepClock operation code to dSPIN */ dSPIN_Write_Byte((uint8_t)dSPIN_STEP_CLOCK | (uint8_t)direction); } /** * @brief Issues dSPIN Move command. * @param direction mMovement direction * @param n_step number of steps * @retval None */ void dSPIN_Move(dSPIN_Direction_TypeDef direction, uint32_t n_step) { /* Send Move operation code to dSPIN */ dSPIN_Write_Byte((uint8_t)dSPIN_MOVE | (uint8_t)direction); /* Send n_step - byte 2 data dSPIN */ dSPIN_Write_Byte((uint8_t)(n_step >> 16)); /* Send n_step - byte 1 data dSPIN */ dSPIN_Write_Byte((uint8_t)(n_step >> 8)); /* Send n_step - byte 0 data dSPIN */ dSPIN_Write_Byte((uint8_t)(n_step)); } /** * @brief Issues dSPIN Go To command. * @param abs_pos absolute position where requested to move * @retval None */ void dSPIN_Go_To(uint32_t abs_pos) { /* Send GoTo operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_GO_TO); /* Send absolute position parameter - byte 2 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(abs_pos >> 16)); /* Send absolute position parameter - byte 1 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(abs_pos >> 8)); /* Send absolute position parameter - byte 0 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(abs_pos)); } /** * @brief Issues dSPIN Go To Dir command. * @param direction movement direction * @param abs_pos absolute position where requested to move * @retval None */ void dSPIN_Go_To_Dir(dSPIN_Direction_TypeDef direction, uint32_t abs_pos) { /* Send GoTo_DIR operation code to dSPIN */ dSPIN_Write_Byte((uint8_t)dSPIN_GO_TO_DIR | (uint8_t)direction); /* Send absolute position parameter - byte 2 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(abs_pos >> 16)); /* Send absolute position parameter - byte 1 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(abs_pos >> 8)); /* Send absolute position parameter - byte 0 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(abs_pos)); } /** * @brief Issues dSPIN Go Until command. * @param action * @param direction movement direction * @param speed * @retval None */ void dSPIN_Go_Until(dSPIN_Action_TypeDef action, dSPIN_Direction_TypeDef direction, uint32_t speed) { /* Send GoUntil operation code to dSPIN */ dSPIN_Write_Byte((uint8_t)dSPIN_GO_UNTIL | (uint8_t)action | (uint8_t)direction); /* Send speed parameter - byte 2 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(speed >> 16)); /* Send speed parameter - byte 1 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(speed >> 8)); /* Send speed parameter - byte 0 data to dSPIN */ dSPIN_Write_Byte((uint8_t)(speed)); } /** * @brief Issues dSPIN Release SW command. * @param action * @param direction movement direction * @retval None */ void dSPIN_Release_SW(dSPIN_Action_TypeDef action, dSPIN_Direction_TypeDef direction) { /* Send ReleaseSW operation code to dSPIN */ dSPIN_Write_Byte((uint8_t)dSPIN_RELEASE_SW | (uint8_t)action | (uint8_t)direction); } /** * @brief Issues dSPIN Go Home command. (Shorted path to zero position) * @param None * @retval None */ void dSPIN_Go_Home(void) { /* Send GoHome operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_GO_HOME); } /** * @brief Issues dSPIN Go Mark command. * @param None * @retval None */ void dSPIN_Go_Mark(void) { /* Send GoMark operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_GO_MARK); } /** * @brief Issues dSPIN Reset Pos command. * @param None * @retval None */ void dSPIN_Reset_Pos(void) { /* Send ResetPos operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_RESET_POS); } /** * @brief Issues dSPIN Reset Device command. * @param None * @retval None */ void dSPIN_Reset_Device(void) { /* Send ResetDevice operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_RESET_DEVICE); } /** * @brief Issues dSPIN Soft Stop command. * @param None * @retval None */ void dSPIN_Soft_Stop(void) { /* Send SoftStop operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_SOFT_STOP); } /** * @brief Issues dSPIN Hard Stop command. * @param None * @retval None */ void dSPIN_Hard_Stop(void) { /* Send HardStop operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_HARD_STOP); } /** * @brief Issues dSPIN Soft HiZ command. * @param None * @retval None */ void dSPIN_Soft_HiZ(void) { /* Send SoftHiZ operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_SOFT_HIZ); } /** * @brief Issues dSPIN Hard HiZ command. * @param None * @retval None */ void dSPIN_Hard_HiZ(void) { /* Send HardHiZ operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_HARD_HIZ); } /** * @brief Issues dSPIN Get Status command. * @param None * @retval Status Register content */ uint16_t dSPIN_Get_Status(void) { uint16_t temp = 0; uint16_t rx = 0; /* Send GetStatus operation code to dSPIN */ dSPIN_Write_Byte(dSPIN_GET_STATUS); /* Send zero byte / receive MSByte from dSPIN */ temp = dSPIN_Write_Byte((uint8_t)(0x00)); temp = temp << 8; rx |= temp; /* Send zero byte / receive LSByte from dSPIN */ temp = dSPIN_Write_Byte((uint8_t)(0x00)); rx |= temp; return rx; } /** * @brief Checks if the dSPIN is Busy by hardware - active Busy signal. * @param None * @retval one if chip is busy, otherwise zero */ uint8_t dSPIN_Busy_HW(void) { if (!(GPIO_ReadInputDataBit(dSPIN_BUSY_Port, dSPIN_BUSY_Pin))) return 0x01; else return 0x00; } /** * @brief Checks if the dSPIN is Busy by SPI - Busy flag bit in Status Register. * @param None * @retval one if chip is busy, otherwise zero */ uint8_t dSPIN_Busy_SW(void) { if (!(dSPIN_Get_Status() & dSPIN_STATUS_BUSY)) return 0x01; else return 0x00; } /** * @brief Checks dSPIN Flag signal. * @param None * @retval one if Flag signal is active, otherwise zero */ uint8_t dSPIN_Flag(void) { if (!(GPIO_ReadInputDataBit(dSPIN_FLAG_Port, dSPIN_FLAG_Pin))) return 0x01; else return 0x00; } /** * @brief Transmits/Receives one byte to/from dSPIN over SPI. * @param byte Transmited byte * @retval Received byte */ uint8_t dSPIN_Write_Byte(uint8_t byte) { /* nSS signal activation - low */ GPIO_ResetBits(dSPIN_nSS_Port, dSPIN_nSS_Pin); /* SPI byte send */ SPI_I2S_SendData(dSPIN_SPI, byte); /* Wait for SPIx Busy flag */ while (SPI_I2S_GetFlagStatus(dSPIN_SPI, SPI_I2S_FLAG_BSY) != RESET); /* nSS signal deactivation - high */ GPIO_SetBits(dSPIN_nSS_Port, dSPIN_nSS_Pin); return (uint8_t)(SPI_I2S_ReceiveData(dSPIN_SPI)); } /** * @brief Transmits/Receives several bytes to dSPIN over SPI * @param pTxByte pTxBytePointer to TX bytes * @param pRxByte Pointer to RX bytes * @param nBytes Number of TX = RX bytes * @retval None */ void dSPIN_Write_Daisy_Chain_Bytes(uint8_t *pTxByte, uint8_t *pRxByte, uint8_t nBytes) { uint32_t index; /* nSS signal activation - low */ GPIO_ResetBits(dSPIN_nSS_Port, dSPIN_nSS_Pin); /* SPI byte send */ for (index = 0; index < nBytes; index++) { SPI_I2S_SendData(dSPIN_SPI, *pTxByte); /* Wait for SPIx Busy flag */ while (SPI_I2S_GetFlagStatus(dSPIN_SPI, SPI_I2S_FLAG_BSY) != RESET); *pRxByte = SPI_I2S_ReceiveData(dSPIN_SPI); pTxByte++; pRxByte++; } /* nSS signal deactivation - high */ GPIO_SetBits(dSPIN_nSS_Port, dSPIN_nSS_Pin); } /** * @brief Issues dSPIN Set Param command to each device (slave). * @param slaves_number number of slaves * @param pParam Pointer to an array of dSPIN register address * @param pValue Pointer to an array of dSPIN parameter value * @retval None */ void dSPIN_All_Slaves_Set_Param(uint8_t slaves_number, uint8_t *pParam, uint32_t *pValue) { uint32_t i; uint8_t maxArgumentNbBytes = 0; for (i = 0; i < slaves_number; i++) { switch (*pParam) { case dSPIN_ABS_POS: ; case dSPIN_MARK: ; case dSPIN_SPEED: spiTxBursts[0][i] = *pParam; spiTxBursts[1][i] = (uint8_t)(*pValue >> 16); spiTxBursts[2][i] = (uint8_t)(*pValue >> 8); maxArgumentNbBytes = 3; break; case dSPIN_EL_POS: ; case dSPIN_ACC: ; case dSPIN_DEC: ; case dSPIN_MAX_SPEED: ; case dSPIN_MIN_SPEED: ; case dSPIN_FS_SPD: ; #if defined(L6470) case dSPIN_INT_SPD: ; #endif /* defined(L6470) */ case dSPIN_CONFIG: ; case dSPIN_STATUS: spiTxBursts[0][i] = dSPIN_NOP; spiTxBursts[1][i] = *pParam; spiTxBursts[2][i] = (uint8_t)(*pValue >> 8); if (maxArgumentNbBytes < 2) { maxArgumentNbBytes = 2; } break; default: spiTxBursts[0][i] = dSPIN_NOP; spiTxBursts[1][i] = dSPIN_NOP; spiTxBursts[2][i] = *pParam; if (maxArgumentNbBytes < 1) { maxArgumentNbBytes = 1; } } spiTxBursts[3][i] = (uint8_t)(*pValue); pParam++; pValue++; } for (i = dSPIN_CMD_ARG_MAX_NB_BYTES - 1 - maxArgumentNbBytes; i < dSPIN_CMD_ARG_MAX_NB_BYTES; i++) { dSPIN_Write_Daisy_Chain_Bytes(&spiTxBursts[i][0], &spiRxBursts[i][0], slaves_number); } } /** * @brief Issues dSPIN Get Param command to each device (slave). * @param slaves_number number of slaves * @param pParam Pointer to an array of dSPIN register address * @param pValue Pointer to an array of dSPIN parameter value * @retval None */ void dSPIN_All_Slaves_Get_Param(uint8_t slaves_number, uint8_t *pParam, uint32_t *pValue) { uint32_t i; uint8_t maxArgumentNbBytes = 0; for (i = 0; i < slaves_number; i++) { switch (*pParam) { case dSPIN_ABS_POS: ; case dSPIN_MARK: ; case dSPIN_SPEED: spiTxBursts[0][i] = ((uint8_t)dSPIN_GET_PARAM) | (*pParam); spiTxBursts[1][i] = dSPIN_NOP; spiTxBursts[2][i] = dSPIN_NOP; maxArgumentNbBytes = 3; break; case dSPIN_EL_POS: ; case dSPIN_ACC: ; case dSPIN_DEC: ; case dSPIN_MAX_SPEED: ; case dSPIN_MIN_SPEED: ; case dSPIN_FS_SPD: ; #if defined(L6470) case dSPIN_INT_SPD: ; #endif /* defined(L6470) */ case dSPIN_CONFIG: ; case dSPIN_STATUS: spiTxBursts[0][i] = dSPIN_NOP; spiTxBursts[1][i] = ((uint8_t)dSPIN_GET_PARAM) | (*pParam); spiTxBursts[2][i] = dSPIN_NOP; if (maxArgumentNbBytes < 2) { maxArgumentNbBytes = 2; } break; default: spiTxBursts[0][i] = dSPIN_NOP; spiTxBursts[1][i] = dSPIN_NOP; spiTxBursts[2][i] = ((uint8_t)dSPIN_GET_PARAM) | (*pParam); if (maxArgumentNbBytes < 1) { maxArgumentNbBytes = 1; } } spiTxBursts[3][i] = dSPIN_NOP; spiRxBursts[1][i] = 0; spiRxBursts[2][i] = 0; spiRxBursts[3][i] = 0; pParam++; } for (i = dSPIN_CMD_ARG_MAX_NB_BYTES - 1 - maxArgumentNbBytes; i < dSPIN_CMD_ARG_MAX_NB_BYTES; i++) { dSPIN_Write_Daisy_Chain_Bytes(&spiTxBursts[i][0], &spiRxBursts[i][0], slaves_number); } for (i = 0; i < slaves_number; i++) { *pValue = (spiRxBursts[1][i] << 16) | (spiRxBursts[2][i] << 8) | (spiRxBursts[3][i]); pValue++; } } /** * @brief Configures dSPIN slaves internal registers with values in the config structure. * @param slaves_number number of slaves * @param dSPIN_RegsStructArray Configuration structure array address (pointer to configuration structure array) * @retval None */ void dSPIN_All_Slaves_Registers_Set(uint8_t slaves_number, dSPIN_RegsStruct_TypeDef *dSPIN_RegsStructArray) { uint32_t i; /* ABS_POS */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_ABS_POS; arrayValues[i] = dSPIN_RegsStructArray[i].ABS_POS; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* EL_POS */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_EL_POS; arrayValues[i] = dSPIN_RegsStructArray[i].EL_POS; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* MARK */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_MARK; arrayValues[i] = dSPIN_RegsStructArray[i].MARK; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* ACC */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_ACC; arrayValues[i] = dSPIN_RegsStructArray[i].ACC; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* DEC*/ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_DEC; arrayValues[i] = dSPIN_RegsStructArray[i].DEC; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* MAX_SPEED */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_MAX_SPEED; arrayValues[i] = dSPIN_RegsStructArray[i].MAX_SPEED; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* MIN_SPEED */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_MIN_SPEED; arrayValues[i] = dSPIN_RegsStructArray[i].MIN_SPEED; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* FS_SPD */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_FS_SPD; arrayValues[i] = dSPIN_RegsStructArray[i].FS_SPD; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); #if defined(L6470) /* KVAL_HOLD */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_KVAL_HOLD; arrayValues[i] = dSPIN_RegsStructArray[i].KVAL_HOLD; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* KVAL_RUN */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_KVAL_RUN; arrayValues[i] = dSPIN_RegsStructArray[i].KVAL_RUN; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* KVAL_ACC */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_KVAL_ACC; arrayValues[i] = dSPIN_RegsStructArray[i].KVAL_ACC; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* KVAL_DEC */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_KVAL_DEC; arrayValues[i] = dSPIN_RegsStructArray[i].KVAL_DEC; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* INT_SPD */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_INT_SPD; arrayValues[i] = dSPIN_RegsStructArray[i].INT_SPD; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* ST_SLP */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_ST_SLP; arrayValues[i] = dSPIN_RegsStructArray[i].ST_SLP; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* FN_SLP_ACC */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_FN_SLP_ACC; arrayValues[i] = dSPIN_RegsStructArray[i].FN_SLP_ACC; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* FN_SLP_DEC */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_FN_SLP_DEC; arrayValues[i] = dSPIN_RegsStructArray[i].FN_SLP_DEC; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* K_THERM */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_K_THERM; arrayValues[i] = dSPIN_RegsStructArray[i].K_THERM; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* STALL_TH */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_STALL_TH; arrayValues[i] = dSPIN_RegsStructArray[i].STALL_TH; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); #endif /* defined(L6470) */ #if defined(L6472) /* TVAL_HOLD */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_TVAL_HOLD; arrayValues[i] = dSPIN_RegsStructArray[i].TVAL_HOLD; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* TVAL_RUN */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_TVAL_RUN; arrayValues[i] = dSPIN_RegsStructArray[i].TVAL_RUN; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* TVAL_ACC */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_TVAL_ACC; arrayValues[i] = dSPIN_RegsStructArray[i].TVAL_ACC; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* TVAL_DEC */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_TVAL_DEC; arrayValues[i] = dSPIN_RegsStructArray[i].TVAL_DEC; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* T_FAST */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_T_FAST; arrayValues[i] = dSPIN_RegsStructArray[i].T_FAST; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* TON_MIN */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_TON_MIN; arrayValues[i] = dSPIN_RegsStructArray[i].TON_MIN; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* TOFF_MIN */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_TOFF_MIN; arrayValues[i] = dSPIN_RegsStructArray[i].TOFF_MIN; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); #endif /* defined(L6472) */ /* OCD_TH */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_OCD_TH; arrayValues[i] = dSPIN_RegsStructArray[i].OCD_TH; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* STEP_MODE */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_STEP_MODE; arrayValues[i] = dSPIN_RegsStructArray[i].STEP_MODE; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* ALARM_EN */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_ALARM_EN; arrayValues[i] = dSPIN_RegsStructArray[i].ALARM_EN; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); /* CONFIG */ for (i = 0; i < slaves_number; i++) { arrayTxBytes[i] = dSPIN_CONFIG; arrayValues[i] = dSPIN_RegsStructArray[i].CONFIG; } dSPIN_All_Slaves_Set_Param(slaves_number, arrayTxBytes, arrayValues); } /** * @brief Issues dSPIN Move command to one slave device * @param slaves_number number of slaves * @param slaveNumber slave number * @param direction movement direction * @param n_step number of steps * @retval None */ void dSPIN_One_Slave_Move(uint8_t slaves_number, uint8_t slaveNumber, dSPIN_Direction_TypeDef direction, uint32_t n_step) { dSPIN_One_Slave_Send_Command(slaveNumber, slaves_number, (uint8_t)dSPIN_MOVE | (uint8_t)direction, n_step); } /** * @brief Issues dSPIN Run command to one slave device * @param slaveNumber slave number * @param slaves_number number of slaves * @param direction movement direction * @param speed * @retval None */ void dSPIN_One_Slave_Run(uint8_t slaveNumber, uint8_t slaves_number, dSPIN_Direction_TypeDef direction, uint32_t speed) { dSPIN_One_Slave_Send_Command(slaveNumber, slaves_number, (uint8_t)dSPIN_RUN | (uint8_t)direction, speed); } /** * @brief Issues a command to one slave device * @param slaveNumber slave number * @param slaves_number number of slaves * @param param command to issue * @param value command argument * @retval None */ void dSPIN_One_Slave_Send_Command(uint8_t slaveNumber, uint8_t slaves_number, uint8_t param, uint32_t value) { uint32_t i; for (i = 0; i < slaves_number; i++) { if (i == slaveNumber) { spiTxBursts[0][i] = (param); spiTxBursts[1][i] = (uint8_t)(value >> 16); spiTxBursts[2][i] = (uint8_t)(value >> 8); spiTxBursts[3][i] = (uint8_t)(value); } else { spiTxBursts[0][i] = dSPIN_NOP; spiTxBursts[1][i] = dSPIN_NOP; spiTxBursts[2][i] = dSPIN_NOP; spiTxBursts[3][i] = dSPIN_NOP; } } for (i = dSPIN_CMD_ARG_MAX_NB_BYTES - dSPIN_CMD_ARG_NB_BYTES_MOVE; i < dSPIN_CMD_ARG_MAX_NB_BYTES; i++) { dSPIN_Write_Daisy_Chain_Bytes(&spiTxBursts[i][0], &spiRxBursts[i][0], slaves_number); } } /** * @brief Issues commands to the slave devices for synchronous execution * @param slaves_number number of slaves * @param pParam Pointer to an array of dSPIN commands * @param pValue Pointer to an array of dSPIN arguments * @retval None */ void dSPIN_All_Slaves_Send_Command(uint8_t slaves_number, uint8_t *pParam, uint32_t *pValue) { uint32_t i; uint8_t maxArgumentNbBytes = 0; for (i = 0; i < slaves_number; i++) { switch ((*pParam) & DAISY_CHAIN_COMMAND_MASK) { case dSPIN_RUN: ; case dSPIN_MOVE: ; case dSPIN_GO_TO: ; case dSPIN_GO_TO_DIR: ; case dSPIN_GO_UNTIL: ; case dSPIN_GO_UNTIL_ACT_CPY: spiTxBursts[0][i] = *pParam; spiTxBursts[1][i] = (uint8_t)(*pValue >> 16); spiTxBursts[2][i] = (uint8_t)(*pValue >> 8); spiTxBursts[3][i] = (uint8_t)(*pValue); maxArgumentNbBytes = 3; break; default: spiTxBursts[0][i] = dSPIN_NOP; spiTxBursts[1][i] = dSPIN_NOP; spiTxBursts[2][i] = dSPIN_NOP; spiTxBursts[3][i] = *pParam; } pParam++; pValue++; } for (i = dSPIN_CMD_ARG_MAX_NB_BYTES - 1 - maxArgumentNbBytes; i < dSPIN_CMD_ARG_MAX_NB_BYTES; i++) { dSPIN_Write_Daisy_Chain_Bytes(&spiTxBursts[i][0], &spiRxBursts[i][0], slaves_number); } } /** * @brief Issues dSPIN Get Status command to each device (slave) * @param slaves_number number of slaves * @param pValue pointer to an array of Status Register content * @retval None */ void dSPIN_All_Slaves_Get_Status(uint8_t slaves_number, uint32_t *pValue) { uint32_t i; for (i = 0; i < slaves_number; i++) { spiTxBursts[0][i] = dSPIN_GET_STATUS; spiTxBursts[1][i] = dSPIN_NOP; spiTxBursts[2][i] = dSPIN_NOP; spiRxBursts[1][i] = 0; spiRxBursts[2][i] = 0; } for (i = 0; i < dSPIN_CMD_ARG_NB_BYTES_GET_STATUS + dSPIN_RSP_NB_BYTES_GET_STATUS; i++) { dSPIN_Write_Daisy_Chain_Bytes(&spiTxBursts[i][0], &spiRxBursts[i][0], slaves_number); } for (i = 0; i < slaves_number; i++) { *pValue = (spiRxBursts[1][i] << 8) | (spiRxBursts[2][i]); pValue++; } } /** * @brief Checks if one of the dSPIN device (slave) is Busy by SPI - Busy flag bit in Status Register. * @param slaves_number number of slaves * @retval one if there is a busy chip, otherwise zero */ uint8_t dSPIN_One_Or_More_Slaves_Busy_SW(uint8_t slaves_number) { uint32_t i; uint16_t status = 0; dSPIN_All_Slaves_Get_Status(slaves_number, arrayValues); for (i = 0; i < slaves_number; i++) { status |= arrayValues[i]; } if (!(status & dSPIN_STATUS_BUSY)) return 0x01; else return 0x00; } /** @} */ /******************* (C) COPYRIGHT 2013 STMicroelectronics *****END OF FILE****/