我正在尝试将数据从 stm32F411 主设备传输到 stm32F411 从设备。该数据将用于配置数据并将数据写入连接到从站的 SD 卡。我正在使用从站来卸载将数据传输到 SD 卡的工作。从机侧的 SPI 通过轮询处理,不使用 DMA 或中断。这两个项目都是使用 CubeIDE 设置的。
问题在于从站似乎无法正确接收数据,因为数据已损坏、以某种方式移位或丢失字符。从机也没有正确地将数据传输回主机,仅发送看起来像虚拟数据的内容。
主控SPI配置:
static void MX_SPI3_Init(void) {
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi3) != HAL_OK) {
Error_Handler();
}
}
从机 SPI 配置:
static void MX_SPI1_Init(void)
{
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_HARD_INPUT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
掌握逻辑和示例输入:
sd_open_file("Quadcopter.txt", FA_WRITE | FA_READ | FA_OPEN_ALWAYS);
uint8_t sd_open_file(const char *file_name, uint8_t instruction){
uint8_t response[1];
uint8_t command = LOGGER_SD_OPEN_FILE;
uint16_t file_length = strlen(file_name)+1;
uint16_t total_length = file_length+1;
uint8_t transmit_length[] = {(total_length >> 8) & 0xFF, total_length & 0xFF};
uint8_t transmit_buffer[total_length]; // string length, \0 and command
transmit_buffer[0] = instruction;
memcpy(&transmit_buffer[1], file_name, file_length); // Copy the string including null terminator.
HAL_StatusTypeDef status;
slave_select();
status = HAL_SPI_Transmit(m_device_handle, &command, 1, 5000); // send command
status = HAL_SPI_Transmit(m_device_handle, transmit_length, 2, 5000); // send how many bytes the dat will be
status = HAL_SPI_Transmit(m_device_handle, transmit_buffer, total_length, 5000); // send data
status = HAL_SPI_Receive(m_device_handle, response, 1, 5000);
uint8_t data[200];
status = HAL_SPI_Receive(m_device_handle, data, total_length, 1000);
slave_deselect();
...
}
从逻辑:
HAL_StatusTypeDef spi_slave_result_receive = HAL_SPI_Receive(&hspi1, slave_buffer, 1, 1000);
...c
HAL_StatusTypeDef status_receive;
// We ask how much data should we receive.
if((status_receive = HAL_SPI_Receive(&hspi1, slave_buffer, 2, 1000)) != HAL_OK){
break;
}
uint16_t amount_of_data_to_receive = (slave_buffer[0] << 8) | slave_buffer[1];
// Receive the instruction and file name
if( (status_receive = HAL_SPI_Receive(&hspi1, slave_buffer, amount_of_data_to_receive, 1000)) != HAL_OK){
break;
}
// instruction is byte 0
char* extracted_string = extract_string_from_spi_data_at_index(slave_buffer, SLAVE_BUFFER_SIZE, 1);
volatile uint8_t result = sd_open_file(extracted_string, slave_buffer[0]);
HAL_SPI_Transmit(&hspi1, &result, 1, 100);
HAL_SPI_Transmit(&hspi1, slave_buffer, amount_of_data_to_receive, 100);
free(extracted_string);
我尝试通过逻辑分析仪查看 SPI 总线。我可以看到主人正确地传输了一切。从机返回一些错误数据。
我尝试降低SPI总线的频率。没做什么,
我尝试更改从机和主机上的极性和相位。什么都没做
在从站调试期间,我看到它成功到达从站逻辑的末尾。在调试数据中,我可以看到 Slave_buffer 成功完成了指令的第一次读取。通过跳过两个字节并读取第三次读取的字节来搞乱下一次读取。
由于跳过第一个字节,导致第三次读取混乱,跳过更多字节并损坏一些数据。
我尝试只使用一个大数组来获取所有数据,然后再对其进行操作,但效果不佳。这是我现在使用的方法,是迄今为止最好的方法。
我也尝试手动向从机功能提供正确的数据,例如接收和发送的正确数据量,但仍然失败。所以传输是一个完全独立的问题,不是由接收问题引起的。
我编写了一些健全性检查代码,以确保主从通信与主从之间的 LED 一起工作,并且工作完美。它发送一个字节并接收一个字节。
我查看了 stackoverflow 上的 this 帖子,它看起来很相似,因为它没有正确接收数据,但我正在接收一些数据,只是搞砸了,我遇到了再次发送出去的问题。
我预计从机上的 SPI 能够成功接收长度超过 10 个字节的数据并将其至少传输回来。我这样做的计划有缺陷吗?我考虑过将主控连接到闪存芯片并在那里写入,但我喜欢有一个芯片来为我处理 SD 卡写入的想法。如有任何帮助,我们将不胜感激。
编辑: 根据 @wek 的要求,我在健全性检查代码中添加了一个 GPIO 引脚切换,以查看处理一个字节需要多长时间。下面是它的逻辑分析仪输出:
我已经在我的 stm32 上解决了所有这些问题,并为此实现了 DMA SPI RX 和 TX 的工作功能,以及完成所有这些工作的一个简单方法。两者都很好用。
这是我的项目链接: https://github.com/Rokasbarasa1/Logger