STM32 SPI 从机配置

问题描述 投票:0回答:1

我正在尝试通过 SPI 在两个 NucleoF303K8 板之间进行通信。 其中一块板为主控,由 UART 控制。它可以通过 SPI 发送 3 种消息:

  1. {0x01 0x00 0x00 0x00}
    表示“读取值”

  2. {0x81 0x00 0x00 0x00}
    表示“设置值 = 0”

  3. {0x81 0x01 0x00 0x00}
    表示“设置值 = 1”

另一块板是从板。它根据命令设置(并获取)LED 引脚值。

Slave算法如下:

  1. NSS_Pin
    变低时,
    EXTI_Callback
    被调用,并开始接收1字节

  2. 收到第一个字节后,我猜测它是读出命令还是写入命令

  3. 如果是读回,我使用

    SPI_DMA
    来传输值,如果是写入,我使用
    SPI DMA
    来接收值

  4. NSS_Pin
    再次达到高电平时,如果是
    writeIn
    ,则从机处理消息,或者如果是
    readout

    ,则等待另一个命令

这是代码:

extern DMA_HandleTypeDef hdma_spi1_tx;
extern DMA_HandleTypeDef hdma_spi1_rx;
extern SPI_HandleTypeDef hspi1;


uint8_t txb[16] = {0x01,0xAA,0xBB};
uint8_t rxb[16] = {};
uint8_t code = 0;
uint8_t op = 0; // 0: idle, 1: readout, 2: writein

void readOut(){
    op = 1;
    HAL_SPI_Transmit_DMA(&hspi1, txb,3);
}
void receiveWriteIn(){
    op = 2;
    HAL_SPI_Receive_DMA(&hspi1, rxb, 3);
}
void processWriteIn(){
    HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, (GPIO_PinState)rxb[0]);
}

void SystemLoad(){
    HAL_GPIO_WritePin(LD3_GPIO_Port,LD3_Pin,GPIO_PIN_SET);
    while(1){
    }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    HAL_SPI_DMAStop(&hspi1);
    if(GPIO_Pin == NSS_Pin){
        if(HAL_GPIO_ReadPin(NSS_GPIO_Port, NSS_Pin) == GPIO_PIN_RESET){
            op = 0;
            HAL_SPI_Receive_DMA(&hspi1,&code,1);
        }else{
            if(op == 2){
                processWriteIn();
            }
            op = 0;
            code = 0;
        }
    }
}

inline void mainCbk(SPI_HandleTypeDef *hspi){
    HAL_SPI_DMAStop(hspi);
    if(hspi == &hspi1){
        if(op == 0){
            if(code & 0x80){
                receiveWriteIn();
            }else{
                readOut();
            }
        }
    }
}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi){
    mainCbk(hspi);
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi){
    mainCbk(hspi);
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi){
    mainCbk(hspi);
}

CubeMX 中的从站设置为:

  1. 1 个 GPIO 输出 (LED) 和 1 个 EXTI

  2. SPI1
    ,具有
    DMARX
    (优先级高)和
    DMATX
    (优先级非常高)并且
    NVIC
    为 DMA 通道和 SPI1 全局中断启用

  3. NVIC优先级,Debug、SysTick等优先级最高(0),EXTI和SPI1全局中断优先级较低(1)

  4. HCLK 为 64 MHz,PCLK1 为 32 MHz,PCLK2 为 64 MHz

  5. 主设备的 SPI 速度为 250 KBit/s

由于某种原因,我有两个主要问题:

  1. writeIn
    数据以
    rxbuffer
    循环迁移。 “设置值 = 1”中的
    0x01
    出现在
    rxb[0]
    中,然后出现在
    rxb[1]
    rxb[2]
    中,并从每个 SPI 消息开始。

  2. 从设备传输的读出数据也表现得很奇怪: 我在主设备上收到的前两条消息(并使用在线逻辑分析仪查看)正确的值:

{0x00 0x01 0xAA 0xBB}

但后来有些事情发生了变化,它变成了

{0xBB 0x01 0xAA 0xBB}

{0xBB 0x00 0x01 0xBB}

{0xBB 0x81 0xAA 0xBB}
如果我在读出后尝试写入它就会变得像

{0xBB 0xBB 0xBB 0xBB}

虽然

rxb
中的
HAL_SPI_Receive_DMA(&hspi1, rxb, 3);
充满了0

我查看了SPI1.DR寄存器,但它是0,所以我不知道该怎么想。我尝试过在消息 TX 和 RX 回调上进行 DMAStop,也尝试过 SPI_Abort。

我以不同的方式混合了优先级:

  1. 一切平等

  2. EXTI > SPI > DMARX > DMATX(和 TX > RX)

  3. DMATX > DMARX > EXTI = SPI

  4. DMATX > DMARX > EXTI > SPI

  5. DMATX > DMARX > SPI > EXTI

我也尝试过使用

HAL_SPI_Transmit_IT
,但即使 DMA 完全被禁用,也得到相同的结果。

理论上它必须正确工作,因为 SPI 缓冲区在下一个字节 si 被传输之前被填充,但它似乎表现得很奇怪。

配置我的设备的正确方法是什么?或者也许MCU无法以这种方式控制,因为它必须使用软件核心来处理消息,并且有正确的方法来做到这一点?

stm32 spi stm32-hal
1个回答
0
投票

你能让它在没有DMA或中断的情况下工作吗?一步一步来吧

SPI Echo 示例(1 字节命令,1 字节数据,SPI_DataSize_8b / 我手动设置从机选择引脚 / 如果需要单独读取和写入数据,并且需要实现设定值回读,可以使用 FromMaster/ToMaster 数组改进此代码):

void SPI_Slave_Process(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, SPI_HandleTypeDef *hspi, uint8_t* FromMaster, uint8_t* ToMaster) {
    static uint8_t RxData;
    static uint8_t TxData;
    while(!(HAL_GPIO_ReadPin(GPIOx, GPIO_Pin))) {
        HAL_SPI_Receive(hspi, &RxData, 1, 2);
        TxData = RxData;
        HAL_SPI_Transmit(hspi, &TxData, 1, 2);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.