STM32驱动AT45DB161D代码

STM32驱动AT45DB161D代码
STM32驱动AT45DB161D代码

//SPI初始化部分:

void SPI2_Init(void)

{

RCC->APB2ENR|=1<<3; //PORTB时钟使能

RCC->APB1ENR|=1<<14; //SPI2时钟使能

//这里只针对SPI口初始化

GPIOB->CRH&=0X000FFFFF;

GPIOB->CRH|=0XBBB00000; //PB13/14/15复用

GPIOB->ODR|=0X7<<13; //PB13/14/15上拉

SPI2->CR1|=0<<10; //全双工模式

SPI2->CR1|=1<<9; //软件nss管理

SPI2->CR1|=1<<8;

SPI2->CR1|=1<<2; //SPI主机

SPI2->CR1|=0<<11; //8bit数据格式

SPI2->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1

SPI2->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1 //对SPI2属于APB1的外设.时钟频率最大为36M.

SPI2->CR1|=7<<3; //Fsck=Fpclk1/256

SPI2->CR1|=0<<7; //MSBfirst

SPI2->CR1|=1<<6; //SPI设备使能

SPI2_ReadWriteByte(0xff);//启动传输

}

//SPI2 读写一个字节

//TxData:要写入的字节

//返回值:读取到的字节

u8 SPI2_ReadWriteByte(u8 TxData)

{

u16 retry=0;

while((SPI2->SR&1<<1)==0) //等待发送区空

{

retry++;

if(retry>=0XFFFE)return 0; //超时退出

}

SPI2->DR=TxData; //发送一个byte

retry=0;

while((SPI2->SR&1<<0)==0) //等待接收完一个byte

{

retry++;

if(retry>=0XFFFE)return 0; //超时退出

}

return SPI2->DR; //返回收到的数据

}

//以下对存储器的操作都是针对AT45DB161D的,

//AT45DB161D:16Mbit=2M字节

//

void FLASH_Init(void)

{

RCC->APB2ENR|=1<<3; //使能PORTB时钟

RCC->APB2ENR|=1<<8; //使能PORTG时钟

GPIOB->CRH&=0XFFF0FFFF;

GPIOB->CRH|=0X00030000; //PB12 推挽

GPIOB->ODR|=1<<12; //PB12上拉

GPIOG->CRH&=0XFFFFFFF0;

GPIOG->CRH|=0X00000003; //PG8 推挽

GPIOG->ODR|=1<<8; //PG8 上拉

SPI2_Init(); //初始化SPI2

}

//读取AT45DB161D的状态寄存器(查看数据手册P23)

//返回:读取的状态

//bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0

//RDY/BUSY COMP 1 0 1 1 PROTECT PAGESIZE u8 Flash_ReadStatus(void)

{

u8 rd;

FLASH_CS_L; //使能操作

SPI2_ReadWriteByte(STATUS_REG_READ); //发送读状态寄存器命令"D7H”

rd=SPI2_ReadWriteByte(0XFF); //读回状态

FLASH_CS_H; //失能操作

return rd;

}

//FLASH判忙函数

//不断读取外部FLASH的状态寄存器的bit7为判断是否为0

//bit7:0,忙;1,不忙

static void Flash_CheckBusy(void)

{

u8 st;

st=SPI2_ReadWriteByte(0XFF);

while( (st&BUSY_BIT_MASK)== BUSY_STATUS )

{

st=SPI2_ReadWriteByte(0XFF);

}

}

//读FLASH函数,调用者需保证所读取的数据不能超过范围

//page:指定页地址(0~4095页)

//offset:页内偏移地址(0~527字节)

//nBytes:读取的字节数

//*data:读到的数组首地址

//-----连续读到达一个页的结尾时,芯片会从下个页的开头继续读取,

//-----页间的跨越是没有延时的。当主存储器的最后一个位被读出后,

//-----芯片会自动返回到第一页的开头继续读取。与页间跨越相同的,

//------从存储器阵列结尾转到开头也是无延时的。

void Flash_Read(u16 page,u16 offset,u16 nBytes,u8 *data)

