2025-06-17 1:59 PM - last edited on 2025-06-18 3:10 AM by Saket_Om
I'm using an STM32L452RE MCU to communicate with the L6470 stepper motor driver via SPI, and I'm currently having trouble reading data from the driver.
I’m able to transmit data (e.g., RUN, MOVE, SOFT_STOP commands).
The motor runs and responds correctly, so SPI transmit appears functional.
Problem:
I'm trying to read registers like ABS_POS, ACC, etc. using the GET_PARAM command.
I always receive 0 in response, regardless of the register.
Setup:
MCU: STM32 (HAL SPI)
SPI Mode: CPOL = 1, CPHA = 1 (Mode 3)
Driver: L6470
Motor: Connected and moving
MISO, MOSI, SCK, CS connections confirmed
uint32_t L6470_ReadABS_POS(void) {
uint8_t cmd = 0x25; // GET_PARAM | ACC (0x05)
static uint8_t TramsmitData[2];
TramsmitData[0] = cmd;
TramsmitData[1] = 0x00;
static uint8_t receivedData[2] = {0};
for (int index = 0; index < 1; index++)
{
L6470_CS_Low();
HAL_SPI_Transmit(&hspi2,&TramsmitData[index], sizeof(TramsmitData[index]), HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi2, &receivedData[index],sizeof(receivedData[index]), HAL_MAX_DELAY);
L6470_CS_High();
}
printf("receivedData[0] %d \r\n",receivedData[0]);
printf("receivedData[1] %d \r\n",receivedData[1]);
// printf("ABS_POS = %ld\n", value);
}
void L6470_Init()
{
L6470_SetABS_Pos(1000);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_SPI2_Init();
/* USER CODE BEGIN 2 */
L6470_Init();
L6470_Run(0, 0x6312); // RUN forward at max speed
L6470_ReadABS_POS();
}
2025-06-17 2:14 PM
Welcome to the forum
Please see How to write your question to maximize your chances to find a solution for best results - in particular, How to insert source code
What board(s) are you using?
Please show schematic(s)
Have you looked at the SPI lines with an oscilloscope and/or analyser to see what's going on?
2025-06-17 5:57 PM - edited 2025-06-18 5:46 AM
ACC register is 2 bytes. You're only reading 1. The default value is 0x08A, so the most significant byte is 0 which is what you're reading. All is as expected.
The receivedData[1] never gets populated because your loop only runs for index=0. However, even if it did run, it wouldn't do anything useful. Unclear what is intended here.
Send 0x25. Read two bytes. That's your ACC value (MSB first).
Edit: Also, since you need to send 0 when reading values, you should use HAL_SPI_TransmitReceive here with 0s in the transmit buffer. A single transaction of 3 bytes will work. HAL_SPI_Receive sends arbitrary data. No good.
2025-06-18 7:42 AM - edited 2025-06-18 2:07 PM
Apologies, you were absolutely right — I was mistakenly reading only one byte and not using HAL_SPI_TransmitReceive properly. I've corrected the code to send the command 0x25 followed by two dummy bytes (0x00, 0x00) in a single transaction to read the ACC register.
However, now I’m facing a new issue: no matter what value I set for ACC, when I read it back, I always get 0x80 0x00 0x89 (i.e., 128 0 137). I double-checked the write sequence as well and it appears to complete successfully.(I am able to execute run command)
I’ve also attached the image and my updated code for reference. Any suggestions on what I might be missing?
Additionally, I’ve already set all KVALs and MAX_SPEED to their maximum values, yet the motor won't go beyond ~1000 steps/sec. Beyond that, it starts vibrating heavily and doesn’t rotate at all, I am using NEMA 17 and NEMA 23 with 24v Supply and tried with no load condition and with some load as well. Phase resistance for NEMA 17 is 3.3R and NEMA 23 has 2.23R
I've attached an image and included my updated code for reference. Any suggestions on what I might be missing would be greatly appreciated.
Thanks again for your help and patience!
void L6470_SendCommand(uint8_t *cmd, uint8_t len)
{
for (uint8_t i = 0; i < len; i++) {
L6470_CS_Low();
HAL_SPI_Transmit(&hspi2, &cmd[i], 1, HAL_MAX_DELAY);
L6470_CS_High();
}
HAL_Delay(1); // small delay for stability
}
void L6470_Run(uint8_t dir, float speed)
{
uint32_t spd =speed;
uint8_t cmd[] = {
(dir == 0) ? 0x50 : 0x51, // RUN forward/reverse
(uint8_t)(spd >> 16) & 0xFF,
(uint8_t)(spd >> 8) & 0xFF,
(uint8_t)(spd & 0xFF)
};
L6470_SendCommand(cmd, 4);
}
void L6470_SetACC(){
uint8_t ACC_cmd[] = {
0x05, // ACC register address (Write command)
(0x25 >> 8) & 0xFF, // MSB = 0
(0x25 & 0xFF) // LSB = 0x8A = 138
};
L6470_SendCommand(ACC_cmd, 3);
}
void L6470_SetDCC(){
uint8_t DCC_cmd[] = {
0x05, // ACC register address (Write command)
(0x08A >> 8) & 0xFF, // MSB = 0
(0x08A & 0xFF) // LSB = 0x8A = 138
};
L6470_SendCommand(DCC_cmd, 3);
}
void L6470_SetABS_POS(){
uint8_t ABS_cmd[] = {
0x01,
(0x00 >> 16) & 0x3F,
(0x00 >> 8) & 0xFF,
(0x00 & 0xFF)
};
L6470_SendCommand(ABS_cmd, 4);
}
void L6470_SET_MAX_SPEED(){
uint8_t MAX_SPEED_cmd[] = {
0x07,
(0x3CFA >> 8) & 0xFF, // MSB = 0
(0x3CFA & 0xFF) // LSB = 0x8A = 138
};
L6470_SendCommand(MAX_SPEED_cmd, 3);
}
void L6470_SET_MIN_SPEED(){
uint8_t MIN_SPEED_cmd[] = {
0x08,
(0x00 >> 8) & 0xFF, // MSB = 0
(0x00 & 0xFF) // LSB = 0x8A = 138
};
L6470_SendCommand(MIN_SPEED_cmd, 3);
}
void L6470_SET_FS_SPD(){
uint8_t FS_SPD_cmd[] = {
0x15,
(0x3ff >> 8) & 0xFF, // MSB = 0
(0x3ff & 0xFF) // LSB = 0x8A = 138
};
L6470_SendCommand(FS_SPD_cmd, 3);
}
void L6470_KVALs(){
uint8_t kval_max = 0xFF;
uint8_t kval_hold_cmd[] = { 0x09, kval_max };
L6470_SendCommand(kval_hold_cmd, 2);
uint8_t kval_run_cmd[] = { 0x0A, kval_max };
L6470_SendCommand(kval_run_cmd, 2);
uint8_t kval_acc_cmd[] = { 0x0B, kval_max };
L6470_SendCommand(kval_acc_cmd, 2);
uint8_t kval_dec_cmd[] = { 0x0C, kval_max };
L6470_SendCommand(kval_dec_cmd, 2);
}
void L6470_SET_STEP_MODE(){
uint8_t step_mode_cmd[] = {
0x16, // STEP_MODE register address
0x00 // Set to full step
};
L6470_SendCommand(step_mode_cmd, 2);
}
void L6470_SET_OCD_TH (){
uint8_t ocd_cmd[] = { 0x13, 0x0F }; // 0x0F = max threshold
L6470_SendCommand(ocd_cmd, 2);
}
void L6470_SET_STALL_TH(){
uint8_t stall_cmd[] = { 0x14, 0x7F }; // Max sensitivity
L6470_SendCommand(stall_cmd, 2);
}
void L6470_INT_SPEED(){
uint16_t int_speed_val = (uint16_t)(930 * 16.77);
uint8_t int_speed_cmd[] = {
0x0D, // INT_SPEED register
(uint8_t)(int_speed_val >> 8), // MSB
(uint8_t)(int_speed_val & 0xFF) // LSB
};
L6470_SendCommand(int_speed_cmd, 3);
}
uint32_t L6470_ReadABS_POS(void) {
static uint8_t receivedData[3] = {0x00,0x00, 0x00};
uint8_t tx_buf[3] = {0x25, 0x00, 0x00}; // 0x25 = GET_PARAM | ACC (0x05), followed by 2 dummy bytes
L6470_CS_Low();
// HAL_Delay(10);
HAL_SPI_TransmitReceive(&hspi2,tx_buf,receivedData,3,HAL_MAX_DELAY);
L6470_CS_High();
//HAL_Delay(10);
printf("receivedData[0] %d \r\n",receivedData[0]);
printf("receivedData[1] %d \r\n",receivedData[1]);
printf("receivedData[2] %d \r\n",receivedData[2]);
}
void L6470_Init()
{
L6470_SetACC();
L6470_SetDCC();
L6470_SetABS_POS();
L6470_SET_MAX_SPEED();
L6470_SET_MIN_SPEED();
L6470_SET_FS_SPD();
L6470_KVALs();
L6470_SET_STEP_MODE();
L6470_SET_OCD_TH();
L6470_SET_STALL_TH();
L6470_INT_SPEED();
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_SPI2_Init();
/* USER CODE BEGIN 2 */
L6470_Init();
L6470_Run(0, 33554); // RUN forward at max speed 500step/sec
L6470_ReadABS_POS();
while (1)
{
}
}