簡體   English   中英

通過 SPI 使用 STM32F030R8 控制 AMIS-30543

[英]Control AMIS-30543 with STM32F030R8 via SPI

我試圖讓我的 STM32 板使用 SPI 來控制步進電機(使用 AMIS-30543 驅動器,26M024B2B 步進電機)。 我正在使用 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 位消息來寫入驅動程序,該消息指定什么命令的類型和數據的去向,然后是將填充控制寄存器的 8 位數據。 我使用以下邏輯組裝了第一個數據包......

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);
}

您沒有正確設置 AMIS-30543-D。 為了准確配置 AMIS-30543-D,您必須使用帶有配置信息( smesm 、...)的 SPI 編寫多個寄存器 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/Collat​​eral/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 特定的語法,如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/SPIhttps://github.com/arduino/ArduinoCore- avr/blob/master/libraries/SPI/src/SPI.h用於可轉換為 ARM 的 AVR。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM