cancel
Showing results for 
Search instead for 
Did you mean: 

Control AMIS-30543 with STM32F030R8

SNeub.1
Associate

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

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

13 REPLIES 13

> 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

SNeub
Associate II

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

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

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

SNeub
Associate II

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?

0690X00000DAMERQA5.png

>  I don't have a logic analyzer/oscilloscope

Get one, borrow or buy some cheap one. Otherwise it's just blind shooting.

JW

SNeub
Associate II

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...

  1. set NSS low
  2. wait for the SPI_SR_TXE flag to be set high(?) by the hardware
  3. place 8 bits of data in the data register, these 8 bits specify the command type (Read or Write) and the target slave device register
  4. wait for the SPI_SR_RXNE flag to be set high(?) by the hardware
  5. wait for the SPI_SR_TXE flag to be set high(?) by the hardware
  6. place 8 bits of dummy data in the data register
  7. wait for the SPI_SR_RXNE flag to be set high(?) by the hardware
  8. read 8 bits of data from the data register, these 8 bits are the contents of the slave device register
  9. set NSS high

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.

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...

  1. set NSS low
  2. wait for the SPI_SR_TXE flag to be set high(?) by the hardware
  3. place 8 bits of data in the data register, these 8 bits specify the command type (Read or Write) and the target slave device register
  4. wait for the SPI_SR_RXNE flag to be set high(?) by the hardware
  5. wait for the SPI_SR_TXE flag to be set high(?) by the hardware
  6. place 8 bits of dummy data in the data register
  7. wait for the SPI_SR_RXNE flag to be set high(?) by the hardware
  8. read 8 bits of data from the data register, these 8 bits are the contents of the slave device register
  9. set NSS high

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.

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