hpdell 发表于 2010-10-21 09:34:59

sst25vf0xxx 的单字节的数据读写程序

此程序的可以读写单个字节的数据或者是多字节,绝对是OK的
单片机采用STC12LE5A60S2
晶振:33MHz
FLASH:SST25VF080B





#include<reg52.h>


sbit SPI_CS = P2^2;
sbit SPI_CK = P3^4;
sbit SPI_DI = P3^5;
sbit SPI_DO = P2^1;
sbit SPI_WP = P2^0;
sbit SPI_HOLD = P2^3;


#define SPI_WP_H SPI_WP=1               
#define SPI_WP_L SPI_WP=0               

#define SPI_CS_H SPI_CS=1
#define SPI_CS_L SPI_CS=0

#define SPI_CK_H SPI_CK=1
#define SPI_CK_L SPI_CK=0

#define SPI_DI_H SPI_DI=1
#define SPI_DI_L SPI_DI=0

#define SPI_DO_H SPI_DO=1
#define SPI_DO_L SPI_DO=0

#define SPI_WP_H SPI_WP=1
#define SPI_WP_L SPI_WP=0

#define SPI_HOLD_H SPI_HOLD=1
#define SPI_HOLD_L SPI_HOLD=0



#define Read_Data               0x03       //读取存储器数据
#define FastReadData            0x0B       //快速读取存储器数据
#define FastReadDualOutput      0x3B       //快速双端口输出方式读取存储器数据
#define ReadStatusRegister      0x05       //读状态寄存器
#define Enable_Write_Status_Register 0x50               //写状态寄存器使能 or 0x06
#define WriteStatusRegister       0x01       //写状态寄存器
#define WriteEnable               0x06       //写使能,设置状态寄存器 or 0x50
#define WriteDisable            0x04       //写禁止

#define Page_Program            0x02       //页面编程--写数据
#define ChipErase               0xC7       //片擦除
#define SectorErase_4K            0x20       //扇区擦除        ,4kb
#define BlockErase_32K            0x52       //块擦除,32kb
#define BlockErase_64K            0xD8       //块擦除,64kb
#define AAI_Word_Program                                        0xAD       //连续编程

void Spi_init();
void Spi_send_byte(unsigned char byte);
unsigned char Spi_get_byte();
unsigned char Spi_read_StatusRegister();
void Spi_wait_busy();
void Spi_WRSR(unsigned char byte);
void Spi_write_StatusRegister(unsigned char byte);
void Spi_Write_Enable();
void Spi_Write_Disable();


unsigned char Spi_Read_Byte(unsigned long addr);
unsigned char Spi_FasttRead_Byte(unsigned long addr);
void Spi_FastRead_nByte(unsigned long addr,unsigned char *p,unsigned long nByte);

void Spi_Write_Byte(unsigned long addr,unsigned char dat);
void Spi_Write_AAI_nByte(unsigned long addr,unsigned char *dat,unsigned long nByte);


void Spi_Erase_Chip();
void Spi_Erase_Sector_4k(unsigned char addr);
void Spi_Erase_Block_64k(unsigned long addr);



unsigned char read_dat_static=0;

void Spi_init()
{
        SPI_CK_L;               /* set clock to low initial state for SPI operation mode 0 */
//        SPI_CK_H;       /* set clock to low initial state for SPI operation mode 3 */
        SPI_WP_L;
        SPI_HOLD_H;
        SPI_CS_H;       


        Spi_Write_Disable();       
}


void Spi_send_byte(unsigned char byte)
{
        uchar i=0;
        SPI_CK_L;
        for(i=0;i<8;i++)
        {
                if((byte & 0x80)        == 0x80)        /* check if MSB is high */
                        SPI_DI_H;
                else
                        SPI_DI_L;

                SPI_CK_H;
                byte <<= 1;
                SPI_CK_L;
        }
        SPI_CK_L;
}

unsigned char Spi_get_byte()
{
        uchar i=0,dat=0,temp=0;
        SPI_CK_L;
        for(i=0;i<8;i++)
        {
                dat <<= 1;
                temp=SPI_DO;
                SPI_CK_H;
                if(temp==1)
                        dat |= 0x01;
                SPI_CK_L;
        }
        SPI_CK_L;
        return dat;
}


void Spi_Write_Enable()
{
        SPI_CS_L;
        Spi_send_byte(WriteEnable);       /* select write to status register */       
        SPI_CS_H;
}


void Spi_Write_Disable()
{
        SPI_CS_L;
        Spi_send_byte(WriteDisable);       // select write to status register
        SPI_CS_H;               
}

