Управление AMIS-30543 с помощью STM32F030R8 через SPI - PullRequest
2 голосов
/ 07 февраля 2020

Я пытаюсь заставить мою плату 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);
}

1 Ответ

2 голосов
/ 07 февраля 2020

Вы неправильно настроили AMIS-30543-D. Для точной настройки AMIS-30543-D необходимо записать несколько регистров с использованием SPI с информацией о конфигурации (sm, esm, ...). Полный драйвер для AMIS-30543-D находится в https://pololu.github.io/amis-30543-arduino/_a_m_i_s30543_8h_source.html регистры, которые должны быть записаны, указаны в разделе кода

 void writeWR()
  554     {
  555         driver.writeReg(WR, wr);
  556     }
  557 
  559     void writeCR0()
  560     {
  561         driver.writeReg(CR0, cr0);
  562     }
  563 
  565     void writeCR1()
  566     {
  567         driver.writeReg(CR1, cr1);
  568     }
  569 
  571     void writeCR3()
  572     {
  573         driver.writeReg(CR3, cr3);
  574     }

Это Arduino C, но вы можете легко перевести это на обычный C.

Что записывается в регистры через SPI и почему вы можете увидеть в техническом описании / справочном руководстве AMIS-30543: https://www.onsemi.com/pub/Collateral/AMIS-30543-D.PDF

Т.е. настройка шага режим, страница спецификации 12-24

void setStepMode(uint8_t mode)
  341     {
  342         // Pick 1/32 micro-step by default.
  343         uint8_t esm = 0b000;
  344         uint8_t sm = 0b000;
  345 
  346         // The order of these cases matches the order in Table 12 of the
  347         // AMIS-30543 datasheet.
  348         switch(mode)
  349         {
  350         case MicroStep32: sm = 0b000; break;
  351         case MicroStep16: sm = 0b001; break;
  352         case MicroStep8: sm = 0b010; break;
  353         case MicroStep4: sm = 0b011; break;
  354         case CompensatedHalf: sm = 0b100; break; /* a.k.a. MicroStep2 */
  355         case UncompensatedHalf: sm = 0b101; break;
  356         case UncompensatedFull: sm = 0b110; break;
  357         case MicroStep128: esm = 0b001; break;
  358         case MicroStep64: esm = 0b010; break;
  359         case CompensatedFullTwoPhaseOn: esm = 0b011; break;  /* a.k.a. MicroStep 1 */
  360         case CompensatedFullOnePhaseOn: esm = 0b100; break;
  361         }
  362 
  363         cr0 = (cr0 & ~0b11100000) | (sm << 5);
  364         cr3 = (cr3 & ~0b111) | esm;
  365         writeCR0();
  366         writeCR3();
  367     }

Дополнительно проверьте, работает ли связь SPI

ответ на комментарий:

Код SPI

   27 class AMIS30543SPI
   28 {
   29 public:
   30 
   33     void init(uint8_t slaveSelectPin) { ssPin = slaveSelectPin;
   34 
   35         digitalWrite(ssPin, HIGH);
   36         pinMode(ssPin, OUTPUT);
   37     }
   38 
   40     uint8_t readReg(uint8_t address)
   41     {
   42         selectChip();
   43         transfer(address & 0b11111);
   44         uint8_t dataOut = transfer(0);
   45         deselectChip();
   46         return dataOut;
   47     }
   48 
   50     void writeReg(uint8_t address, uint8_t value)
   51     {
   52         selectChip();
   53         transfer(0x80 | (address & 0b11111));
   54         transfer(value);
   55 
   56         // The CS line must go high after writing for the value to actually take
   57         // effect.
   58         deselectChip();
   59     }
   60 
   61 private:
   62 
   63     SPISettings settings = SPISettings(500000, MSBFIRST, SPI_MODE0);
   64 
   65     uint8_t transfer(uint8_t value)
   66     {
   67         return SPI.transfer(value);
   68     }
   69 
   70     void selectChip()
   71     {
   72         digitalWrite(ssPin, LOW);
   73         SPI.beginTransaction(settings);
   74     }
   75 
   76     void deselectChip()
   77     {
   78        digitalWrite(ssPin, HIGH);
   79        SPI.endTransaction();
   80 
   81        // The CS high time is specified as 2.5 us in the AMIS-30543 datasheet.
   82        delayMicroseconds(3);
   83     }
   84 
   85     uint8_t ssPin;
   86 };

Он содержит некоторый специфицированный для Arduino синтаксис c, такой как digitalWrite(), который может быть переведен в GPIO_SetBits(GPIOx, GPIO_Piny), ... (полное руководство по GPIO находится в https://stm32f4-discovery.net/2014/04/stm32f429-discovery-gpio-tutorial-with-onboard-leds-and-button/). То же самое можно сделать с кодом Arduino SPI, исходный код arduino spi.h находится в https://www.arduino.cc/en/Reference/SPI и https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SPI/src/SPI.h для AVR, который можно преобразовать в ARM.

...