打印
[STM32F4]

STM32 SPI3总结

[复制链接]
2229|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dongnanxibei|  楼主 | 2016-8-24 18:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

硬件平台:

MCU: STM32F407

FLASH: AT25DF321A

端口:SPI3

先总结一下自己的经验,再贴代码。

1.不能粗心大意。

例如:while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);语句后有分号,刚开始时,没有注意,结构总是不能收到数据,总是在SPI_I2S_ReceiveData(SPI3);处循环等待。

2.了解原理

刚开始不懂为什么发送数据的时候,经常会发送0xff这个字节,后来了解原理之后才明白,发送这个字节是伪字节,目的是给从机(AT25DF321A)提供时钟。原理网上很多,这里就不贴了。

3.要仔细阅读flash文档

当执行完擦写命令,读出的数据应该是0xff,可总是是0x00,后来通过读状态寄存器发现,原来flash被锁保护,在进行阅读知道怎么去更改状态寄存器解除保护。


本程序是实现读flash的id和写一个字节到指定地址,测试flash是否可用。


沙发
dongnanxibei|  楼主 | 2016-8-24 18:29 | 只看该作者

以下是相关代码:

//pin
#define SPI_SCLK_PIN   GPIO_Pin_10
#define SPI_MISO_PIN   GPIO_Pin_11
#define SPI_MISI_PIN   GPIO_Pin_12
#define SPI_GPIO_PORT  GPIOC
#define SPI_GPIO_CS_PORT GPIOA
#define SPI_GPIO_CS_PIN  GPIO_Pin_15
#define SPI_CS_LOW() GPIO_ResetBits(SPI_GPIO_CS_PORT,SPI_GPIO_CS_PIN) //Chip Select pin set low
#define SPI_CS_HIGH() GPIO_SetBits(SPI_GPIO_CS_PORT,SPI_GPIO_CS_PIN)  //Chip Select pin set low

//command of AT25
#define CMD_AT25_READ_ID  0x9f
#define CMD_AT25_WRITE_ENABLE 0x06
#define CMD_AT25_PAGE_PROGRAME 0x02
#define CMD_AT25_READ_STATUSREGISTER 0x05
#define CMD_AT25_READ_ARRAY_1B 0x1b
#define CMD_AT25_READ_ARRAY_0B 0x0b
#define CMD_AT25_ERASE_4K 0x20
#define CMD_AT25_WRITE_STATUSREGISTER_BYTE1 0x01


/*******************************************************************************
* Description    : Configure SPI GPIO            
*******************************************************************************/
static void SPI_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
GPIO_StructInit(&GPIO_InitStructure);


GPIO_InitStructure.GPIO_Pin = SPI_SCLK_PIN | SPI_MISI_PIN | SPI_MISO_PIN;
GPIO_InitStructure.GPIO_Mode =   GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd =  GPIO_PuPd_UP;
GPIO_Init(SPI_GPIO_PORT,&GPIO_InitStructure);


GPIO_PinAFConfig(SPI_GPIO_PORT, GPIO_PinSource10, GPIO_AF_SPI3);
GPIO_PinAFConfig(SPI_GPIO_PORT, GPIO_PinSource11, GPIO_AF_SPI3);
GPIO_PinAFConfig(SPI_GPIO_PORT, GPIO_PinSource12, GPIO_AF_SPI3);


GPIO_InitStructure.GPIO_Pin = SPI_GPIO_CS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd =  GPIO_PuPd_NOPULL;


GPIO_Init(SPI_GPIO_CS_PORT,&GPIO_InitStructure);
}

/*******************************************************************************
* Description    : Configure SPI            
*******************************************************************************/
static void SPI_Configuration(void)
{
SPI_InitTypeDef SPI_InitStructure;


RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3,ENABLE);


SPI_Cmd(SPI3, DISABLE);


SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   
SPI_InitStructure.SPI_CRCPolynomial = 7;   


SPI_Init(SPI3, &SPI_InitStructure);
SPI_Cmd(SPI3, ENABLE);
}

/*******************************************************************************
* Description    : send data to AT25            
*******************************************************************************/
static uint16_t SPI_FLASH_SendByte(uint16_t byte)
{
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI3, byte);
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI3);
}

/*******************************************************************************
* Description    : Read id of AT25            
*******************************************************************************/
uint32_t Read_AT25_ID(void)
{


uint32_t at25_id = 0;


SPI_CS_LOW();


SPI_FLASH_SendByte(CMD_AT25_READ_ID);
at25_id = SPI_FLASH_SendByte(0xff);
at25_id = SPI_FLASH_SendByte(0xff);
at25_id = SPI_FLASH_SendByte(0xff);

SPI_CS_HIGH();


return at25_id;
}

