|
此程序的可以读写单个字节的数据或者是多字节,绝对是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来反美的!
|