unsigned char Spi_read_StatusRegister()
{
        uchar StatusRegister=0;       
        SPI_CS_L;
        Spi_send_byte(ReadStatusRegister);
        StatusRegister =         Spi_get_byte();
        SPI_CS_H;               
        return StatusRegister;       
}

/*------------------------------------------
写状态寄存器,在写,擦除前必须保证状态寄存器的值是0x00
-----------------------------------------------*/
void Spi_WRSR(unsigned char byte)
{
        SPI_CS_L;
        Spi_send_byte(WriteStatusRegister);       /* select write to status register */
        Spi_send_byte(byte);       /* data that will change the status(only bits 2,3,7 can be written) */       
        SPI_CS_H;
}


void Spi_write_StatusRegister(unsigned char byte)
{
        Spi_Write_Enable();
        Spi_WRSR(byte);
        Spi_wait_busy();
        Spi_Write_Disable();
}



void Spi_wait_busy()
{
        while(Spi_read_StatusRegister() == 0X03)
                Spi_read_StatusRegister();               /*waste time until not busy WEL & Busy bit all be 1 (0x03). */
}


/*------------------------------------------------------
从芯片内读出一个字节的数据
addr是读取数据的地址
------------------------------------------------------*/
unsigned char Spi_Read_Byte(unsigned long addr)
{
        unsigned char byte=0;
        SPI_CS_L;       
        Spi_send_byte(Read_Data);                // read command
        Spi_send_byte((unsigned char)((addr&0xFFFFFF)>>16));
        Spi_send_byte((unsigned char)((addr&0xFFFF)>>8));
        Spi_send_byte((unsigned char)(addr&0xFF));       
        byte = Spi_get_byte();
        SPI_CS_H;       
        return byte;               // return one byte read
}



/*------------------------------------------------
SST25Read 高速读
,可调用此函数读
函数名称:void spi_FastRead_nByte(unsigned long addr,unsigned char *p,unsigned long nByte)
addr 读取地址

----------------------------------*/
void Spi_FastRead_nByte(unsigned long addr,unsigned char *p,unsigned long nByte)
{
        SPI_CS_L;
        Spi_send_byte(FastReadData);       // read command 0x0b
        Spi_send_byte((unsigned char)((addr&0xFFFFFF)>>16));
        Spi_send_byte((unsigned char)((addr&0xFFFF)>>8));
        Spi_send_byte((unsigned char)(addr&0xFF));
        Spi_send_byte(0xff);               //dummy byte
        for(;nByte>0;nByte--)
                *p++ = Spi_get_byte();
        SPI_CS_H;
}


/*------------------------------------------------------
写一个字节的数据
addr是写入数据的地址
dat 是写入的数据
------------------------------------------------------*/

void Spi_Write_Byte(unsigned long addr,unsigned char dat)
{
       
        Spi_Write_Enable();
        Spi_WRSR(0x00);
        Spi_Write_Enable();
        SPI_CS_L;
        Spi_send_byte(Page_Program);       // send Byte Program command
        Spi_send_byte((unsigned char)((addr&0xFFFFFF)>>16));
        Spi_send_byte((unsigned char)((addr&0xFFFF)>>8));
        Spi_send_byte((unsigned char)(addr&0xFF));
        Spi_send_byte(dat);
        SPI_CS_H;       
        Spi_wait_busy();
}



/*------------------------------------------------------
写n个字节的数据
addr是写入数据的地址
dat 是写入的数据
------------------------------------------------------*/
void Spi_Write_AAI_nByte(unsigned long addr,unsigned char *dat,unsigned long nByte){
        unsigned long cnt;       

        if(nByte == 0)
                return;

        for(cnt=0;cnt<nByte;cnt++)
        {
                if(cnt==0)
                {
                        Spi_Write_Enable();
                        Spi_WRSR(0x00);
                        Spi_Write_Enable();
                        SPI_CS_L;       
                       
                        Spi_send_byte(AAI_Word_Program);
                        Spi_send_byte((unsigned char)((addr&0xFFFFFF)>>16));
                        Spi_send_byte((unsigned char)((addr&0xFFFF)>>8));
                        Spi_send_byte((unsigned char)(addr&0xFF));
                        Spi_send_byte(*dat++);
                        Spi_send_byte(*dat++);       
                        //Spi_wait_busy();
                }       

                else        if(cnt!=0)
                {
                        Spi_Write_Enable();
                        SPI_CS_L;       
                       
                        Spi_send_byte(AAI_Word_Program);
                        Spi_send_byte(*dat++);
                        Spi_send_byte(*dat++);
                        //Spi_wait_busy();                       
                }
       
                SPI_CS_H;               
                Spi_wait_busy_AAI();
               cnt += 1;                //因为for循环还要加上一次
       
       
        }
        Spi_Write_Disable();        //WRDI用于退出AAI写模式 所谓AAI 就是地址自动加
        nByte = 0; //地址清0
}