/*******************************************************************************
* Description    : Write  Enable of AT25
*******************************************************************************/
static void SPI_FLASH_Write_Enable(void)
{
SPI_CS_LOW();


SPI_FLASH_SendByte(CMD_AT25_WRITE_ENABLE);


SPI_CS_HIGH();
}

/*******************************************************************************
* Description    : Write  Enable of AT25
*******************************************************************************/
static void SPI_FLASH_Page_Write(void)
{
SPI_FLASH_Write_Enable();
SPI_FLASH_WaitForWriteEnd();


SPI_CS_LOW();


SPI_FLASH_SendByte(CMD_AT25_PAGE_PROGRAME);
SPI_FLASH_SendByte(0x00);
SPI_FLASH_SendByte(0x01);
SPI_FLASH_SendByte(0x11);
SPI_FLASH_SendByte(0x1d);


SPI_CS_HIGH();
SPI_FLASH_WaitForWriteEnd();
}

/*******************************************************************************
* Description    : read the status register
*******************************************************************************/
static  void SPI_FLASH_WaitForWriteEnd(void)
{
uint8_t FLASH_Status = 0;


SPI_CS_LOW();
SPI_FLASH_SendByte(CMD_AT25_READ_STATUSREGISTER);


do
{
FLASH_Status = SPI_FLASH_SendByte(0xff);
}while(FLASH_Status &0x01 == 0x01);


SPI_CS_HIGH();
}


使用特权

评论回复
板凳
dongnanxibei|  楼主 | 2016-8-24 18:30 | 只看该作者
/*******************************************************************************
* Description    : Write Status Register Byte 1 to make All sectors are
                   software unprotected
*******************************************************************************/
static void SPI_FLASH_Write_StatusRegister1(void)
{
uint8_t FLASH_Status = 0;

SPI_FLASH_Write_Enable();
SPI_FLASH_WaitForWriteEnd();

SPI_CS_LOW();

SPI_FLASH_SendByte(CMD_AT25_WRITE_STATUSREGISTER_BYTE1);
SPI_FLASH_SendByte(0x00);//注意此处,要根据flash文档发送相应的数据


SPI_CS_HIGH();
}

/*******************************************************************************
* Description    : read data from flash
*******************************************************************************/
static void SPI_FLASH_Read_Array(void)
{
uint8_t data = 0;


SPI_CS_LOW();


SPI_FLASH_SendByte(CMD_AT25_READ_ARRAY_0B);
SPI_FLASH_SendByte(0x00);
SPI_FLASH_SendByte(0x01);
SPI_FLASH_SendByte(0x11);
SPI_FLASH_SendByte(0xff);
//SPI_FLASH_SendByte(0xff);
data = SPI_FLASH_SendByte(0xff);


SPI_CS_HIGH();
}

/*******************************************************************************
* Description    : erase block
*******************************************************************************/
static void SPI_FLASH_Erase_Block(void)
{
SPI_FLASH_Write_Enable();
    SPI_FLASH_WaitForWriteEnd();


SPI_CS_LOW();
SPI_FLASH_SendByte(CMD_AT25_ERASE_4K);
SPI_FLASH_SendByte(0x00);
SPI_FLASH_SendByte(0x00);
SPI_FLASH_SendByte(0x00);
SPI_CS_HIGH();


SPI_FLASH_WaitForWriteEnd();
}





使用特权

评论回复
地板
mmuuss586| | 2016-8-24 18:51 | 只看该作者
谢谢分享;

使用特权

评论回复
5
any012| | 2016-8-25 10:46 | 只看该作者
好奇为什么没有打开复用时钟?
我用的103,打开了复用始终,并且禁止了JTAG,反倒是SPI3无输出波形,不解。

使用特权

评论回复
6
icecut| | 2016-8-25 11:31 | 只看该作者
不错...进步很大.软件靠细节啊

使用特权

评论回复
7
dongnanxibei|  楼主 | 2016-8-25 12:03 | 只看该作者
多学习多练习,多读别人的程序,才好提高。

使用特权

评论回复
8
huangcunxiake| | 2016-8-25 20:09 | 只看该作者
实现读flash的id和写一个字节到指定地址

使用特权

评论回复
9
neeringstu| | 2016-8-25 21:04 | 只看该作者
spi的最快速率能够达到多少呢?

使用特权

评论回复
10
dongnanxibei|  楼主 | 2016-8-26 20:10 | 只看该作者
neeringstu 发表于 2016-8-25 21:04
spi的最快速率能够达到多少呢?

这个最快达到多少要看你选择的时钟大小了。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

200

主题

3544

帖子

16

粉丝