STM32 firmware for a remotely-controlled stepper motor demo with a mobile interface.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1472 lines
48 KiB

/**
******************************************************************************
* @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.
*
* <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
*/
/* 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****/