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);
}
}
这是时序图
我看您在初始化配置SPI时,有使能硬件CS引脚。您将这个disable掉,即使用手动GPIO控制CS引脚,和当前的一样。
这行代码:
SPI_SS_Output_Enable(SPI2);
您好,在屏蔽后也是类似的波形,是不是漏掉哪些关键关键的配置导致的? 发送前,是不是应该清一下标志? delin17 发表于 2023-12-12 11:57
发送前,是不是应该清一下标志?
这里应该是不用清楚的,因为提供的接口里面没有这部分状态标志位 https://bbs.21ic.com/icview-3294508-1-1.html
这个是我之前发布的读写TF卡时使用SPI外设的初始化代码 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。
以上代码经验证通过。
jobszheng 发表于 2023-12-12 18:02
这个是使用官方提供的固件库进行的读写API。
以上代码经验证通过。
问题我找到了,感谢您的回复,提早的上拉是因为我收发的那个函数判断标志位有问题,需要判断发送接收,而不能判断忙碌,再次十分感谢您的回复 春风知意 发表于 2023-12-13 10:58
问题我找到了,感谢您的回复,提早的上拉是因为我收发的那个函数判断标志位有问题,需要判断发送接收,而 ...
关于您提到官方提供的固件库,您方便分享官方库链接给我吗,我参考的官方库里面没有收发这些api,只是简单的示例。 楼主,您现在应该就使用的是官方的固件库在编写。
在ftp://download.nationstech.com 这个FTP里面,对应的型号文件夹里面的
类似 Nationstech.N32G45x_Library.2.1.0 这个文件夹 jobszheng 发表于 2023-12-13 13:52
楼主,您现在应该就使用的是官方的固件库在编写。
在ftp://download.nationstech.com 这个FTP里面,对应的 ...
是的,我这里的显示的版本是1.2.1 可能是硬件方面的问题 如果片选信号的拉高是由驱动或固件控制的,那么可能是驱动或固件中的某些设置或代码导致了这个问题。 调整示波器设置
页:
[1]