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

13 REPLIES 13
SNeub
Associate II

So, I've gone back through the documentation for the MCU and the slave device (AMIS-30543) and got a logic analyzer. I've updated the code some and I think I've narrowed down where the error may lay. Here is a screen grab of the logic analyzer results and updated code.

The slave device's documentation is here. It states it must receive a command+address byte followed by an empty byte in order for one of its registers to be read.

https://www.pololu.com/file/0J869/AMIS-30543-D.pdf 

It looks like I'm correctly sending 8 bits of data to the slave device, but am still receiving blank data in return.

0690X00000DC7CZQA1.png

Code:

int main(void)
{
	Clock_Init();
	USART2_Init();
	SPI1_Init();
	
	while (1)
	{
		DelayMS(1);
		writeReg(CR0, 0x11);
		readReg(CR0);
	}
}
 
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 SPI1_Init(void)
{
	// define GPIO pins		-> PC7, output
	//				-> PB3, output
	//				-> PB4, output
	//				-> PA5, alternate function
	//				-> PA6, alternate function
	//				-> PA7, alternate function
	GPIOC->MODER = 0x00004000;
	GPIOB->MODER = 0x00000140;
	GPIOA->MODER |= 0x0000A800;
	
	// define alt. func.s		-> PA5, AF0, SPI1 SCK
	//				-> PA6, AF0, SPI1 MISO
	//				-> PA7, AF0, SPI1 MOSI
	GPIOA->AFR[0] |= 0x00000000;
	
	// format spi
	SPI1->CR1 = 0x00000014;	// br = f_pclk / 8
	
	// format spi
	SPI1->CR2 = 0x00001704;	// ds = 8 bit
	
	// enable spi
	SPI1->CR1 |= 0x00000040;
	
	// flush data register
	uint8_t flushValue = SPI1->DR;
}
 
void writeReg(uint8_t address, uint8_t value)
{
	selectChip();
	transfer(0x80 | (address & 0b11111));
	transfer(value);
	deselectChip();
}
 
uint8_t readReg(uint8_t address)
{
	selectChip();
	transfer(address & 0b11111);
	uint8_t dataOut = transfer(0x00);
	deselectChip();
	return dataOut;
}
 
uint8_t transfer(uint8_t value)
{
	while (!(SPI1->SR & 0x00000002));	// wait for the transmission to complete
	*(uint8_t*)&SPI1->DR = value;		// start the transmission
	while (!(SPI1->SR & 0x00000001));	// wait for the reception buffer to be full
	return (uint8_t)SPI1->DR;			// return the received byte
}
 
void selectChip(void)
{
	csLow();
}
 
void deselectChip(void)
{
	csHigh();
}

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

I'm very happy to report it is working now; soldering the joints did the trick. I soldered the pins now instead of simply laying the chip on top of the breakout pins (I thought the contact was sufficient, but was clearly wrong in that assessment). The stepper motor now spins as instructed.

I did notice that I'm unable to flash the MCU while the power supply is connected to the stepper motor and the motor will continue spinning when the MCU is unplugged from the computer (I was powering the MCU via USB for development). The LD2 LED is also faintly illuminated, for some reason.

My frankenstein-ian translation of the Arduino AMIS-30543/SPI libraries here:

https://www.dropbox.com/s/rd56urolci0ou82/main.txt?dl=0

Thank you for your help, JW.

Thanks for coming back with the result.

JW