春风知意 发表于 2023-12-11 17:15

SPI片选相关问题

用示波器去抓波形的时候发现片选会在时钟和MOSI前面就拉高片选信号,此时我的函数发送数据都还没开始执行片选就拉高了,主要的问题还是时序不同步,请教下大家这是什么问题导致的具体的配置如下
#include "./flash/spi.h"

void spi_gpio_init(void)
{
    GPIO_InitType GPIO_InitStructure;

    RCC_Pclk2_Config(RCC_HCLK_DIV2);

    RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_SPI2);

    RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA|RCC_AHB_PERIPH_GPIOB);

    RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);


    GPIO_Structure_Initialize(&GPIO_InitStructure);

    // SPI_MISOPA9 AF1||SPI_CLKPA10 AF6 ||SPI_MOSI   PB1 AF2 ||SPI_CSPA15||
    GPIO_InitStructure.Pin            = SPI_MISO;
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF1_SPI2;
    GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);


    GPIO_InitStructure.Pin            = SPI_MOSI;
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_SPI2;
    GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);

    /* If CLKPOL is HIGH, set SPI_SCK GPIO to GPIO_PULL_UP, otherwise set to GPIO_PULL_DOWN */
    GPIO_InitStructure.Pin            = SPI_CLK;   
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Pull      = GPIO_PULL_UP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF6_SPI2;
    GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);


    // GPIO_InitStructure.Pin          = SPI_CS;
    // GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_OUT_PP;
    // GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
    // GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);


}

void spi_gpio_cs_init(void)
{
    GPIO_InitType GPIO_InitStructure;

    GPIO_InitStructure.Pin          = SPI_CS;
    GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_OUT_PP;
    GPIO_InitStructure.GPIO_Pull      = GPIO_PULL_UP;
    GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
    GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
    GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
}


void spi_init(void)
{
    SPI_InitType SPI_InitStructure;

    spi_gpio_init();
    spi_gpio_cs_init();
    SPI_I2S_Reset(SPI2);

    SPI_Initializes_Structure(&SPI_InitStructure);
    SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
    SPI_InitStructure.SpiMode       = SPI_MODE_MASTER;
    SPI_InitStructure.DataLen       = SPI_DATA_SIZE_8BITS;
    SPI_InitStructure.CLKPOL      = SPI_CLKPOL_HIGH;
    SPI_InitStructure.CLKPHA      = SPI_CLKPHA_SECOND_EDGE;
    SPI_InitStructure.NSS         = SPI_NSS_SOFT;
    /* It is recommended that the SPI master mode of the C version chips should not exceed 18MHz */
    SPI_InitStructure.BaudRatePres= SPI_BR_PRESCALER_256;
    SPI_InitStructure.FirstBit      = SPI_FB_MSB;
    //SPI_InitStructure.CRCPoly       = 7;
    SPI_Initializes(SPI2, &SPI_InitStructure);
    SPI_SS_Output_Enable(SPI2);
    /* Enable SPI_MASTER */
   SPI_Set_Nss_Level(SPI2,SPI_NSS_HIGH);

    SPI_ON(SPI2);

    SPI_CS_HIGH();
}


uint8_t spi_tramsit_receive(uint8_t data)
{
   uint8_t brxbuff;
//    printf("data = %2X\n",(uint16_t)data);
   SPI_I2S_Data_Transmit(SPI2,data);
   while(SPI_I2S_Flag_Status_Get(SPI2, SPI_I2S_FLAG_TE) == SET);
   brxbuff = SPI_I2S_Data_Get(SPI2);
   while(SPI_I2S_Flag_Status_Get(SPI2, SPI_I2S_FLAG_BUSY) != SET) ;
   return brxbuff;
}
**/

下面主要是main函数中的内容和宏定义
#define SPI_CS_HIGH()   GPIO_Pins_Set(GPIOA,GPIO_PIN_15);
#define SPI_CS_LOW()    GPIO_Pins_Reset(GPIOA,GPIO_PIN_15);
//PA
#define SPI_MISO    GPIO_PIN_9
#define SPI_CLK   GPIO_PIN_10
#define SPI_CS      GPIO_PIN_15
//PB
#define SPI_MOSI    GPIO_PIN_1



