HAL库 STM32驱动W25QXX驱动例程
📍驱动程序参考:《STM32CubeMX | 基于STM32使用HAL库W25Q128驱动程序》 🔑 驱动方式:硬件SPI方式和SPI DMA方式。 🔖适用于:W25X系列/Q系列芯片:W25Q80、W25Q16、W25Q32、 W25Q64、 W25Q128、 📌W25Q256可以参考《stm32 W25QXX系列驱动 W25Q80 W25Q16 W25Q32 W25Q64 W25Q128 W25Q256》
📘相关应用篇内容《STM32 STD/HAL库驱动W25Q64模块读写字库数据+OLED0.96显示例程》 🍁W25Q64原理图:
🔨spi方式配置
🛠SPI DMA配置
🌿自定义CS引脚:
🔰SPI方式和SPI DMA方式软件驱动代码不同之处
static uint8_t W25QXX_SPI_ReadWriteByte ( uint8_t TxData)
{
uint8_t RxData = 0X00 ;
if ( HAL_SPI_TransmitReceive_DMA ( W25QXX_SPI_Handle, & TxData, & RxData, 1 ) != HAL_OK) {
RxData = 0XFF ;
}
return RxData;
}
W25QXX驱动代码
# ifndef __W25QXX_H
# define __W25QXX_H
# include <main.h>
# define W25QXX_SPI_Handle ( & hspi2)
# define W25Q80 0XEF13
# define W25Q16 0XEF14
# define W25Q32 0XEF15
# define W25Q64 0XEF16
# define W25Q128 0XEF17
# define W25QXX_CS_L ( ) HAL_GPIO_WritePin ( W25QXX_CS_GPIO_Port, W25QXX_CS_Pin, GPIO_PIN_RESET)
# define W25QXX_CS_H ( ) HAL_GPIO_WritePin ( W25QXX_CS_GPIO_Port, W25QXX_CS_Pin, GPIO_PIN_SET)
extern uint16_t W25QXX_TYPE;
extern uint32_t W25QXX_SIZE;
extern uint8_t W25QXX_UID[ 8 ] ;
# define W25X_WriteEnable 0x06
# define W25X_WriteDisable 0x04
# define W25X_ReadStatusReg 0x05
# define W25X_WriteStatusReg 0x01
# define W25X_ReadData 0x03
# define W25X_FastReadData 0x0B
# define W25X_FastReadDual 0x3B
# define W25X_PageProgram 0x02
# define W25X_BlockErase 0xD8
# define W25X_SectorErase 0x20
# define W25X_ChipErase 0xC7
# define W25X_PowerDown 0xB9
# define W25X_ReleasePowerDown 0xAB
# define W25X_DeviceID 0xAB
# define W25X_ManufactDeviceID 0x90
# define W25X_JedecDeviceID 0x9F
int W25QXX_Init ( void ) ;
void W25QXX_ReadUniqueID ( uint8_t UID[ 8 ] ) ;
uint16_t W25QXX_ReadID ( void ) ;
uint8_t W25QXX_ReadSR ( void ) ;
void W25QXX_Write_SR ( uint8_t sr) ;
void W25QXX_Write_Enable ( void ) ;
void W25QXX_Write_Disable ( void ) ;
void W25QXX_Write_NoCheck ( uint8_t * pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) ;
void W25QXX_Read ( uint8_t * pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) ;
void W25QXX_Write ( uint8_t * pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) ;
void W25QXX_Erase_Chip ( void ) ;
void W25QXX_Erase_Sector ( uint32_t Dst_Addr) ;
void W25QXX_Wait_Busy ( void ) ;
void W25QXX_PowerDown ( void ) ;
void W25QXX_WAKEUP ( void ) ;
uint32_t W25QXX_ReadCapacity ( void ) ;
# endif
# include "W25QXX.h"
# include "spi.h"
uint16_t W25QXX_TYPE = 0 ;
uint32_t W25QXX_SIZE = 0 ;
uint8_t W25QXX_UID[ 8 ] ;
static void delay_us ( uint32_t us)
{
uint32_t delay = ( HAL_RCC_GetHCLKFreq ( ) / 4000000 * us) ;
while ( delay-- ) {
;
}
}
static uint8_t W25QXX_SPI_ReadWriteByte ( uint8_t TxData)
{
uint8_t RxData = 0X00 ;
if ( HAL_SPI_TransmitReceive_DMA ( W25QXX_SPI_Handle, & TxData, & RxData, 1 ) != HAL_OK) {
RxData = 0XFF ;
}
return RxData;
}
int W25QXX_Init ( void )
{
MX_SPI2_Init ( ) ;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( 0XFF ) ;
W25QXX_CS_H ( ) ;
W25QXX_TYPE = W25QXX_ReadID ( ) ;
W25QXX_SIZE = W25QXX_ReadCapacity ( ) ;
W25QXX_ReadUniqueID ( W25QXX_UID) ;
if ( ( W25QXX_TYPE & 0XEF00 ) != 0XEF00 ) {
return - 1 ;
}
return 0 ;
}
uint8_t W25QXX_ReadSR ( void )
{
uint8_t byte = 0 ;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_ReadStatusReg) ;
byte = W25QXX_SPI_ReadWriteByte ( 0Xff ) ;
W25QXX_CS_H ( ) ;
return byte;
}
void W25QXX_Write_SR ( uint8_t sr)
{
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_WriteStatusReg) ;
W25QXX_SPI_ReadWriteByte ( sr) ;
W25QXX_CS_H ( ) ;
}
void W25QXX_Write_Enable ( void )
{
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_WriteEnable) ;
W25QXX_CS_H ( ) ;
}
void W25QXX_Write_Disable ( void )
{
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_WriteDisable) ;
W25QXX_CS_H ( ) ;
}
uint16_t W25QXX_ReadID ( void )
{
uint16_t Temp = 0 ;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( 0x90 ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
Temp |= W25QXX_SPI_ReadWriteByte ( 0xFF ) << 8 ;
Temp |= W25QXX_SPI_ReadWriteByte ( 0xFF ) ;
W25QXX_CS_H ( ) ;
return Temp;
}
uint32_t W25QXX_ReadCapacity ( void )
{
int i = 0 ;
uint8_t arr[ 4 ] = { 0 , 0 , 0 , 0 } ;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( 0x5A ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
W25QXX_SPI_ReadWriteByte ( 0x84 ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
for ( i = 0 ; i < sizeof ( arr) ; i++ ) {
arr[ i] = W25QXX_SPI_ReadWriteByte ( 0xFF ) ;
}
W25QXX_CS_H ( ) ;
return ( ( ( ( * ( uint32_t * ) arr) ) + 1 ) >> 3 ) ;
}
void W25QXX_ReadUniqueID ( uint8_t UID[ 8 ] )
{
int i = 0 ;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( 0x4B ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
W25QXX_SPI_ReadWriteByte ( 0x00 ) ;
for ( i = 0 ; i < 8 ; i++ ) {
UID[ i] = W25QXX_SPI_ReadWriteByte ( 0xFF ) ;
}
W25QXX_CS_H ( ) ;
}
void W25QXX_Read ( uint8_t * pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
uint16_t i;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_ReadData) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) ( ( ReadAddr) >> 16 ) ) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) ( ( ReadAddr) >> 8 ) ) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) ReadAddr) ;
for ( i = 0 ; i < NumByteToRead; i++ ) {
pBuffer[ i] = W25QXX_SPI_ReadWriteByte ( 0XFF ) ;
}
W25QXX_CS_H ( ) ;
}
void W25QXX_Write_Page ( uint8_t * pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint16_t i;
W25QXX_Write_Enable ( ) ;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_PageProgram) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) ( ( WriteAddr) >> 16 ) ) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) ( ( WriteAddr) >> 8 ) ) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) WriteAddr) ;
for ( i = 0 ; i < NumByteToWrite; i++ )
W25QXX_SPI_ReadWriteByte ( pBuffer[ i] ) ;
W25QXX_CS_H ( ) ;
W25QXX_Wait_Busy ( ) ;
}
void W25QXX_Write_NoCheck ( uint8_t * pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint16_t pageremain;
pageremain = 256 - WriteAddr % 256 ;
if ( NumByteToWrite <= pageremain)
pageremain = NumByteToWrite;
while ( 1 ) {
W25QXX_Write_Page ( pBuffer, WriteAddr, pageremain) ;
if ( NumByteToWrite == pageremain)
break ;
else {
pBuffer += pageremain;
WriteAddr += pageremain;
NumByteToWrite -= pageremain;
if ( NumByteToWrite > 256 )
pageremain = 256 ;
else
pageremain = NumByteToWrite;
}
} ;
}
uint8_t W25QXX_BUFFER[ 4096 ] ;
void W25QXX_Write ( uint8_t * pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint32_t secpos;
uint16_t secoff;
uint16_t secremain;
uint16_t i;
uint8_t * W25QXX_BUF;
W25QXX_BUF = W25QXX_BUFFER;
secpos = WriteAddr / 4096 ;
secoff = WriteAddr % 4096 ;
secremain = 4096 - secoff;
if ( NumByteToWrite <= secremain)
secremain = NumByteToWrite;
while ( 1 ) {
W25QXX_Read ( W25QXX_BUF, secpos * 4096 , 4096 ) ;
for ( i = 0 ; i < secremain; i++ ) {
if ( W25QXX_BUF[ secoff + i] != 0XFF )
break ;
}
if ( i < secremain) {
W25QXX_Erase_Sector ( secpos) ;
for ( i = 0 ; i < secremain; i++ ) {
W25QXX_BUF[ i + secoff] = pBuffer[ i] ;
}
W25QXX_Write_NoCheck ( W25QXX_BUF, secpos * 4096 , 4096 ) ;
} else
W25QXX_Write_NoCheck ( pBuffer, WriteAddr, secremain) ;
if ( NumByteToWrite == secremain)
break ;
else {
secpos++ ;
secoff = 0 ;
pBuffer += secremain;
WriteAddr += secremain;
NumByteToWrite -= secremain;
if ( NumByteToWrite > 4096 )
secremain = 4096 ;
else
secremain = NumByteToWrite;
}
} ;
}
void W25QXX_Erase_Chip ( void )
{
W25QXX_Write_Enable ( ) ;
W25QXX_Wait_Busy ( ) ;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_ChipErase) ;
W25QXX_CS_H ( ) ;
W25QXX_Wait_Busy ( ) ;
}
void W25QXX_Erase_Sector ( uint32_t Dst_Addr)
{
Dst_Addr *= 4096 ;
W25QXX_Write_Enable ( ) ;
W25QXX_Wait_Busy ( ) ;
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_SectorErase) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) ( ( Dst_Addr) >> 16 ) ) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) ( ( Dst_Addr) >> 8 ) ) ;
W25QXX_SPI_ReadWriteByte ( ( uint8_t ) Dst_Addr) ;
W25QXX_CS_H ( ) ;
W25QXX_Wait_Busy ( ) ;
}
void W25QXX_Wait_Busy ( void )
{
while ( ( W25QXX_ReadSR ( ) & 0x01 ) == 0x01 ) ;
}
void W25QXX_PowerDown ( void )
{
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_PowerDown) ;
W25QXX_CS_H ( ) ;
delay_us ( 3 ) ;
}
void W25QXX_WAKEUP ( void )
{
W25QXX_CS_L ( ) ;
W25QXX_SPI_ReadWriteByte ( W25X_ReleasePowerDown) ;
W25QXX_CS_H ( ) ;
delay_us ( 3 ) ;
}
int main ( void )
{
uint32_t USART_TIMER ;
HAL_Init ( ) ;
SystemClock_Config ( ) ;
MX_GPIO_Init ( ) ;
MX_DMA_Init ( ) ;
MX_SPI2_Init ( ) ;
MX_USART1_UART_Init ( ) ;
USART_TIMER = HAL_GetTick ( ) ;
printf ( "SYSCLOCK:%d\r\n" , HAL_RCC_GetSysClockFreq ( ) ) ;
W25QXX_Init ( ) ;
printf ( "FLASH ID=%X\r\n" , W25QXX_ReadID ( ) ) ;
HAL_Delay ( 1000 ) ;
while ( 1 ) {
if ( HAL_GetTick ( ) - USART_TIMER > 1000 ) {
USART_TIMER = HAL_GetTick ( ) ;
HAL_GPIO_TogglePin ( LED1_GPIO_Port, LED1_Pin) ;
printf ( "FLASH ID=%X HCLKFreq:%d\r\n" , W25QXX_ReadID ( ) , ( uint32_t ) HAL_RCC_GetHCLKFreq ( ) ) ;
}
}
}
串口打印:
📚程序源码
链接:https:
提取码:ilml
链接:https:
提取码:ircb