grayloach 发表于 2019-11-19 00:34:04

SPI读取数据是MOSI怎么一直保持0xFF输出?

最近在做SD卡的程序,使用模拟SPI可以正常读写,但是改成硬件SPI后发现SD卡反馈的数据不对。
通过时序对比发现,异常的SD卡读取时序读取前的Dummy信号将MOSI输出为上一次发送的数据了,
比如上一次发送的数据是0x87,那么当进行SPI读取时,它会将MOSI设置为0x87,后面的读取才是
0xFF,这样就导致了连续发送了两次0x87,使得通信异常。

请问有没有办法让SPI读取时保持MOSI为0xFF?

正常的SD卡读取时序:


异常的SD卡读取时序:


端口初始化代码:
static void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_9, GPIO_PIN_RESET);

/*Configure GPIO pin : PA4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
       
        GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
       
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);        //端口不写1会导致一直读入的都是低电平

        __HAL_RCC_GPIOC_CLK_ENABLE();
        GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
       
/*Configure GPIO pin : PG9 */
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

/*Configure GPIO pins : PG12 PG13 PG14 PG15 */
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

}
SPI初始化代码:
/* SPI1 init function */
static void MX_SPI1_Init(void)
{

/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;//SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;//SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
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(__FILE__, __LINE__);
}

}
SPI发送代码:
        HAL_SPI_Transmit(&hspi1, &d, 1, 1000);
SPI接收代码:
        HAL_SPI_Receive(&hspi1, &r, 1, 1000);


toofree 发表于 2019-11-19 09:52:48

用发送函数读数据,读时肯定会发,发时可以不读(对读取内容不理会)。

likang1202 发表于 2019-11-19 08:51:01

改一下时钟极性和时钟相位试一试

grayloach 发表于 2019-11-22 00:07:06

likang1202 发表于 2019-11-19 08:51
改一下时钟极性和时钟相位试一试

还是一样的,输出转输入后的第一次读数还是会把上一次的数据传输到MOSI端口。

grayloach 发表于 2019-11-22 00:07:59

toofree 发表于 2019-11-19 09:52
用发送函数读数据,读时肯定会发,发时可以不读(对读取内容不理会)。

硬件SPI也可以这么操作?但是貌似STM32的硬件SPI的读写共用了一个DR寄存器,不知道怎么操作了。

grayloach 发表于 2019-11-23 23:38:29

toofree 发表于 2019-11-19 09:52
用发送函数读数据,读时肯定会发,发时可以不读(对读取内容不理会)。

已解决,谢谢!
页: [1]
查看完整版本: SPI读取数据是MOSI怎么一直保持0xFF输出?