STM32下AT45DB161D驱动代码---模拟SPI(模式0)
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