uint32_t spi_read_id(void)
{
   uint32_t data = 0 ;
   uint8_t receiveid = {0x00};
   uint8_t id = 0;
   SPI_CS_LOW();
   spi_tramsit_receive(0x01);
   receiveid = spi_tramsit_receive(0X01);
   receiveid = spi_tramsit_receive(0X01);
   receiveid = spi_tramsit_receive(0X01);
   SPI_CS_HIGH();

   data =receiveid <<16 |receiveid<<8| receiveid;
   return id ;

}


int main(void)
{
    uint8_t data = 0xAA;
    uint32_t id = 0;
    uart_init();   
    spi_flash_init();
    while(1)
    {
         id = spi_read_id();
         printf("id = %d",id);
      SysTick_Delay_Ms(1000);


   }
}

春风知意 发表于 2023-12-11 17:20

这是时序图

jobszheng 发表于 2023-12-12 08:50

我看您在初始化配置SPI时,有使能硬件CS引脚。您将这个disable掉,即使用手动GPIO控制CS引脚,和当前的一样。
这行代码:
SPI_SS_Output_Enable(SPI2);

春风知意 发表于 2023-12-12 09:27

您好,在屏蔽后也是类似的波形,是不是漏掉哪些关键关键的配置导致的?

delin17 发表于 2023-12-12 11:57

发送前,是不是应该清一下标志?

春风知意 发表于 2023-12-12 16:00

delin17 发表于 2023-12-12 11:57
发送前,是不是应该清一下标志?

这里应该是不用清楚的,因为提供的接口里面没有这部分状态标志位

jobszheng 发表于 2023-12-12 18:00

https://bbs.21ic.com/icview-3294508-1-1.html
这个是我之前发布的读写TF卡时使用SPI外设的初始化代码

jobszheng 发表于 2023-12-12 18:02

uint8_t bsp_spi_sendbyte(uint8_t dat)
{
/*!< Loop while DAT register in not emplty */
while (SPI_I2S_GetStatus(SPI1, SPI_I2S_TE_FLAG) == RESET)
    ;

/*!< Send byte through the SPI1 peripheral */
SPI_I2S_TransmitData(SPI1, dat);

/*!< Wait to receive a byte */
while (SPI_I2S_GetStatus(SPI1, SPI_I2S_RNE_FLAG) == RESET)
    ;

/*!< Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPI1);
}
这个是使用官方提供的固件库进行的读写API。
以上代码经验证通过。



春风知意 发表于 2023-12-13 10:58

jobszheng 发表于 2023-12-12 18:02
这个是使用官方提供的固件库进行的读写API。
以上代码经验证通过。

问题我找到了,感谢您的回复,提早的上拉是因为我收发的那个函数判断标志位有问题,需要判断发送接收,而不能判断忙碌,再次十分感谢您的回复

春风知意 发表于 2023-12-13 11:06

春风知意 发表于 2023-12-13 10:58
问题我找到了,感谢您的回复,提早的上拉是因为我收发的那个函数判断标志位有问题,需要判断发送接收,而 ...

关于您提到官方提供的固件库,您方便分享官方库链接给我吗,我参考的官方库里面没有收发这些api,只是简单的示例。

jobszheng 发表于 2023-12-13 13:52

楼主,您现在应该就使用的是官方的固件库在编写。
在ftp://download.nationstech.com 这个FTP里面,对应的型号文件夹里面的
类似 Nationstech.N32G45x_Library.2.1.0 这个文件夹

春风知意 发表于 2023-12-13 14:10

jobszheng 发表于 2023-12-13 13:52
楼主,您现在应该就使用的是官方的固件库在编写。
在ftp://download.nationstech.com 这个FTP里面,对应的 ...

是的,我这里的显示的版本是1.2.1

两只袜子 发表于 2023-12-15 15:34

可能是硬件方面的问题

jcky001 发表于 2023-12-15 15:34

如果片选信号的拉高是由驱动或固件控制的,那么可能是驱动或固件中的某些设置或代码导致了这个问题。

cr315 发表于 2023-12-15 15:35

调整示波器设置
页: [1]
查看完整版本: SPI片选相关问题