{

u32 addr; //绝对地址变量,注意528字节每页与512字节每页的绝对地址计算不一样,//这里用默认(264字节每页模式)

addr=((u32)page<<10)+offset; //24根地址线,PA11~PA0为页地址,BA9~BA0为页内//地址,详情请查看数据手册A T45DB161D第31页Table15-7

Flash_CheckBusy(); //判忙

FLASH_CS_L;

SPI2_ReadWriteByte(CONTINUE_ARRAY_READ); //发送连续读命令"0BH"

SPI2_ReadWriteByte( (u8)(addr>>16) ); //发送地址,从高到低

SPI2_ReadWriteByte( (u8)(addr>>8) );

SPI2_ReadWriteByte( (u8)(addr) );

SPI2_ReadWriteByte( 0 ); //a dummy byte

while( (nBytes--)>0 )

{

*data++=SPI2_ReadWriteByte(0XFF); //循环读取字节

}

FLASH_CS_H;

Flash_CheckBusy();

}

//写FLASH函数,调用者需保证所写入的数据不能超过范围

//page:指定页地址(0~4095页)整页直接写入主存储器

//*data:待写入的数组首地址

void Flash_PageWrite(u16 page,u8 *data)

{

u16 i;

u32 addr=0;

Flash_CheckBusy(); //判忙

addr=( (u32)page<<10); //页首地址

FLASH_CS_L;

SPI2_ReadWriteByte(MAIN_MEM_PAGE_PROGRAM); //发送主存储器编程命令"82H"

SPI2_ReadWriteByte( (u8)(addr>>16) );

SPI2_ReadWriteByte( (u8)(addr>>8) );

SPI2_ReadWriteByte( (u8)(addr) );

for(i=0;i<264;i++)

{

SPI2_ReadWriteByte( *data++ ); //循环写入字节数据

}

FLASH_CS_H;

Flash_CheckBusy(); //等待写完

}

//写入BUFF1函数,调用者需保证所写入的数据不能超过范围

//offset: 页内偏移地址(0~527字节)

//nBytes:写入的字节数(最大528)

//*data:待写入的数组首地址

void Flash_WriteBuf(u16 offset,u16 nBytes,u8 *data)

{

Flash_CheckBusy();

FLASH_CS_L;

SPI2_ReadWriteByte(BUFFER1_WRITE);//发送写BUFF1命令“84H”

SPI2_ReadWriteByte( 0x00 );

SPI2_ReadWriteByte( (u8)(offset>>8) );

SPI2_ReadWriteByte( (u8)offset );

while( (nBytes--)>0 )

{

SPI2_ReadWriteByte( *data++ );

}

FLASH_CS_H;

Flash_CheckBusy();

}

//从BUFF1写入到主存储器函数,BUFF1刚好是1页大小的缓存

//page:页地址(0~4095)

void Flash_BufToMemory(u16 page)

{

u32 addr=0;

addr=((u32)page<<10);

Flash_CheckBusy();

FLASH_CS_L;

SPI2_ReadWriteByte( BUFFER1_TO_MEMORY_WITH_ERASE);//发送从BUFF1到

//FLASH的写入操作命令"83H"

SPI2_ReadWriteByte( (u8)(addr>>16) );

SPI2_ReadWriteByte( (u8)(addr>>8) );

SPI2_ReadWriteByte( (u8)(addr) );

FLASH_CS_H;

Flash_CheckBusy();

}

//页擦除函数,整页进行擦除

//page:页地址(0~4095)

void Flash_PageErase(u16 page)

{

u32 addr=0;

addr=( (u32)page<<10);//计算页的绝对地址

Flash_CheckBusy();

FLASH_CS_L;

SPI2_ReadWriteByte(PAGE_ERASE); //发送页擦除命令“81H”

SPI2_ReadWriteByte( (u8)(addr>>16) );

SPI2_ReadWriteByte( (u8)(addr>>8) );

SPI2_ReadWriteByte( (u8)(addr) );

FLASH_CS_H;

}

相关主题
相关文档
最新文档