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然后清空队列,但是我不知道该如何实现。 |