STM8L151 使用硬體SPI驅動W25Q16 Flash
阿新 • • 發佈:2019-01-10
SPI:有四根線的序列通訊協議,允許與其他裝置以半、全雙工、同步、序列方式通訊。
MISO:主模式輸入、從模式輸出線
MOSI:主模式輸出、從模式輸入線
CLK:時鐘線
NSS:從裝置選擇引腳,主裝置標準IO驅動,並用來區分從裝置
以STM8L 驅動SPI Flash W25Q16 為例說明記錄下,使用STM8L 的SPI該注意哪些地方,以及如何簡單驅動W25Q16。
華邦的W25Q16 SPI Flash晶片是採用SPI介面,至於該晶片的優缺點就不說了,STM8L上有一個硬體SPI,可以很方便的來驅動W25Q16,下面就來看看該如何配置STM8L的SPI 外設。
獲取裝置ID的指令傳送順序如上圖,第一位元組先發0x90,然後發兩個dummy Byte(任何數值都可)和0x00,之後再讀取廠商ID和裝置ID,上面的函式基本實現的就是這個時序。 實測的測試結果如下,
結果與手冊給的ID一致。
在上面中要注意SPI 使用到的管腳PB5, PB6, PB7 的設定,在SPI主機模式中, PB5、PB6根據外圍電路可以設定為外部上拉輸出,也可設定為上面的內部上拉輸出,而PB7則要設定為內部上拉輸入或浮空輸入(外加上拉電阻),這些設定完還要開啟SPI外設的時鐘。 其中W25Q16的SPI匯流排模式是Mode0 或Mode3 ,這個在手冊中或本文中下面的時序圖中可以看出,那麼對於SPI的初始化就要考慮了,當 SPI_Init中引數為SPI_CPOL_High, SPI_CPHA_2Edge表示Mode0,為SPI_CPOL_Low, SPI_CPHA_1Edge表示Mode3,如果為其他組合那麼就會導致通訊資料錯位不正確。 下面是讀取Flash 廠商ID和裝置ID的函式,void SPI_FLASH_Init(void) { //SPI_CLOCK:PB5, SPI_MOSI: PB6, SPI_MISO: PB7 GPIO_Init(GPIOB, GPIO_Pin_5, GPIO_Mode_Out_PP_High_Fast); GPIO_Init(GPIOB, GPIO_Pin_6, GPIO_Mode_Out_PP_High_Fast); //主機模式,配置為輸入 該設定很關鍵 GPIO_Init(GPIOB, GPIO_Pin_7, GPIO_Mode_In_PU_No_IT); /* 初始化SPI */ SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_4, SPI_Mode_Master,\ SPI_CPOL_High, SPI_CPHA_2Edge, \ SPI_Direction_2Lines_FullDuplex, SPI_NSS_Soft, 0x07); SPI_Cmd(SPI1, ENABLE); /* 使能SPI */ /* 配置CS管腳 */ GPIO_Init(SPI_CS , SPI_Pin_CS, GPIO_Mode_Out_PP_High_Fast); GPIO_WriteBit(SPI_CS, SPI_Pin_CS, SET); /* 拉高不使能外部SPI裝置 */ }
uint8_t SPI_FLASH_SendByte(u8 byte) { /* Loop while DR register in not emplty */ while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET); /* Send byte through the SPI1 peripheral */ SPI_SendData(SPI1, byte); /* Wait to receive a byte */ while (SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET); /* Return the byte read from the SPI bus */ return SPI_ReceiveData(SPI1); }
uint16_t SPI_FLASH_ReadID(void)
{
u16 Device_ID = 0;
/* Select the FLASH: Chip Select low */
SPI_FLASH_CS_LOW(); //拉低片選管腳電平,選中外設
/* Send "RDID " instruction */
SPI_FLASH_SendByte(0x90); //讀取裝置ID指令
SPI_FLASH_SendByte(0X00);
SPI_FLASH_SendByte(0X00);
SPI_FLASH_SendByte(0X00);
/* Read a byte from the FLASH */
Device_ID = (SPI_FLASH_SendByte(Dummy_Byte)<<8);
Device_ID |= SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_CS_HIGH();//拉高片選管腳電平,
return Device_ID;
}
在W25Q16的手冊中,
函式讀回來的資料應該是上面的值,再看看手冊上的ID讀取指令0x90
獲取裝置ID的指令傳送順序如上圖,第一位元組先發0x90,然後發兩個dummy Byte(任何數值都可)和0x00,之後再讀取廠商ID和裝置ID,上面的函式基本實現的就是這個時序。 實測的測試結果如下,
結果與手冊給的ID一致。