小学生
最后登录1970-1-1
在线时间 小时
注册时间2017-10-31
|
本帖最后由 brave_hui 于 2020-10-28 15:11 编辑
我跟着教程写单片机读取的FLASHW25Q128值都是0x0,找了两天也没找出问题,用原教程的代码下载到单片机后也是0x0
麻烦大家给看看。硬件使用SPI3端口,CS软件模拟,读取FLASH的ID结果是0x0,擦除0扇区后去读的结果也是0x0,怎么都没找到是哪里出了问题
头文件:
#ifndef _W25Q128_H
#define _W25Q128_H
#include "stm32f10x.h"
#include <stdio.h>
/*SPI 参数定义****************************/
#define FLASH_SPIx SPI3 //使用SPI3端口
#define FLASH_SPI_APBxClock_FUN RCC_APB1PeriphClockCmd //开启SPI时钟函数封装成宏-使能SPI1时钟 配置SPI时钟
#define FLASH_SPI_CLK RCC_APB1Periph_SPI3 //SPI时钟开启函数的输入参数 ↑
#define FLASH_SPI_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd //开启GPIO时钟函数封装成宏-使能GPIO时钟 配置GPIO时钟
#define FLASH_SPI_GPIO_CLK (RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOB) //开启GPIO时钟函数的输入参数 ↑
#define FLASH_SPI_CS_PORT GPIOD
#define FLASH_SPI_CS_PIN GPIO_Pin_2
//SCK 引脚
#define FLASH_SPI_SCK_PORT GPIOB
#define FLASH_SPI_SCK_PIN GPIO_Pin_3
//MISO 引脚
#define FLASH_SPI_MISO_PORT GPIOB
#define FLASH_SPI_MISO_PIN GPIO_Pin_4
//MOSI 引脚
#define FLASH_SPI_MOSI_PORT GPIOB
#define FLASH_SPI_MOSI_PIN GPIO_Pin_5
#define FLASH_SPI_CS_LOW GPIO_ResetBits( FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN )
#define FLASH_SPI_CS_HIGH GPIO_SetBits( FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN )
/*等待超时时间*/
#define SPIT_FLAG_TIMEOUT ((uint32_t)0x1000)
#define SPIT_LONG_TIMEOUT ((uint32_t)(10 * SPIT_FLAG_TIMEOUT))
#define DUMMY 0x00
#define Dummy 0x00
#define READ_JEDEC_ID 0x9f
#define ERASE_SECTOR 0x20
#define READ_STATUS 0x05
#define READ_DATA 0x03
/*信息输出*/
#define FLASH_DEBUG_ON 1
#define FLASH_INFO(fmt,arg...) printf("<<-FLASH-INFO->> "fmt"\n",##arg)
#define FLASH_ERROR(fmt,arg...) printf("<<-FLASH-ERROR->> "fmt"\n",##arg)
#define FLASH_DEBUG(fmt,arg...) do{\
if(FLASH_DEBUG_ON)\
printf("<<-FLASH-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\
}while(0)
void SPI_FLASH_Init(void);
uint8_t SPI_FLASH_Read_Byte(void);
uint32_t SPI_Read_ID(void);
void SPI_Write_Enable(void);
void SPI_waitForwriteEnd(void);
void SPI_Read_Data(uint32_t addr,uint8_t *readbuff,uint32_t numByteToRead);
void SPI_Erase_Sector(uint32_t addr);
#endif
c文件
#include "./w25q128/w25q128.h"
//4Kbytes为一个Sector
//16个扇区为1个Block
//W25Q128
//容量为16M字节,共有256个Block,4096个Sector
//GPIO 初始化
static __IO uint32_t SPITimeout = SPIT_LONG_TIMEOUT;
static uint32_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);
void SPI_FLASH_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct;
RCC_APB1PeriphClockCmd (RCC_APB1Periph_SPI3,ENABLE); //打开SPI功能时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD , ENABLE); //打开GPIO引脚时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);
/*-------1.初始化SPI GPIO引脚-------*/
//CS,普通GPIO,软件配置
GPIO_InitStruct.GPIO_Pin = FLASH_SPI_CS_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //CS 使用软件配置,配置成普通推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(FLASH_SPI_CS_PORT , &GPIO_InitStruct);
//SCK
GPIO_InitStruct.GPIO_Pin = FLASH_SPI_SCK_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
//MISO
GPIO_InitStruct.GPIO_Pin = FLASH_SPI_MISO_PIN ;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(FLASH_SPI_MISO_PORT, &GPIO_InitStruct);
//MOSI
GPIO_InitStruct.GPIO_Pin = FLASH_SPI_MOSI_PIN ;
GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStruct);
//FLASH停止信号:CS为高电平时停止
FLASH_SPI_CS_HIGH;
/*-------2.配置SPI功能模式-------*/
// FLASH芯片 支持SPI模式0及模式3,配置SPI0模式为模式3:CPOL 1 CPHA 1
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitStruct.SPI_CRCPolynomial = 7 ; //不实用CRC功能,数值随便写
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//配置SPI为双线全双工
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; //NSS软件配置
SPI_Init (SPI3,&SPI_InitStruct); //写入配置到寄存器
SPI_Cmd(SPI3 , ENABLE); //使能SPI
}
/*--------------------向存储器发送一个字节数据-------------------*/
/*1.检测并等待TXE为1(发送缓冲区为空)
2.发送一个字节
3.检测检测并等待RXNE为1(接收缓冲区为空),
因为SPI是同步通信,只有发送数据的时候才产生SCK时钟,当接收缓冲区为空,发送缓冲区也为空(参考通讯时序图)
*/
uint8_t SPI_FLASH_SendByte(uint8_t data)
{
SPITimeout = SPIT_FLAG_TIMEOUT;
while (SPI_I2S_GetFlagStatus( SPI3, SPI_I2S_FLAG_TXE)==RESET) //当TXE=0,TX缓冲区非空,执行if减减
// TXE=1,TX缓冲区空
{if((SPITimeout--)==0) return SPI_TIMEOUT_UserCallback(1);}
SPI_I2S_SendData(SPI3, data); //1-程序执行到这里,说明TX缓冲区为空.2-写入数据寄存器,把要写入的数据写入发送缓冲区向,
while (SPI_I2S_GetFlagStatus( SPI3, SPI_I2S_FLAG_RXNE)==RESET) //当RXNE=0,RX缓冲区空,当RXNE为1说明说句发送完成
//RXNE=1,RX缓冲区非空
{if((SPITimeout--)==0) return SPI_TIMEOUT_UserCallback(0);}
return SPI_I2S_ReceiveData(SPI3); //当RXNE=1,非空时,程序执行到这里,说明数据发送完成,并且接到一个字节
}
uint8_t SPI_FLASH_Read_Byte(void)
{
return SPI_FLASH_SendByte(Dummy);
}
/*---------------------------读取FLASH的ID--------------------------*/
uint32_t SPI_Read_ID(void)
{
uint32_t flash_id;
//片选使能
FLASH_SPI_CS_LOW;
SPI_FLASH_SendByte(READ_JEDEC_ID);
flash_id = SPI_FLASH_SendByte(DUMMY);
flash_id <<= 8;
flash_id |= SPI_FLASH_SendByte(DUMMY);
flash_id <<= 8;
flash_id |= SPI_FLASH_SendByte(DUMMY);
FLASH_SPI_CS_HIGH;
return flash_id;
}
//FLASH写入使能
void SPI_Write_Enable(void)
{
//片选使能
FLASH_SPI_CS_LOW;
SPI_FLASH_SendByte(0x06);
FLASH_SPI_CS_HIGH;
}
/*---------------------------擦除FLASH指定的4K扇区,代码20H--------------------------*/
void SPI_Erase_Sector(uint32_t addr)
{
//片选使能
FLASH_SPI_CS_LOW;
SPI_FLASH_SendByte(ERASE_SECTOR);
SPI_FLASH_SendByte((addr>>16)&0xff);
SPI_FLASH_SendByte((addr>>8)&0xff);
SPI_FLASH_SendByte(addr&0xff);
FLASH_SPI_CS_HIGH;
SPI_waitForwriteEnd();
}
/*---------------------等待FLASH内部时序操作完成,检测BUSY位状态-------------------*/
void SPI_waitForwriteEnd(void)
{
uint8_t status_reg = 0;
FLASH_SPI_CS_LOW;
SPI_FLASH_SendByte(READ_STATUS); //读取状态寄存器1的BUSY位,1为忙碌 0为操作完成,空闲
do
{
status_reg = SPI_FLASH_SendByte(Dummy);
}
while ((status_reg&0x01)==1);
FLASH_SPI_CS_HIGH;
}
/*---------------------------读取FLASH的内容--------------------------*/
//addr:读取flash地址 readbuff:读取的内容存储到buff中 numByteToRead ;读取的数量
void SPI_Read_Data(uint32_t addr,uint8_t *readbuff,uint32_t numByteToRead)
{
//片选使能
FLASH_SPI_CS_LOW;
SPI_FLASH_SendByte(ERASE_SECTOR);
SPI_FLASH_SendByte((addr>>16)&0xff);
SPI_FLASH_SendByte((addr>>8)&0xff);
SPI_FLASH_SendByte(addr&0xff);
while(numByteToRead--)
{
*readbuff = SPI_FLASH_SendByte(Dummy);
readbuff++;
}
FLASH_SPI_CS_HIGH;
SPI_waitForwriteEnd();
}
/*---------------------------写入FLASH指定的扇区--------------------------*/
//static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
//{
// /* 等待超时后的处理,输出错误信息 */
// FLASH_ERROR("SPI 等待超时!errorCode = %d",errorCode);
// return 0;
//}
//static __IO uint32_t SPITimeout = SPIT_LONG_TIMEOUT;
//static uint32_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);
static uint32_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{
/* 等待超时后的处理,输出错误信息 */
FLASH_ERROR("SPI 等待超时!errorCode = %d",errorCode);
return 0;
}
main.c
#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h>
#include "rccclkconfig.h"
#include "bsp_led.h"
#include "key.h"
#include "exti.h"
#include "systick.h"
#include "usart.h"
//#include "dma_mtom.h"
//#include "dma_mtop.h"
#include "i2c.h"
#include "./w25q128/w25q128.h"
#include <string.h>
void Delay( uint32_t count )
{
for(; count!=0; count--);
}
uint8_t buff[4096];
int main(void)
{
uint32_t id = 0x00;
HSI_SetSysClk( RCC_PLLMul_16); //配置系统时钟为HSI:8/2*16=64M
LED_GPIO_Config();
LED_G(ON);
Delay(1000);
USART_Config();
SPI_FLASH_Init();
printf("\r\n this is a SPI3 \r\n");
SPI_Write_Enable();
id = SPI_Read_ID();
printf("\r\n id is 0x%x \r\n",id);
while(1)
{
LEDR_TOGGLE;
Delay(0xFFFFF);
}
}
|
-
|