我使用STM32G030C8T6作为SPI(从设备),它从Raspberry pi(主设备)接收字符,接收工作完美!那里没有问题,但是当我尝试从 STM32 向 Pi 发送数据时,STM32 似乎卡住了一段时间,并且 Pi rx 缓冲区仅重复填充一位,例如,如果我发送 char buf[6] = { 0,1,2,3,4,5}; Pi 接收 (111111) 或 (333333),具体取决于我发送的字符数。
我到底想做什么?
我想将ADC数据从STM32(从模式)传输到Pi(主模式),到目前为止它只接收一位我重复。
有人可以帮我实现这个目标吗?
这是我的 SPI 配置:
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
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;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
然后是读取字符、发送数据和字符串的函数
char SPI_read(void)
{
// SPI1->SR is the STATUS REGISTER on SPI1 Bus
// SPI1->DR is the DATA REGISTER on SPI1 Bus
char data;
while(!(SPI1->SR & SPI_SR_RXNE));
while(SPI1->SR & SPI_SR_BSY);
data = SPI1->DR;
printmsg("%c",data);
return data;
}
void spi_Send(char caracSend)
{
while(!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = caracSend;
}
void spi_send_string(char* stringSend)
{
int i=0;
unsigned int sizeChar = 0;
sizeChar = strlen(stringSend);
__NOP();
for(i=0;i<sizeChar;i++)
{
spi_Send(stringSend[i]);
}
}
这是我从 Pi 接收数据的函数,我在主 while 循环中调用它。
void SPI_Receive_Commands(void)
{
while(HAL_GPIO_ReadPin(SPI_SS_GPIO_Port, SPI_SS_Pin) == GPIO_PIN_RESET);
{
HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buf, 10, 100);
if(spi_buf[0] == 'v')
{
memset(spi_buf,'*',10);
printmsg("Character V received\r\n");
Battery_Voltage();
spi_send_string(batteryVoltage);
spi_Send('v');
printmsg("Sending battery voltage\r\n");
}
}
}
非常感谢您提前帮助我。
初始化。当您读取和写入字节时,您需要将 RX FIFO 阈值设置为 1/4。我不知道如何在 HAL 中做到这一点。寄存器级别只需设置
FRXTH
寄存器中的 CR2
位
DR
寄存器必须以8位操作访问。
您不需要在轮询模式下使用 BSY 位,除非您想禁用 SPI 外设。
void spi_Send(char caracSend)
{
while(!(SPI1->SR & SPI_SR_TXE));
*(volatile uint8_t *)&SPI1->DR = caracSend;
}
void spi_send_string(char* str)
{
if(str) while(*str) spi_Send(*str++);
}
char SPI_read(void)
{
char data;
while(!(SPI1->SR & SPI_SR_RXNE));
data = *(volatile uint8_t *)&SPI1->DR;
return data;
}
请记住,树莓派必须发送虚拟数据以允许从设备发送信息。从机不生成时钟信号,并且时钟必须由主机
提供您可以使用STM32作为SPI从机,但SPI绝对不适用于发送/接收字符串。它用于从从设备读取和写入精确的寄存器。 SPI 外设(如果我没记错的话)只有 16 位缓冲区。
如果必须发送 ascii 解码字符串,则应该选择较慢的异步协议。
如果您必须使用 SPI 更快地读取数据,则应从从机发送值而不进行 ASCII 解码。
我建议使用 STM32CubeIDE 及其从 .ioc 文件生成代码。它将对 SPI 进行低级初始化。你所需要使用的就是这两个函数:
HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
SPI Echo 示例(1 字节命令,1 字节数据/我手动设置从机选择引脚/如果需要单独读取和写入数据,并且需要实现设定值回读,可以使用 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);
}
}