void Spi_Erase_Chip()
{
        Spi_Write_Enable();
        Spi_WRSR(0x00);
        Spi_Write_Enable();
        SPI_CS_L;
        Spi_send_byte(ChipErase);
        SPI_CS_H;
        Spi_wait_busy();
}


/*-----------------------------------------
扇区擦除
每个扇区的大小是4096biye
sst25vf080 一共有256个扇区
addr 扇区的数量,最大是0~255个扇区
-----------------------------------------------*/
void Spi_Erase_Sector_4k(unsigned char addr)
{
        unsigned long sector_addr=0;

        sector_addr = (unsigned long)(addr * 4096);

        Spi_Write_Enable();
        Spi_WRSR(0x00);
        Spi_Write_Enable();
        SPI_CS_L;
        SPI_CS_L;
        Spi_send_byte(SectorErase_4K);
        Spi_send_byte((unsigned char)((sector_addr&0xFFFFFF)>>16));
        Spi_send_byte((unsigned char)((sector_addr&0xFFFF)>>8));
        Spi_send_byte((unsigned char)(sector_addr&0xFF));
        SPI_CS_H;
        Spi_wait_busy();
        Spi_Write_Disable();
}






void main()
{
        unsigned int i=0;

        delay_ms(1000);
        Uart0_Init();

        Spi_init();

        Spi_Erase_Chip();
        Spi_Erase_Sector_4k(0);

        read_dat_static = Spi_read_StatusRegister();       //读寄存器状态测试OK

        printexp("read_dat_static",read_dat_static,16);   //通过串口发回给电脑


        Spi_write_StatusRegister(0x1C);                        //写寄存器状态测试OK


        read_dat_static = Spi_read_StatusRegister();

        printexp("写寄存器状态测试OK",read_dat_static,16);

        Spi_Write_Byte(0,0x4f);           //单字节读写测试OK

        read_dat_static = Spi_Read_Byte(0);

        printexp("写入的数据又重新读出来,单字节的数据",read_dat_static,16);

        Spi_Write_Byte(3,0xce);

        read_dat_static = Spi_Read_Byte(3);

        printexp("写入的数据又重新读出来,单字节的数据",read_dat_static,16);
       
Spi_Write_AAI_nByte(0,write_buff,256);   //aai模式,
Spi_FastRead_nByte(0,read_buff,256);

for(i=0;i<256;i++)
{
                uart0_tx(read_buff);
}


        for(;;)
        {
                ;
        }
}

dongfangxuri 发表于 2010-10-26 22:09:58

mark

380121850 发表于 2010-11-4 00:56:39

用软件模拟的是可以的
我现在用430硬件的SPI,可读,不可写,不知道为什么

linxiaolong 发表于 2010-11-11 20:27:33

正好用到,谢谢!

hebin939 发表于 2010-11-20 02:00:08

程序是有问题的。。

hebin939 发表于 2010-11-20 02:01:31

Spi_wait_busy_AAI();
都没有定义,,还说绝对OK

intentydh 发表于 2010-12-7 11:26:51

mark.

hpdell 发表于 2011-2-22 13:53:00

那时把这个函数给忘记了,现在补上,望各位谅解,

#define BUSY                      (0X03)
#define AAI_BUSY               (0X43)



void Spi_wait_busy_AAI()
{
        while(Spi_read_StatusRegister() == AAI_BUSY)
                Spi_read_StatusRegister();               /*waste time until not busy WEL & Busy bit all be 1 (0x03). */
}

eiglxl 发表于 2011-2-22 14:12:49

Write_AAI 对起始地址是有要求的。

hpdell 发表于 2011-2-23 09:15:01

按照最小扇区就可以了,我现在存到里面的数据,读出后送入到TFT显示,效果很好哦!!!!!!!!

_dog 发表于 2011-10-25 23:11:56

这个帖子就是好,还有一个08年的老贴,参照着看解决了,

LingYi 发表于 2013-9-4 17:52:57

本帖最后由 LingYi 于 2013-9-5 10:14 编辑

楼主,高速循环读我测试怎么读不出数据阿?

eva015401 发表于 2013-11-5 23:54:24

mark FLASH C51

ruixs 发表于 2016-5-30 15:42:46

需要研究中。。。

smart_inside 发表于 2016-12-17 13:19:30

没有人说是最后的读写速度如何呢,写入能到300K BYTE./S吗???

cc1987 发表于 2017-6-13 16:39:47

支持下~学习
页: [1]
查看完整版本: sst25vf0xxx 的单字节的数据读写程序