打印
[STM32C0]

STM32c031c6 SPI Slave Transmit Only模式的疑问

[复制链接]
357|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
两只袜子|  楼主 | 2025-2-24 15:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32c031c6 SPI Slave Transmit Only模式的疑问。

SPI配置如下。

hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_SLAVE;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
业务场景:

我希望用MCU将自己模拟成一个32位的移位寄存器,我配置了DMA,CS引脚使用的是外部EXTI。

void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == CS_Pin) {
//        cs = true;
//        if (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY)
//            HAL_SPI_Abort(&hspi1);


        if (HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_READY) {
            if (HAL_OK != HAL_SPI_Transmit_DMA(&hspi1, gpio_value, 8)) {
//                Error_Handler();
//                HAL_UART_Transmit(&huart1, "Error_Handler\n", 14, 10);
            }
        }

    }
}
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == CS_Pin) {
//        CLEAR_BIT(hspi1.Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
//        __HAL_SPI_DISABLE(&hspi1); // 禁用 SPI 外设
        for (int i = 0; i < 30; i++) {
            int j = i + 1;

            if (HAL_GPIO_ReadPin(portmap[i], pinmap[i]) == GPIO_PIN_RESET) {
                SET_BIT(gpio_value[j / 8], 1 << (j % 8));
            } else {
                CLEAR_BIT(gpio_value[j / 8], 1 << (j % 8));
            }
        }



        if (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_BUSY) {
//            HAL_UART_Transmit_IT(&huart1, "HF\n", 3);
            HAL_SPI_Abort_IT(&hspi1);
//            HAL_UART_Transmit_IT(&huart1, "Hf\n", 3);
//
        }

    }

}
目前这样会遇到问题,就是我并不知道SPI MASTER到底需要几个字节的内容。如果双方商量好要4个字节,那么没问题。

业务场景下这个小模块面对的master 可能要3个字节 可能要5个字节,这不是我能决定的,也不是可以预知的。

在slave发送8字节的情况下,master如果只请求了3字节,cs就拉高了,这时候spi外设的FIDO还是被DMA填满了3字节。虽然我使用了Abort,但是FIFO好像并不会被清除,而且会等待发送完成,但是这时候没有CLK了,就会导致Abort 在SPI_DMATxAbortCallback函数当中卡住。此时会错过下一次Master的数据请求。

请问有什么可以解决的方案吗?最优解决策略应该就是在CS上升沿中断当中取消SPI然后清空队列,但是我不知道该如何实现。

使用特权

评论回复
沙发
wangjiahao88| | 2025-3-6 15:06 | 只看该作者
个人认为,可以参考ADC之类的SPI总线器件;例如大厂ADI;TI的;他们的产品从器件一般用的都是固定的字节数;
而且每个地址对应一个不同的通道;
所以,老夫简易你也使用固定的字节,例如32Mbps的速率,存放固定的字节个数,例如128个Byte;类似于一个簇的写法,比较好。
或者先请求,地址、长度;从机再放数据;

使用特权

评论回复
板凳
wangjiahao88| | 2025-3-6 15:06 | 只看该作者
个人认为,可以参考ADC之类的SPI总线器件;例如大厂ADI;TI的;他们的产品从器件一般用的都是固定的字节数;
而且每个地址对应一个不同的通道;
所以,老夫简易你也使用固定的字节,例如32Mbps的速率,存放固定的字节个数,例如128个Byte;类似于一个簇的写法,比较好。
或者先请求,地址、长度;从机再放数据;

使用特权

评论回复
地板
classroom| | 2025-3-7 10:34 | 只看该作者
可以考虑用软件模拟SPI通信。

使用特权

评论回复
5
laocuo1142| | 2025-3-7 11:56 | 只看该作者
修改DMA配置保证在CS上升沿时能够正确地中止DMA传输。

使用特权

评论回复
6
flycamelaaa| | 2025-3-7 13:03 | 只看该作者
用轮询和超时机制但此方法可能会增加CPU的负载

使用特权

评论回复
7
powerantone| | 2025-3-7 15:00 | 只看该作者
用中断而非DMA

使用特权

评论回复
8
stormwind123| | 2025-3-7 17:00 | 只看该作者
可以在CS上升沿中断中尝试重置SPI外设。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2109

主题

7957

帖子

11

粉丝