STM32 SPI3總結
最近學習STM32的SPI功能,經過一段時間的折騰,終於能寫入讀寫資料了。記錄一下。
硬體平臺:
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是否可用。
以下是相關程式碼:
//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();
}
/*******************************************************************************
* 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();
}