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