Я пытаюсь заставить мою плату STM32 управлять шаговым двигателем (используя драйвер AMIS-30543, шаговый двигатель 26M024B2B) с помощью SPI. Я использую Keil uVision 5 и использую голый подход в C. Моя проблема в том, что двигатель не вращается, и я не уверен, где скрываются ошибки. Буду признателен, если вы укажете, где я ошибся, и как это исправить. Спасибо за потраченное время!
У меня все вместе, как показано ниже.
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
Код, который я написал ниже. Код пытается записать в регистр управления водителя, а затем переключить вывод NXT, чтобы двигатель увеличивался с каждым переключателем в соответствии с его регистром управления. Я прочитал таблицу данных для драйвера, и для вашего удобства связал его с этим сообщением.
Соответствующие разделы на листе данных - это раздел интерфейса SPI (стр. 31) в сочетании с таблицами 11 и 12 и рисунком 19. Моя интерпретация заключается в том, что драйвер можно записать, отправив ему 8-битное сообщение, в котором указывается, какой тип команды и где данные будут go, затем 8 бит данных это заполнит контрольный регистр. Я собрал первый пакет, используя следующую логику c ...
writing to CR0 -> 1000 0001 -> 0x81
writing to CR1 -> 1000 0010 -> 0x82
writing to CR2 -> 1000 0011 -> 0x83
#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>
// GPIO -> PB5 -> direction
// GPIO -> PB3 -> next
// USART2 TX -> PA2, AF1 -> transmit
// USART2 RX -> PA3, AF1 -> receive
// SPI1 NSS -> PA4 -> slave select
// SPI1 SCK -> PA5, AF0 -> clock
// SPI1 MISO -> PA6, AF0 -> master in slave out
// SPI1 MOSI -> PA7, AF0 -> master out slave in
void Clock_Init(void);
void GPIO_Init(void);
void USART2_Init(void);
void SPI1_Init(void);
void SPI1_Write(uint8_t data);
void DelayMS(int n);
int main(void)
{
Clock_Init();
GPIO_Init();
USART2_Init();
SPI1_Init();
// char str[100];
// set stepper rotation direction
GPIOB->ODR |= 0x00000020;
// apply settings to the stepper motor driver
uint8_t packet0;
uint8_t packet1;
GPIOA->ODR = 0x00000010; // write NSS high
packet0 = 0x81; // write to CR0
packet1 = 0x20; // set rotation amount
SPI1_Write(packet0); // send WRITE command & register address
SPI1_Write(packet1); // send register data
GPIOA->ODR = 0x00000000; // write NSS low
GPIOA->ODR = 0x00000010; // write NSS high
packet0 = 0x82; // write to CR1
packet1 = 0x80; // set rotation amount
SPI1_Write(packet0); // send WRITE command & register address
SPI1_Write(packet1); // send register data
GPIOA->ODR = 0x00000000; // write NSS low
GPIOA->ODR = 0x00000010; // write NSS high
packet0 = 0x83; // write to CR2
packet1 = 0x80; // set motor enable
SPI1_Write(packet0); // send WRITE command & register address
SPI1_Write(packet1); // send register data
GPIOA->ODR = 0x00000000; // write NSS low
printf("\r\nTest Interface\r\n");
while (1)
{
// printf("Command: ");
// gets(str);
// printf("\r\n");
// printf("Your command is: ");
// puts(str);
// printf("\r\n");
GPIOB->ODR ^= 0x00000008; // toggle the step signal
DelayMS(50);
}
}
// initialize device clock
void Clock_Init(void)
{
// enable port A -> bit 17, AHB
// enable port B -> bit 18, AHB
RCC->AHBENR |= 0x00060000;
// enable USART2 -> bit 17, APB1
RCC->APB1ENR |= 0x00020000;
// enable SPI1 -> bit 12, APB2
RCC->APB2ENR |= 0x00001000;
}
// initialize GPIO pins
void GPIO_Init(void)
{
// set GPIO to general purpose -> PB3, bit 6:7
// -> PB5, bit 10:11
GPIOB->MODER |= 0x00000440;
}
// initialize USART2
void USART2_Init(void)
{
// set GPIO to alternate function -> PA2, bit 4:5
// -> PA3, bit 6:7
GPIOA->MODER |= 0x000000A0;
// define alternate function -> PA2, AF1
// -> PA3, AF1
GPIOA->AFR[0] |= 0x00001100;
// set the baud rate -> 8000000 / 9600 to HEX, 9600 @ 8MHz
USART2->BRR = 0x00000341;
// enable transmit -> bit 3
// enable receive -> bit 2
USART2->CR1 = 0x0000000C;
// enable usart enable -> bit 0
USART2->CR1 |= 0x00000001;
}
// initialize SPI1
void SPI1_Init(void)
{
// clear GPIO pin -> PA5, bit 10:11
// -> PA6, bit 12:13
// -> PA7, bit 14:15
GPIOA->MODER &=~ 0x0000FC00;
// set GPIO to alternate function -> PA5, bit 10:11
// -> PA6, bit 12:13
// -> PA7, bit 14:15
GPIOA->MODER |= 0x0000A800;
// clear alternate function -> PA5, AF0
// -> PA6, AF0
// -> PA7, AF0
GPIOA->AFR[0] &=~ 0xFFF00000;
// define alternate function -> PA5, AF0
// -> PA6, AF0
// -> PA7, AF0
GPIOA->AFR[0] |= 0x00000000;
// clear GPIO pin -> PA4, bit 8:9
GPIOA->MODER &=~ 0x00000300;
// set GPIO to output -> PA4, bit 8:9
GPIOA->MODER |= 0x00000100;
// set the baud rate -> f_PCLK / 16
// set the data frame -> 8 bit
SPI1->CR1 = 0x0000031C;
SPI1->CR2 = 0x00000000;
SPI1->CR1 |= 0x00000040;
}
// delay for a given ms limit
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;
}
// write 8 bits via SPI1
void SPI1_Write(uint8_t data)
{
while (!(SPI1->SR & 0x00000002)); // wait for the transfer buffer to be empty
GPIOA->BSRR = 0x00100000; // assert slave select
SPI1->DR = data; // write data
while (SPI1->SR & 0x00000080); // wait for transmission to be complete
GPIOA->BSRR = 0x00000010; // de-assert slave select
}
// write character to PC
int USART2_Write(int ch)
{
while (!(USART2->ISR & 0x00000080));
USART2->TDR = (ch & 0xFF);
return ch;
}
// read character from PC
int USART2_Read(void)
{
while (!(USART2->ISR & 0x00000020));
return USART2->RDR;
}
// implement stdin/stdout/stderr functionality
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};
int fgetc(FILE *f)
{
int c;
c = USART2_Read();
if (c == '\r')
{
USART2_Write(c);
c = '\n';
}
USART2_Write(c);
return c;
}
int fputc(int c, FILE *f)
{
return USART2_Write(c);
}
ОБНОВЛЕНИЕ:
Вот вторая итерация моей попытки. Я просмотрел больше документации и примеров и пытаюсь получить ответ от водителя, чтобы доказать, что я правильно записываю данные в регистры водителя. Пока что я не получаю ответ. Попытка перевести библиотеки оказалась для меня слишком сложной и запутанной в настоящее время (может быть, я упускаю что-то очевидное?), Поэтому я все еще придерживаюсь принципа «голыми руками».
Большое спасибо за вашу помощь, @ralf htp.
ОБНОВЛЕНИЕ:
Я установил Arduino Uno в соответствии с указаниями здесь и здесь с вышеупомянутыми библиотеками. Шаговый двигатель не вращался. Я сменил драйвер на другой, и шаговый двигатель все еще не вращался. Могу ли я иметь два неисправных драйвера?
#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>
void setDirection(int cw);
void Step(void);
void ssHigh(void);
void ssLow(void);
void SPI1_Reset(void);
void SPI1_Write(uint8_t address, uint8_t data);
uint8_t SPI1_Read(uint8_t address);
void SPI1_Send(uint8_t packet);
uint8_t SPI1_Receive(void);
void DelayMS(int n);
void Clock_Init(void);
void GPIO_Init(void);
void USART2_Init(void);
void SPI1_Init(void);
void printHex(uint8_t data);
int main(void)
{
// initialize
Clock_Init();
GPIO_Init();
USART2_Init();
SPI1_Init();
// set NXT and DIR pins low
GPIOB->ODR = 0x00000000;
// short delay
DelayMS(100);
// reset driver settings
SPI1_Reset();
// set current value (mA)
SPI1_Write(0x11, 0x11);
// set step mode
SPI1_Write(0x19, 0x02);
// enable motor outputs(?)
SPI1_Write(0x13, 0x80);
// check register
uint8_t response = SPI1_Read(0x09);
printHex(response);
// inifinite loop
while (1)
{
// step cw(?) 20 times
setDirection(0);
for (unsigned int i = 0; i < 20; i++)
{
Step();
//printf("spin cw\r\n");
}
DelayMS(300);
// step ccw(?) 20 times
setDirection(1);
for (unsigned int i = 0; i < 20; i++)
{
Step();
//printf("spin ccw\r\n");
}
DelayMS(300);
}
}
void setDirection(int cw)
{
if (cw == 0)
{
GPIOB->BSRR |= 0x00000020;
}
else if (cw == 1)
{
GPIOB->BSRR |= 0x00200000;
}
}
void Step(void)
{
GPIOB->BSRR |= 0x00000008;
DelayMS(3);
GPIOB->BSRR |= 0x00080000;
DelayMS(3);
DelayMS(500);
}
void ssHigh(void)
{
GPIOA->BSRR |= 0x00000010;
}
void ssLow(void)
{
GPIOA->BSRR |= 0x00100000;
}
void SPI1_Reset(void)
{
uint8_t addressWR = 0x10;
uint8_t addressCR0 = 0x11;
uint8_t addressCR1 = 0x12;
uint8_t addressCR2 = 0x13;
uint8_t addressCR3 = 0x19;
uint8_t dataWR = 0xF8;
uint8_t dataCR0 = 0x06;
uint8_t dataCR1 = 0xC2;
uint8_t dataCR2 = 0x00;
uint8_t dataCR3 = 0x00;
SPI1_Write(addressWR, dataWR);
SPI1_Write(addressCR0, dataCR0);
SPI1_Write(addressCR1, dataCR1);
SPI1_Write(addressCR2, dataCR2);
SPI1_Write(addressCR3, dataCR3);
}
void SPI1_Write(uint8_t address, uint8_t data)
{
ssHigh(); // set CS high
ssLow(); // set CS low
SPI1_Send(address); // send the register address
SPI1_Send(data); // send the register data
ssHigh(); // set CS high
ssLow(); // set CS low
}
uint8_t SPI1_Read(uint8_t address)
{
ssHigh(); // set CS high
ssLow(); // set CS low
SPI1_Send(address);
uint8_t output = SPI1_Receive();
ssHigh(); // set CS high
ssLow(); // set CS low
return output;
}
void SPI1_Send(uint8_t packet)
{
while (!(SPI1->SR & 0x00000002)); // wait for TX buffer to be empty
SPI1->DR = packet;
while (SPI1->SR & 0x00000080); // wait for TX to be complete
}
uint8_t SPI1_Receive(void)
{
while (SPI1->SR & 0x00000001); // wait for RX buffer to be empty
return SPI1->DR;
}
int USART2_Write(int ch)
{
while (!(USART2->ISR & 0x00000080));
USART2->TDR = (ch & 0xFF);
return ch;
}
int USART2_Read(void)
{
while (!(USART2->ISR & 0x00000020));
return USART2->RDR;
}
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 Clock_Init(void)
{
// enable port A -> bit 17, AHB
// enable port B -> bit 18, AHB
RCC->AHBENR |= 0x00060000;
// enable USART2 -> bit 17, APB1
RCC->APB1ENR |= 0x00020000;
// enable SPI1 -> bit 12, APB2
RCC->APB2ENR |= 0x00001000;
}
void GPIO_Init(void)
{
// set GPIO to general purpose -> PB3, bit 6:7
// -> PB5, bit 10:11
GPIOB->MODER |= 0x00000440;
}
void USART2_Init(void)
{
// set GPIO to alternate function -> PA2, bit 4:5
// -> PA3, bit 6:7
GPIOA->MODER |= 0x000000A0;
// define alternate function -> PA2, AF1
// -> PA3, AF1
GPIOA->AFR[0] |= 0x00001100;
// set the baud rate -> 8000000 / 9600 to HEX, 9600 @ 8MHz
USART2->BRR = 0x00000341;
// enable transmit -> bit 3
// enable receive -> bit 2
USART2->CR1 = 0x0000000C;
// enable usart enable -> bit 0
USART2->CR1 |= 0x00000001;
}
void SPI1_Init(void)
{
// clear GPIO pin -> PA5, bit 10:11
// -> PA6, bit 12:13
// -> PA7, bit 14:15
GPIOA->MODER &=~ 0x0000FC00;
// set GPIO to alternate function -> PA5, bit 10:11
// -> PA6, bit 12:13
// -> PA7, bit 14:15
GPIOA->MODER |= 0x0000A800;
// clear alternate function -> PA5, AF0
// -> PA6, AF0
// -> PA7, AF0
GPIOA->AFR[0] &=~ 0xFFF00000;
// define alternate function -> PA5, AF0
// -> PA6, AF0
// -> PA7, AF0
GPIOA->AFR[0] |= 0x00000000;
// clear GPIO pin -> PA4, bit 8:9
GPIOA->MODER &=~ 0x00000300;
// set GPIO to output -> PA4, bit 8:9
GPIOA->MODER |= 0x00000100;
// set the baud rate -> f_PCLK / 8
// set the data frame -> 8 bit
SPI1->CR1 = 0x00000314;
SPI1->CR2 = 0x00000000;
SPI1->CR1 |= 0x00000040;
}
void printHex(uint8_t data)
{
printf("0x%02x", data);
}
// implement stdin/stdout/stderr functionality
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};
int fgetc(FILE *f)
{
int c;
c = USART2_Read();
if (c == '\r')
{
USART2_Write(c);
c = '\n';
}
USART2_Write(c);
return c;
}
int fputc(int c, FILE *f)
{
return USART2_Write(c);
}
ОБНОВЛЕНИЕ: я просмотрел библиотеки, упомянутые ralf htp, и перевел их как мог. Теперь я могу получить ответ через драйвер от SPI, но возвращаю только значение «0xFF». В одном случае я получил ответ регистра управления, который ожидал, но он не повторился, и я пытаюсь воссоздать точную настройку (хотя я почти уверен, что у меня уже есть). Новый код ниже.
#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// initializations
void Clock_Init(void);
void USART2_Init(void);
void SPI1_Init(void);
// spi1
void csHigh(void);
void csLow(void);
void selectChip(void);
void deselectChip(void);
uint8_t transfer(uint8_t value);
uint8_t readReg(uint8_t address);
void writeReg(uint8_t address, uint8_t value);
void writeWR(void);
void writeCR0(void);
void writeCR1(void);
void writeCR2(void);
void writeCR3(void);
// driver functionality
void init(void);
bool verifySettings(void);
void applySettings(void);
void resetSettings(void);
void enableDriver(void);
void disableDriver(void);
void setCurrentMilliamps(uint16_t current);
uint16_t readPosition(void);
void setDirection(bool value);
void setStepMode(uint8_t mode);
void sleep(void);
void sleepStop(void);
void stepOnRisingEdge(void);
void stepOnFallingEdge(void);
void setPwmFrequencyDouble(void);
void setPwmFrequencyDefault(void);
void setPwmJitterOn(void);
void setPwmJitterOff(void);
void setPwmSlope(uint8_t emc);
void setSlaGainDefault(void);
void setSlaGainHalf(void);
void setSlaTransparencyOff(void);
void setSlaTransparencyOn(void);
uint8_t readStatusReg(uint8_t address);
void nxtHigh(void);
void nxtLow(void);
void dirHigh(void);
void dirLow(void);
void Step(void);
// general functionality
void DelayTicks(uint32_t ticks);
void DelayMS(int n);
void DelayUS(uint32_t n);
void printHex(uint8_t data);
// ENUMERATIONS: start
enum stepMode
{
MicroStep128 = 128,
MicroStep64 = 64,
MicroStep32 = 32,
MicroStep16 = 16,
MicroStep8 = 8,
MicroStep4 = 4,
MicroStep2 = 2,
MicroStep1 = 1,
CompensatedHalf = MicroStep2,
CompensatedFullTwoPhaseOn = MicroStep1,
CompensatedFullOnePhaseOn = 200,
UncompensatedHalf = 201,
UncompensatedFull = 202,
};
enum nonLatchedStatusFlag
{
OPENY = (1 << 2),
OPENX = (1 << 3),
WD = (1 << 4),
CPFAIL = (1 << 5),
TW = (1 << 6)
};
enum latchedStatusFlag
{
OVCXNB = (1 << 3),
OVCXNT = (1 << 4),
OVCXPB = (1 << 5),
OVCXPT = (1 << 6),
TSD = (1 << 10),
OVCYNB = (1 << 11),
OVCYNT = (1 << 12),
OVCYPB = (1 << 13),
OVCYPT = (1 << 14)
};
enum regAddr
{
WR = 0x00,
CR0 = 0x10,
CR1 = 0x20,
CR2 = 0x30,
CR3 = 0x90,
SR0 = 0x40,
SR1 = 0x50,
SR2 = 0x60,
SR3 = 0x70,
SR4 = 0xA0
};
// ENUMERATIONS: end
// declarations
uint8_t wr;
uint8_t cr0;
uint8_t cr1;
uint8_t cr2;
uint8_t cr3;
// PA2 / D1 -> USART2 TX -> transmit to PC
// PA3 / D2 -> USART2 RX -> receive from PC
// PA4 / A2 -> CS -> chip select (official)
// PA5 / D13 -> SCK -> clock source
// PA6 / D12 -> MISO -> master in slave out
// PA7 / D11 -> MOSI -> master out slave in
// PB3 / D3 -> NXT -> next step
// PB4 / D5 -> DIR -> direction
// PC7 / D9 -> CS -> chip select (unofficial)
int main(void)
{
Clock_Init();
USART2_Init();
SPI1_Init();
init();
nxtLow();
dirLow();
DelayMS(1);
resetSettings();
setCurrentMilliamps(132);
setStepMode(64);
enableDriver();
printHex(readReg(CR2));
printf("\r\n");
while (1)
{
dirHigh();
for (unsigned int i = 0; i < 64; i++)
{
Step();
}
DelayMS(300);
dirLow();
for (unsigned int i = 0; i < 64; 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 9
// -> 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
//
//
// USART2: start
int USART2_Write(int ch)
{
while (!(USART2->ISR & 0x00000080));
USART2->TDR = (ch & 0xFF);
return ch;
}
int USART2_Read(void)
{
while (!(USART2->ISR & 0x00000020));
return USART2->RDR;
}
// USART2: 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_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();
}
void writeWR(void)
{
writeReg(WR, wr);
}
void writeCR0(void)
{
writeReg(CR0, cr0);
}
void writeCR1(void)
{
writeReg(CR1, cr1);
}
void writeCR2(void)
{
writeReg(CR2, cr2);
}
void writeCR3(void)
{
writeReg(CR3, cr3);
}
// SPI1: end
//
//
// DRIVER FUNCTIONALITY: start
void init(void)
{
csHigh();
}
bool verifySettings(void)
{
return readReg(WR) == wr && readReg(CR0) == cr0 && readReg(CR1) == cr1 && readReg(CR2) == cr2 && readReg(CR3) == cr3;
}
void applySettings(void)
{
writeReg(CR2, cr2);
writeReg(WR, wr);
writeReg(CR0, cr0);
writeReg(CR1, cr1);
writeReg(CR3, cr3);
}
void resetSettings(void)
{
wr = cr0 = cr1 = cr2 = cr3 = 0;
applySettings();
}
void enableDriver(void)
{
cr2 |= 0b10000000;
applySettings();
}
void disableDriver(void)
{
cr2 &= ~0b10000000;
applySettings();
}
void setCurrentMilliamps(uint16_t current)
{
uint8_t code = 0;
if (current >= 3000) { code = 0b11001; }
else if (current >= 2845) { code = 0b11000; }
else if (current >= 2700) { code = 0b10111; }
else if (current >= 2440) { code = 0b10110; }
else if (current >= 2240) { code = 0b10101; }
else if (current >= 2070) { code = 0b10100; }
else if (current >= 1850) { code = 0b10011; }
else if (current >= 1695) { code = 0b10010; }
else if (current >= 1520) { code = 0b10001; }
else if (current >= 1405) { code = 0b10000; }
else if (current >= 1260) { code = 0b01111; }
else if (current >= 1150) { code = 0b01110; }
else if (current >= 1060) { code = 0b01101; }
else if (current >= 955) { code = 0b01100; }
else if (current >= 870) { code = 0b01011; }
else if (current >= 780) { code = 0b01010; }
else if (current >= 715) { code = 0b01001; }
else if (current >= 640) { code = 0b01000; }
else if (current >= 585) { code = 0b00111; }
else if (current >= 540) { code = 0b00110; }
else if (current >= 485) { code = 0b00101; }
else if (current >= 445) { code = 0b00100; }
else if (current >= 395) { code = 0b00011; }
else if (current >= 355) { code = 0b00010; }
else if (current >= 245) { code = 0b00001; }
cr0 = (cr0 & 0b11100000) | code;
writeCR0();
}
uint16_t readPosition(void)
{
uint8_t sr3 = readStatusReg(SR3);
uint8_t sr4 = readStatusReg(SR4);
return ((uint16_t)sr3 << 2) | (sr4 & 3);
}
void setDirection(bool value)
{
if (value)
{
cr1 |= 0x80;
}
else
{
cr1 &= ~0x80;
}
writeCR1();
}
int getDirection(void)
{
return cr1 >> 7 & 1;
}
void setStepMode(uint8_t mode)
{
uint8_t esm = 0b000;
uint8_t sm = 0b000;
switch (mode)
{
case MicroStep32: sm = 0b000; break;
case MicroStep16: sm = 0b001; break;
case MicroStep8: sm = 0b010; break;
case MicroStep4: sm = 0b011; break;
case CompensatedHalf: sm = 0b100; break;
case UncompensatedHalf: sm = 0b101; break;
case UncompensatedFull: sm = 0b110; break;
case MicroStep128: esm = 0b001; break;
case MicroStep64: esm = 0b010; break;
case CompensatedFullTwoPhaseOn: esm = 0b011; break;
case CompensatedFullOnePhaseOn: esm = 0b100; break;
}
cr0 = (cr0 & ~0b11100000) | (sm << 5);
cr3 = (cr3 & ~0b111) | esm;
writeCR0();
writeCR3();
}
void sleep(void)
{
cr2 |= (1 << 6);
applySettings();
}
void sleepStop(void)
{
cr2 &= ~(1 << 6);
applySettings();
}
void stepOnRisingEdge(void)
{
cr1 &= ~0b01000000;
writeCR1();
}
void stepOnFallingEdge(void)
{
cr1 |= 0b01000000;
writeCR1();
}
void setPwmFrequencyDouble(void)
{
cr1 |= (1 << 3);
writeCR1();
}
void setPwmFrequencyDefault(void)
{
cr1 &= ~(1 << 3);
writeCR1();
}
void setPwmJitterOn(void)
{
cr1 |= (1 << 2);
writeCR1();
}
void setPwmJitterOff(void)
{
cr1 &= ~(1 << 2);
writeCR1();
}
void setPwmSlope(uint8_t emc)
{
cr1 = (cr1 & ~0b11) | (emc & 0b11);
writeCR1();
}
void setSlaGainDefault(void)
{
cr2 &= ~(1 << 5);
applySettings();
}
void setSlaGainHalf(void)
{
cr2 |= (1 << 5);
applySettings();
}
void setSlaTransparencyOff(void)
{
cr2 &= ~(1 << 4);
applySettings();
}
void setSlaTransparencyOn(void)
{
cr2 |= (1 << 4);
applySettings();
}
uint8_t readStatusReg(uint8_t address)
{
return readReg(address) & 0x7F;
}
void nxtHigh(void)
{
GPIOB->BSRR |= 0x00000008;
}
void nxtLow(void)
{
GPIOB->BSRR |= 0x00080000;
}
void dirHigh(void)
{
GPIOB->BSRR |= 0x00000010;
}
void dirLow(void)
{
GPIOB->BSRR |= 0x00100000;
}
void Step(void)
{
nxtHigh();
DelayUS(3);
nxtLow();
DelayUS(3);
DelayUS(1000);
}
// DRIVER FUNCTIONALITY: 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));
}
void printHex(uint8_t data)
{
printf("0x%02x", data);
}
// GENERAL FUNCTIONALITY: end
//
//
// INTERFACE FUNCTIONALITY: start
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};
int fgetc(FILE *f)
{
int c;
c = USART2_Read();
if (c == '\r')
{
USART2_Write(c);
c = '\n';
}
USART2_Write(c);
return c;
}
int fputc(int c, FILE *f)
{
return USART2_Write(c);
}