1:调试板载的存储芯片W25Q64芯片
实物图片如下:
1.1 SPI 介绍:
SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select)。
SPI通信具有以下特点:
- 同步,全双工;
- 支持总线挂载多设备(SPI仅支持一主多从);
- 在不同情况下,通信线的名称可能有所变化:
SCK:SCLK、CLK、CK;
MOSI:DI(对从机而言);
MISO:DO(对从机而言);
SS:CS(Chip Select)、NSS(Not Slave Select); - SPI通信的SS线可以有多条,即对每一个从机而言都有单独的从机选择线,一般为低电平有效。
1.2 硬件连接
- 所有SPI设备的SCK、MOSI、MISO分别连在一起
- 主机另外引出多条SS控制线,分别接到各从机的SS引脚,同一时间,主机只能选择一条SS线为低电平
- 输出引脚配置为推挽输出(推挽输出能使SPI的通信速度轻松达到MHz的级别),输入引脚配置为浮空或上拉输入。当从机未被SS线选中时,从机的输出引脚MISO必须呈现高阻态,以防止数据冲突
2:硬件连接方式:
由于CW32F003开发板没有将SPI通讯线连接起来,仅仅是将芯片的引脚引出,这样做有一个好处是我们可以任意的切换SPI的引脚,或者是选择其他的引脚,只是外部在调试的时候需用杜邦线连接起来就可以,只是杜邦线有时候会出现松动的情况,不利于我们查找软件问题或者是硬件问题。
这是我们使用的是 SPI1,W25Q64的引脚如下;
SPI_NCS ←----→ PB2
SPI_MISO ←----→ PA4
SPI_MOSI ←----→ PA1
SPI_CLK ←----→ PA0
我们利用串口1,将测试数据打印到串口接收工具,接线如下:
同样我们需要利用杜邦线接线连接到一起,由于我使用的是串口供电,不知道为什么J5接线端子,并没有电压,导致在我调试的过程中CH340芯片并没有工作,我还以为是代码的问题,找了半天才去测试电压,原来供电都不正常,将3.3V接入,就正常了。
3:主要代码如下:
/**
* @brief 配置SPI FLASH
*
*/
void SPI_FLASH_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/************************GPIO Configuration***********************/
RCC_AHBPeriphClk_Enable(FLASH_SPI_SCK_GPIO_CLK | FLASH_SPI_MISO_GPIO_CLK | FLASH_SPI_MOSI_GPIO_CLK | FLASH_SPI_CS_GPIO_CLK, ENABLE);
RCC_APBPeriphClk_Enable2(RCC_APB2_PERIPH_SPI, ENABLE);
//SPI SCK MOSI MISO 复用
FLASH_SPI_AF_SCK;
FLASH_SPI_AF_MISO;
FLASH_SPI_AF_MOSI;
//CS
GPIO_InitStructure.Pins = FLASH_SPI_CS_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure);
//SCK
GPIO_InitStructure.Pins = FLASH_SPI_SCK_GPIO_PIN;
GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
//MOSI
GPIO_InitStructure.Pins = FLASH_SPI_MOSI_GPIO_PIN;
GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
//MISO
GPIO_InitStructure.Pins = FLASH_SPI_MISO_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
//拉高CS
FLASH_SPI_CS_HIGH();
/************************SPI Configuration***********************/
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 双线全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 帧数据长度为8bit
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 时钟空闲电平为高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 第二个边沿采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 片选信号由SSI寄存器控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; // 波特率为PCLK的8分频
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 最高有效位 MSB 收发在前
SPI_InitStructure.SPI_Speed = SPI_Speed_Low; // 低速SPI
SPI_Init(&SPI_InitStructure);
SPI_Cmd(ENABLE);
}
void UART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = DEBUG_USART_BaudRate;
USART_InitStructure.USART_Over = USART_Over_16;
USART_InitStructure.USART_Source = USART_Source_PCLK;
USART_InitStructure.USART_UclkFreq = DEBUG_USART_UclkFreq;
USART_InitStructure.USART_StartBit = USART_StartBit_FE;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(DEBUG_USARTx, &USART_InitStructure);
}
if(JedecID == sJedecID)
{
printf("\r\n\nFLASH Detected\r\n");;
//擦除扇区 4KB
SPI_FLASH_SectorErase(FLASH_SectorToEraseAddress);
//写数据
SPI_FLASH_BufferWrite(TxBuffer, FLASH_WriteAddress, BufferSize);
printf("写入的数据为:%s\r\n", TxBuffer);
//读数据
SPI_FLASH_BufferRead(RxBuffer, FLASH_ReadAddress, BufferSize);
printf("读出的数据为:%s\r\n", RxBuffer);
//检查写入的数据与读出的数据是否一致
TransferStatus = Buffercmp(TxBuffer, RxBuffer, BufferSize);
//擦除扇区 4KB
SPI_FLASH_SectorErase(FLASH_SectorToEraseAddress);
//读数据
SPI_FLASH_BufferRead(RxBuffer, FLASH_ReadAddress, BufferSize);
if(TransferStatus == PASSED)
{
LED1.LED_On(&LED1);
printf("\r\nFLASH Success\r\n");
}
else
{
LED2.LED_On(&LED2);
printf("\r\nFLASH Error 1\r\n");
}
for(uint8_t j = 0; j < BufferSize; j++)
{
if(RxBuffer[j] != 0xFF)
{
LED2.LED_On(&LED2);
printf("\r\nFLASH Error 2\r\n");
}
}
}
else// (FlashID != sFLASH_ID)
{
LED2.LED_On(&LED2);
printf("\r\nFLASH Error 3\r\n");
}
while(1)
{
}
}
串口接收到的数据,由于使用的是杜邦线,偶尔出现SPI通讯异常的情况。。。。。。。。。
全部评论