搜索
bottom↓
回复: 15

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

[复制链接]

出0入0汤圆

发表于 2010-10-21 09:34:59 | 显示全部楼层 |阅读模式
此程序的可以读写单个字节的数据或者是多字节,绝对是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(;;)
        {
                ;
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2010-10-26 22:09:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-4 00:56:39 | 显示全部楼层
用软件模拟的是可以的
我现在用430硬件的SPI,可读,不可写,不知道为什么

出0入0汤圆

发表于 2010-11-11 20:27:33 | 显示全部楼层
正好用到,谢谢!

出0入0汤圆

发表于 2010-11-20 02:00:08 | 显示全部楼层
程序是有问题的。。

出0入0汤圆

发表于 2010-11-20 02:01:31 | 显示全部楼层
Spi_wait_busy_AAI();
都没有定义,,还说绝对OK

出0入0汤圆

发表于 2010-12-7 11:26:51 | 显示全部楼层
mark.

出0入0汤圆

 楼主| 发表于 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). */
}

出0入168汤圆

发表于 2011-2-22 14:12:49 | 显示全部楼层
Write_AAI 对起始地址是有要求的。

出0入0汤圆

 楼主| 发表于 2011-2-23 09:15:01 | 显示全部楼层
按照最小扇区就可以了,我现在存到里面的数据,读出后送入到TFT显示,效果很好哦!!!!!!!!

出0入0汤圆

发表于 2011-10-25 23:11:56 | 显示全部楼层
这个帖子就是好,还有一个08年的老贴,参照着看解决了,

出0入0汤圆

发表于 2013-9-4 17:52:57 | 显示全部楼层
本帖最后由 LingYi 于 2013-9-5 10:14 编辑

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

出0入0汤圆

发表于 2013-11-5 23:54:24 | 显示全部楼层
mark FLASH C51

出0入0汤圆

发表于 2016-5-30 15:42:46 | 显示全部楼层
需要研究中。。。

出0入0汤圆

发表于 2016-12-17 13:19:30 | 显示全部楼层
没有人说是最后的读写速度如何呢,写入能到300K BYTE./S吗???

出0入0汤圆

发表于 2017-6-13 16:39:47 | 显示全部楼层
支持下~学习
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 18:57

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表