AT45DB161D.c文件內容
#include "AT45DB161D.h" /* 作者: 畢小樂 日期:2018-09-21 版本:V1.00 簡介: 1.實現AT45DB161D主內存的連續讀、寫、整片擦除操作,可以像使用EEPROM一樣使用AT45DB161D FLASH存儲器。 2.使用模擬SPI模式(模式0),方便移植到其他平台。 3.移植簡單,只需要修改H文件的管腳對應關系即可,無需修改C文件。 */ void AT45DB161D_Init_Pin(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(AT45DB161D_CS_CLK | AT45DB161D_CLK_CLK | AT45DB161D_MOSI_CLK | AT45DB161D_MISO_CLK, ENABLE); /* CS CLK MOSI in output pushpull mode */ GPIO_InitStructure.GPIO_Pin = AT45DB161D_CS_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(AT45DB161D_CS_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = AT45DB161D_CLK_PIN; GPIO_Init(AT45DB161D_CLK_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = AT45DB161D_MOSI_PIN; GPIO_Init(AT45DB161D_MOSI_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = AT45DB161D_MISO_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(AT45DB161D_MISO_PORT, &GPIO_InitStructure); AT45DB161D_CS_HIGH; } static void AT45DB161D_Delay_uS(int tick) { int i; while(tick>0) { tick--; for(i=0;i<10;i++) __nop(); } } char AT45DB161D_SendByte(char Dat) { int i; char receive=0; AT45DB161D_CS_LOW; for(i=0;i<8;i++) { AT45DB161D_CLK_LOW; AT45DB161D_Delay_uS(5); if((Dat<<i)&0x80) { AT45DB161D_MOSI_HIGH; } else { AT45DB161D_MOSI_LOW; } AT45DB161D_Delay_uS(1); AT45DB161D_CLK_HIGH; AT45DB161D_Delay_uS(1); if(AT45DB161D_MISO) { receive |= 0x01<<(7-i); } else { receive |= 0x00<<(7-i); } AT45DB161D_Delay_uS(4); } AT45DB161D_CLK_LOW; AT45DB161D_Delay_uS(10); // AT45DB161D_CS_HIGH; return receive; } //0BH(操作碼)+3Byte (地址)+1Byte(dummy)+n個SCK時鍾+ CS電平跳變(從低到高) void AT45DB161D_Read(unsigned int Add,char* buf,unsigned int Len) { char Add_Buf[3],i; int Page_Add,Buffer_Add,Add_Value; AT45DB161D_CS_LOW; AT45DB161D_SendByte(0x0B); Page_Add = (Add / 528) << 10; Buffer_Add = Add % 528; Add_Value = Page_Add | Buffer_Add; Add_Buf[0] = (char)((Add_Value & 0x3FFFFF)>>16); Add_Buf[1] = (char)((Add_Value & 0x3FFFFF)>>8); Add_Buf[2] = (char)((Add_Value & 0x3FFFFF)>>0); for(i=0;i<3;i++) { AT45DB161D_SendByte(Add_Buf[i]); } AT45DB161D_SendByte(0x00); while(Len--) { *buf++ = AT45DB161D_SendByte(0x00); } AT45DB161D_CS_HIGH; AT45DB161D_Delay_uS(10); return; } //D4H或D1H(操作碼 緩沖區1)+3Byte (地址)+1Byte(don’t care)+n個SCK時鍾+ CS電平跳變(從低到高) void Read_Buffer(unsigned int Add,char* buf,unsigned int Len) { char Add_Buf[3],i; AT45DB161D_CS_LOW; AT45DB161D_SendByte(0xD1); Add_Buf[0] = (char)((Add & 0x03FF)>>16); Add_Buf[1] = (char)((Add & 0x03FF)>>8); Add_Buf[2] = (char)((Add & 0x03FF)>>0); for(i=0;i<3;i++) { AT45DB161D_SendByte(Add_Buf[i]); } AT45DB161D_SendByte(0x00); while(Len--) { *buf++ = AT45DB161D_SendByte(0x00); } AT45DB161D_CS_HIGH; AT45DB161D_Delay_uS(10); return; } //84H(操作碼 緩沖區1)+3Byte(地址)+要發送的數據 void Write_Buffer(unsigned int Add,char* buf,unsigned int Len) { char Add_Buf[3],i; AT45DB161D_CS_LOW; AT45DB161D_SendByte(0x84); Add_Buf[0] = (char)((Add & 0x03FF)>>16); Add_Buf[1] = (char)((Add & 0x03FF)>>8); Add_Buf[2] = (char)((Add & 0x03FF)>>0); for(i=0;i<3;i++) { AT45DB161D_SendByte(Add_Buf[i]); } while(Len--) { AT45DB161D_SendByte(*buf++); } AT45DB161D_CS_HIGH; AT45DB161D_Delay_uS(10); return; } //D7H(操作碼)+1Byte(狀態字節) char Read_Status_Register(void) { char Status; AT45DB161D_CS_LOW; AT45DB161D_SendByte(0xD7); Status = AT45DB161D_SendByte(0x00); AT45DB161D_CS_HIGH; AT45DB161D_Delay_uS(10); return Status; } void Page_To_Buffer(unsigned int Add) { char Add_Buf[3],i; char Status; AT45DB161D_CS_LOW; AT45DB161D_SendByte(0x53); Add = (Add/528)<<10; Add_Buf[0] = (char)((Add & 0x3FFC00)>>16); Add_Buf[1] = (char)((Add & 0x3FFC00)>>8); Add_Buf[2] = (char)((Add & 0x3FFC00)>>0); for(i=0;i<3;i++) { AT45DB161D_SendByte(Add_Buf[i]); } AT45DB161D_CS_HIGH; AT45DB161D_Delay_uS(10); Status = (Read_Status_Register() & 0x80)>>7; while(Status == 0x00) { Status = (Read_Status_Register() & 0x80)>>7; } return; } /* Add:寫緩沖區開始地址 buf:待寫入數據的指針 Len:待寫入數據的長度,不能大小當前地址能夠寫入的最大字節數 通過緩沖區寫主內存(相當於寫緩沖區命令+緩沖區到主內存頁編程使用內建擦除命令) 82H(操作碼 緩沖區1)+3Byte(地址)+N Byte(數據)+CS電平跳變(從低到高) */ void Buffer_To_Page(unsigned int Add,char* buf,unsigned int Len) { char Add_Buf[3],i; char Status; int Page_Add,Buffer_Add,Add_Value; AT45DB161D_CS_LOW; AT45DB161D_SendByte(0x82); Page_Add = (Add / 528) << 10; Buffer_Add = Add % 528; Add_Value = Page_Add | Buffer_Add; Add_Buf[0] = (char)((Add_Value & 0x3FFFFF)>>16); Add_Buf[1] = (char)((Add_Value & 0x3FFFFF)>>8); Add_Buf[2] = (char)((Add_Value & 0x3FFFFF)>>0); for(i=0;i<3;i++) { AT45DB161D_SendByte(Add_Buf[i]); } while(Len--) { AT45DB161D_SendByte(*buf++); } AT45DB161D_CS_HIGH; AT45DB161D_Delay_uS(10); Status = (Read_Status_Register() & 0x80)>>7; while(Status == 0x00) { Status = (Read_Status_Register() & 0x80)>>7; } return; } /* 1.將當前地址所對應內存頁內容讀取到緩沖區中。 2.使用緩沖區到內存寫命令,修改緩沖區內容,將緩沖區寫到內存頁中。 */ void AT45DB161D_Write(unsigned int Add,char* buf,unsigned int Len) { int Available_Byte,Write_Num; while(Len) { Page_To_Buffer(Add); //將內存頁中的數據拷貝到緩沖區中 Available_Byte = 528-Add%528; if(Available_Byte >= Len) { Write_Num = Len; } else { Write_Num = Available_Byte; } Buffer_To_Page(Add,buf,Write_Num); buf += Write_Num; Len -= Write_Num; Add += Write_Num; } return; } //C7H(操作碼)+94H(操作碼)+80H(操作碼)+9AH(操作碼)+CS電平跳變(從低到高) void AT45DB161D_Chip_Erase(void) { char Status; AT45DB161D_CS_LOW; AT45DB161D_SendByte(0xC7); AT45DB161D_SendByte(0x94); AT45DB161D_SendByte(0x80); AT45DB161D_SendByte(0x9A); AT45DB161D_CS_HIGH; AT45DB161D_Delay_uS(10); Status = (Read_Status_Register() & 0x80)>>7; while(Status == 0x00) { Status = (Read_Status_Register() & 0x80)>>7; } return; }
AT45DB161D.h文件內容
1 #ifndef AT45DB161D_H 2 #define AT45DB161D_H 3 4 #include "stm32f10x.h" 5 6 /* 7 CLK PB13 8 CS PC7 9 MOSI PB15 10 MISO PB14 11 */ 12 13 #define AT45DB161D_CS_PORT GPIOC 14 #define AT45DB161D_CLK_PORT GPIOD 15 #define AT45DB161D_MOSI_PORT GPIOD 16 #define AT45DB161D_MISO_PORT GPIOD 17 18 #define AT45DB161D_CS_PIN GPIO_Pin_12 19 #define AT45DB161D_CLK_PIN GPIO_Pin_3 20 #define AT45DB161D_MOSI_PIN GPIO_Pin_4 21 #define AT45DB161D_MISO_PIN GPIO_Pin_2 22 23 #define AT45DB161D_CS_CLK RCC_APB2Periph_GPIOC 24 #define AT45DB161D_CLK_CLK RCC_APB2Periph_GPIOD 25 #define AT45DB161D_MOSI_CLK RCC_APB2Periph_GPIOD 26 #define AT45DB161D_MISO_CLK RCC_APB2Periph_GPIOD 27 28 #define AT45DB161D_CS_LOW GPIO_ResetBits(AT45DB161D_CS_PORT,AT45DB161D_CS_PIN) 29 #define AT45DB161D_CS_HIGH GPIO_SetBits(AT45DB161D_CS_PORT,AT45DB161D_CS_PIN) 30 #define AT45DB161D_CLK_LOW GPIO_ResetBits(AT45DB161D_CLK_PORT,AT45DB161D_CLK_PIN) 31 #define AT45DB161D_CLK_HIGH GPIO_SetBits(AT45DB161D_CLK_PORT,AT45DB161D_CLK_PIN) 32 #define AT45DB161D_MOSI_LOW GPIO_ResetBits(AT45DB161D_MOSI_PORT,AT45DB161D_MOSI_PIN) 33 #define AT45DB161D_MOSI_HIGH GPIO_SetBits(AT45DB161D_MOSI_PORT,AT45DB161D_MOSI_PIN) 34 35 #define AT45DB161D_MISO GPIO_ReadInputDataBit(AT45DB161D_MISO_PORT,AT45DB161D_MISO_PIN) 36 37 extern void AT45DB161D_Init_Pin(void); 38 extern void AT45DB161D_Read(unsigned int Add,char* buf,unsigned int Len); 39 extern void AT45DB161D_Write(unsigned int Add,char* buf,unsigned int Len); 40 extern void AT45DB161D_Chip_Erase(void); 41 42 #endif