2020-02-12 01:47 PM
I'm setting up a MCU to control a stepper motor. I'm aiming to control the stepper motor driver (AMIS-30543) over SPI. My current goal is to get the driver to respond to my SPI commands so I know it's correctly receiving my commands. The driver responds, but only ever with 0xFF. Once earlier today I got it to respond with 0x02 (the hexadecimal I should receive), but it hasn't repeated since then. So where I need help is figuring out why its behaving like this and how to get the driver to respond correctly.
I'm using Keil uVision 5. Writing in C as a beginner of beginners.
The pins are connected according to the following description.
STM AMIS
3.3v IOREF
GND GND
PB3 NXT
PB5 DIR
PA7 DO
PA6 DI
PA5 CLK
PA4 CS
AMIS 9v Battery
VMOT + terminal (also tried with STM 5V)
GND - terminal (also tried with STM GND)
AMIS 26M024B2B
MXP + coil 1
MXN - coil 1
MYP + coil 2
MYN - coil 2
Relevant segments of my code is below.
int main(void)
{
Clock_Init();
USART2_Init();
SPI1_Init();
init();
nxtLow();
dirLow();
DelayMS(1);
resetSettings();
setCurrentMilliamps(132);
setStepMode(16);
enableDriver();
printf("WR: ");
printHex(readReg(WR));
printf("\r\n");
printf("CR0: ");
printHex(readReg(CR0));
printf("\r\n");
printf("CR1: ");
printHex(readReg(CR1));
printf("\r\n");
printf("CR2: ");
printHex(readReg(CR2));
printf("\r\n");
printf("CR3: ");
printHex(readReg(CR3));
printf("\r\n");
while (1)
{
dirHigh();
for (unsigned int i = 0; i < 16; i++)
{
Step();
}
DelayMS(300);
dirLow();
for (unsigned int i = 0; i < 16; i++)
{
Step();
}
DelayMS(300);
}
}
// INITIALIZATIONS: start
void Clock_Init(void)
{
// enable ports -> port A, AHB, bit 17
// -> port B, AHB, bit 18
// -> port C, AHB, bit 19
RCC->AHBENR = 0x000E0000;
// enable USART2 -> bit 17, APB1
RCC->APB1ENR = 0x00020000;
// enable SPI1 -> bit 12, APB2
RCC->APB2ENR = 0x00001000;
}
void USART2_Init(void)
{
// define GPIO pins -> PA2, alternate function
// -> PA3, alternate function
GPIOA->MODER = 0x000000A0;
// define alternate functions -> PA2, AF1, USART2 TX
// -> PA3, AF1, USART2 RX
GPIOA->AFR[0] = 0x00001100;
// set baud rate -> 8000000 / 9600 to HEX = 9600 @ 8MHz
USART2->BRR = 0x00000341;
// format usart -> enable tx, bit 3
// -> enable rx, bit 2
USART2->CR1 = 0x0000000C;
// enable usart -> enable ue, bit 0
USART2->CR1 |= 0x00000001;
}
void SPI1_Init(void)
{
// define GPIO pins -> PC7, output
// -> PB3, output
// -> PB4, output
// -> PA4, alternate function
// -> PA5, alternate function
// -> PA6, alternate function
// -> PA7, alternate function
GPIOC->MODER = 0x00004000;
GPIOB->MODER = 0x00000140;
GPIOA->MODER |= 0x0000AA00;
// define alternate functions -> PA4, AF0, SPI1 CS / NSS
// -> PA5, AF0, SPI1 SCK
// -> PA6, AF0, SPI1 MISO
// -> PA7, AF0, SPI1 MOSI
GPIOA->AFR[0] |= 0x00000000;
// format spi -> set br, bit 3-5
// -> enable ssm, bit 9
// -> enable ssi, bit 8
// -> set mstr, bit 2
SPI1->CR1 = 0x00000314;
// format spi -> set ds, bit 8-11
SPI1->CR2 = 0x00000700;
// enable spi -> enable spe
SPI1->CR1 |= 0x00000040;
}
// INITIALIZATIONS: end
//
//
// SPI1: start
void csHigh(void)
{
GPIOC->BSRR = 0x00000080;
GPIOA->BSRR = 0x00000010;
}
void csLow(void)
{
GPIOC->BSRR = 0x00800000;
GPIOA->BSRR = 0x00100000;
}
void selectChip(void)
{
csLow();
// begin spi transaction, unnecessary?
}
void deselectChip(void)
{
csHigh();
// end spi transaction, unnecessary?
// stabilization delay
DelayUS(3);
}
uint8_t transfer(uint8_t value)
{
// while (!(SPI1->SR & 0x00000002)); // wait for TX buffer to be empty
// SPI1->DR = value; // start the transmission
// while (!(SPI1->SR & 0x00000080)); // wait for TX to be complete
// return SPI1->DR; // return the received byte
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = value;
//while (!(SPI1->SR & SPI_SR_RXNE));
while (!(SPI1->SR & SPI_SR_BSY));
return SPI1->DR;
}
uint8_t readReg(uint8_t address)
{
selectChip();
transfer(address & 0b11111);
uint8_t dataOut = transfer(0);
deselectChip();
return dataOut;
}
void writeReg(uint8_t address, uint8_t value)
{
selectChip();
transfer(0x80 | (address & 0b11111));
transfer(value);
deselectChip();
}
// SPI1: end
//
// GENERAL FUNCTIONALITY: start
void DelayTicks(uint32_t ticks)
{
SysTick->LOAD = ticks;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0);
SysTick->CTRL = 0;
}
void DelayMS(int n)
{
SysTick->LOAD = 8000 - 1;
SysTick->VAL = 0;
SysTick->CTRL = 0x00000005;
for (int i = 0; i < n; i++)
{
while ((SysTick->CTRL & 0x00010000) == 0);
}
SysTick->CTRL = 0x00000000;
}
void DelayUS(uint32_t n)
{
DelayTicks((n * 1000));
}
// GENERAL FUNCTIONALITY: end
Solved! Go to Solution.
2020-02-24 02:13 AM
At this point, I don't know. As it's the AMIS chip which does not answer to what appears to be a correct sequence, it's then either incorrect wiring, bad solder joints, or faulty chip...
JW
2020-02-13 12:21 PM
> SPI1->DR = value;
This starts a 16-bit transfer, see "Data packing" in SPI chapter of RM and here on forum. Is this what you wanted?
Generally, you want to observe the pins using logic analyzer and compare the observed waveforms with those given in the sensor's datasheet.
JW
2020-02-13 01:12 PM
JW,
Thanks for the response. Yes, that's something I realized after making this post. I did go back and update the FIFO reception threshold so it flagged the RXNE event if the FIFO level is greater than or equal to 1/4 (8bit) with the SPIx_CR2 register. Would that have addressed what you brought up? Even after this update I'm still receiving 0xFF (or whatever dummy data I send) back from the driver.
SPI1_Init(void) now contains the following code for CR2...
// format spi -> set ds, bit 8-11
// -> set frxth, bit 12
SPI1->CR2 = 0x00001700;
SN
2020-02-13 01:12 PM
JW,
Thanks for the response. Yes, that's something I realized after making this post. I did go back and update the FIFO reception threshold so it flagged the RXNE event if the FIFO level is greater than or equal to 1/4 (8bit) with the SPIx_CR2 register. Would that have addressed what you brought up? Even after this update I'm still receiving 0xFF (or whatever dummy data I send) back from the driver.
SPI1_Init(void) now contains the following code for CR2...
// format spi -> set ds, bit 8-11
// -> set frxth, bit 12
SPI1->CR2 = 0x00001700;
SN
2020-02-13 01:33 PM
No, I'm talking about Tx. Have you read the "Data packing" section in SPI chapter in RM and have you looked it up here on the forum?
Have you observed the waveforms?
JW
2020-02-13 01:47 PM
I've read through it in the RM, but I'm barely even a beginner in C/embedded programming so I'm probably missing something important. I haven't looked it up on this forum. I don't have a logic analyzer/oscilloscope, if I did then troubleshooting this would be easier.
Are you referring to how the slave device receives 8 bits of data that specify the command and address then an additional 8 bits of the actual data?
Is this the correct procedure?
2020-02-13 06:15 PM
> I don't have a logic analyzer/oscilloscope
Get one, borrow or buy some cheap one. Otherwise it's just blind shooting.
JW
2020-02-14 07:17 AM
Until I can convince my boss we need a logic analyzer/oscilloscope is there any other advice/observations? As I understand it, the SPI read process is as follows...
Is this correct? Or should I be changing the 8 bits to 16 bits? I specified in the control register I'm using 8 bit data frame.
2020-02-14 07:18 AM
Until I can convince my boss we need a logic analyzer/oscilloscope is there any other advice/observations? As I understand it, the SPI read process is as follows...
Is this correct? Or should I be changing the 8 bits to 16 bits? I specified in the control register I'm using 8 bit data frame.
2020-02-15 03:36 AM
I don't know the sensor's protocol, but as I've said, above:
>> SPI1->DR = value;
> This starts a 16-bit transfer, see "Data packing" in SPI chapter of RM and here on forum.
JW