/*****************《SPI_Flash.C》**************************************/
#include "SPI_Flash.h"
//在这个里有被"/* */"引起来的代码是利用IO口模仿SPI时序,要利用模仿的SPI接口,需要将子函数的
//“ MSP430_SPI_Read_Btye(); 先要预读一次,这可能是在硬件SPI的特殊情况,在通过IO口模拟的情况下,不需要”
//去掉就可以了
//使用过程先调用Master_SPI_Init() , 接着SPI_Flash_Sector_Erase() , SPI_Flash_Read_ID() ,SPI_Flash_Read_Elecsign()上述两个函数的返//回值可以验证你的结果是不是对。
/*#define CLOCK_LOW (P5OUT &=~BIT3)
#define CLOCK_HIGH (P5OUT |=BIT3)
#define MOSI_LOW (P5OUT &=~BIT1)
#define MOSI_HIGH (P5OUT |= BIT1)*/
void Master_SPI_Init(void)
{
U1CTL = CHAR+ SYNC + MM; //八位数据,SPI模式,主机
U1TCTL = STC +SSEL1 ; //选择ACLK作为时钟源,三线SPI模式
U1BR0 = 0x02; //波特率分频因子位4
U1BR1 = 0x00; //
U1MCTL = 0x00;
ME2 |= USPIE1; //SPI1模块允许
P5SEL |= 0x0E;
//U1IE |= URXIE1 + UTXIE1; // Enable USART0 RX interrupt
U1CTL &= ~SWRST; // SWRET复位,USART1模块允许
SPI_Flash_Dir |= BIT0 +BIT4 ; //hold和CS信号输出
SPI_Flash_CS_ON;
SPI_Flash_CS_OFF; //CS信号要置位,等到写指令或数据时再将其清零
SPI_Flash_Stop_Hold; //不中止
//_EINT();
/* SPI_Flash_Dir |=BIT0 +BIT1 +BIT3 +BIT4;
SPI_Flash_CS_ON;
SPI_Flash_CS_OFF; //CS信号要置位,等到写指令或数据时再将其清零
SPI_Flash_Stop_Hold; //不中止
*/
}
void MSP430_SPI_Write_Byte(uchar data)
{
IFG2 &= ~UTXIFG1; // 清除标志,USART1发送中断标志位
U1TXBUF = data; //将数据发送到U1TXBUF中,自动发送
while (!(IFG2 & UTXIFG1)); // 等待发送完成
IFG2 &= ~URXIFG1; //因为在MOSI发送数据的时候,也可能有数据在SOMI接口接收数据,所以将接收标志位清掉
IFG2 &= ~UTXIFG1; //清掉发送标志
/* uchar i;
for(i=0 ; i<8 ;i++)
{
CLOCK_LOW;
_NOP();
if((data & 0x80)!=0) MOSI_HIGH;
else MOSI_LOW;
data<<=1;
CLOCK_HIGH;
_NOP();
}
CLOCK_LOW;*/
}
uchar MSP430_SPI_Read_Btye(void)
{
uchar data=0;
IFG2 &= ~UTXIFG1; //清除标志
U1TXBUF = 0x00;
while (!(IFG2 & URXIFG1)); // 等待
data = U1RXBUF; // 接收
IFG2 &= ~URXIFG1;
while(!(IFG2 & UTXIFG1)); //等待 U1TXBUF = 0发送完成
IFG2 &= ~UTXIFG1; //清除标志RXBUF1
return data;
/* uchar data=0,i;
for(i=0; i<8; i++)
{
CLOCK_LOW;
_NOP();
data <<=1;
if((P5IN & BIT2)!=0) data |=0x01;
else data &=0x0FE;
CLOCK_HIGH;
_NOP();
}
return data;*/
}
void SPI_Flash_Read_Busy(void)
{
uchar data;
do
{
SPI_Flash_CS_ON; //片选有效
MSP430_SPI_Write_Byte(RDSR); //读状态寄存器0x05
MSP430_SPI_Read_Btye();
data = MSP430_SPI_Read_Btye(); //从接收缓存中读取数据??????
SPI_Flash_CS_OFF; //片选无效
}while(data&0x01 != 0); //当读取的数据末位为1表示繁忙,为0表示空闲
}
//写使能
void SPI_Flash_Write_En(void)
{
SPI_Flash_CS_ON;
MSP430_SPI_Write_Byte(WREN); //写使能0x06
SPI_Flash_CS_OFF;
}
//块擦除
void SPI_Flash_Bulk_Erase(void)
{
SPI_Flash_Read_Busy(); // 读忙状态
SPI_Flash_Write_En(); //写使能
SPI_Flash_Read_Busy(); // 读忙状态
SPI_Flash_CS_ON; //片选有效
MSP430_SPI_Write_Byte(BE); //整块擦除0x0C7
SPI_Flash_CS_OFF; //片选无效
SPI_Flash_Read_Busy();
}
//某一扇区擦除 输入参数为某一扇区的24位首地址
void SPI_Flash_Sector_Erase(unsigned long Addr)
{
uchar Addr_High,Addr_Midd,Addr_Low;
Addr_High = (Addr & 0x00ff0000) >> 16;
Addr_Midd = (Addr & 0x0000ff00) >> 8;
Addr_Low = Addr & 0x000000ff;
SPI_Flash_Read_Busy(); // 读忙状态
SPI_Flash_Write_En(); //写使能
SPI_Flash_Read_Busy(); // 读忙状态
SPI_Flash_CS_ON; //片选有效
MSP430_SPI_Write_Byte(SE); //单块擦除0x0D8
MSP430_SPI_Write_Byte(Addr_High); //写地址高位
MSP430_SPI_Write_Byte(Addr_Midd); //写地址高中间位
MSP430_SPI_Write_Byte(Addr_Low); //写地址低位
SPI_Flash_CS_OFF; //片选无效
SPI_Flash_Read_Busy();
}
//对某一页写数据 输入参数分别为:某一24首地址,要写的数据缓存,要写的数据长度
void SPI_Flash_Write_Data(unsigned long Addr ,uchar *Data_Buff ,uchar Data_Len)
{
uchar Addr_High,Addr_Midd,Addr_Low,i;
Addr_High = (Addr & 0x00ff0000) >> 16;
Addr_Midd = (Addr & 0x0000ff00) >> 8;
Addr_Low = Addr & 0x000000ff;
SPI_Flash_Read_Busy(); // 读忙状态
SPI_Flash_Write_En(); //写使能
SPI_Flash_Read_Busy(); // 读忙状态
SPI_Flash_CS_ON; //片选有效
MSP430_SPI_Write_Byte(PP); //页面数据写入0x02
MSP430_SPI_Write_Byte(Addr_High); //写地址高位
MSP430_SPI_Write_Byte(Addr_Midd); //写地址高中间位
MSP430_SPI_Write_Byte(Addr_Low); //写地址低位
for(i =0 ; i<Data_Len ;i++)
{
MSP430_SPI_Write_Byte(Data_Buff[i]);
_NOP();
}
SPI_Flash_CS_OFF; //片选无效
}
//对某一页读数据 输入参数分别为:某24位地址,读出得数据存放的缓存,要读得数据长度
void SPI_Flash_Read_Data(unsigned long Addr ,uchar *Data_Buff ,uchar Data_Len)
{
uchar Addr_High,Addr_Midd,Addr_Low,i;
Addr_High = (Addr & 0x00ff0000) >> 16;
Addr_Midd = (Addr & 0x0000ff00) >> 8;
Addr_Low = Addr & 0x000000ff;
SPI_Flash_Read_Busy(); // 读忙状态
SPI_Flash_Write_En(); //写使能
SPI_Flash_Read_Busy(); // 读忙状态
SPI_Flash_CS_ON; //片选有效
MSP430_SPI_Write_Byte(READ); //读取数据0x03
MSP430_SPI_Write_Byte(Addr_High); //写地址高位
MSP430_SPI_Write_Byte(Addr_Midd); //写地址高中间位
MSP430_SPI_Write_Byte(Addr_Low); //写地址低位
MSP430_SPI_Read_Btye(); 先要预读一次,这可能是在硬件SPI的特殊情况,在通过IO口模拟的情况下,不需要
for(i =0 ; i<Data_Len ;i++)
{
Data_Buff[i] = MSP430_SPI_Read_Btye(); //从接收缓存中读取数据??????
_NOP();
}
SPI_Flash_CS_OFF; //片选无效
}
//读芯片ID号 生产商ID号20H,和Device ID号20H、17H ;输入参数为三个字节的数组
void SPI_Flash_Read_ID(uchar *ID)
{
SPI_Flash_CS_ON; //片选有效
MSP430_SPI_Write_Byte(RDID); //读标识0x9F
MSP430_SPI_Read_Btye(); 先要预读一次,这可能是在硬件SPI的特殊情况,在通过IO口模拟的情况下,不需要
ID[0] = MSP430_SPI_Read_Btye(); //从接收缓存中读取数据??????
ID[1] = MSP430_SPI_Read_Btye(); //从接收缓存中读取数据??????
ID[2] = MSP430_SPI_Read_Btye(); //从接收缓存中读取数据??????
SPI_Flash_CS_OFF; //片选无效
}
//读电子签名,无输入参数,返回的数值应为16H
uchar SPI_Flash_Read_Elecsign(void)
{
uchar status;
SPI_Flash_CS_ON; //片选有效
MSP430_SPI_Write_Byte(RES); //读电子签名0x0AB
MSP430_SPI_Write_Byte(0x00);
MSP430_SPI_Write_Byte(0x00);
MSP430_SPI_Write_Byte(0x00);
MSP430_SPI_Read_Btye(); 先要预读一次,这可能是在硬件SPI的特殊情况,在通过IO口模拟的情况下,不需要
status = MSP430_SPI_Read_Btye(); //从接收缓存中读取数据??????
SPI_Flash_CS_OFF; //片选无效
return status;
}
//去除写保护状态
void SPI_Flash_Unprotected(void)
{
SPI_Flash_CS_ON; //片选有效
SPI_Flash_Write_En(); //写使能
MSP430_SPI_Write_Byte(WRSR); //写状态寄存器0x01
MSP430_SPI_Write_Byte(0x00);
SPI_Flash_CS_OFF; //片选无效
}
/***********《SPI_Flash.h》*****************************************************/
#ifndef _SPI_FLASH_H
#define _SPI_FLASH_H
/*******************************************************************************
2012-7-21 BY ZJX
//使用时只需修改前7行代码
*******************************************************************************/
#include "my_msp430x14x.h"
#define WREN 0x06 //写使能
#define WRDI 0x04 //写无效
#define RDID 0x9F //读标识
#define RDSR 0x05 //读状态寄存器
#define WRSR 0x01 //写状态寄存器
#define READ 0x03 //读取数据
#define FAST_READ 0x0B //快速读取数据
#define PP 0x02 //页面数据写入
#define SE 0x0D8 //单块擦除
#define BE 0x0C7 //整块擦除
#define RES 0x0AB //读电子签名
#define SPI_Flash_Hold_Out P5OUT
#define SPI_Flash_CS_Out P5OUT
#define SPI_Flash_Dir P5DIR
#define SPI_Flash_Hold_BIT BIT4
#define SPI_Flash_CS_BIT BIT0
#define SPI_Flash_Hold (SPI_Flash_Hold_Out &= ~SPI_Flash_Hold_BIT)
#define SPI_Flash_Stop_Hold (SPI_Flash_Hold_Out |= SPI_Flash_Hold_BIT)
#define SPI_Flash_CS_OFF (SPI_Flash_CS_Out |=SPI_Flash_CS_BIT)
#define SPI_Flash_CS_ON (SPI_Flash_CS_Out &= ~SPI_Flash_CS_BIT)
void Master_SPI_Init(void);
void MSP430_SPI_Write_Byte(uchar data);
void SPI_Flash_Read_Busy( void );
void SPI_Flash_Write_En(void);
void SPI_Flash_Bulk_Erase(void);
void SPI_Flash_Sector_Erase(unsigned long Addr);
void SPI_Flash_Write_Data(unsigned long Addr ,uchar *Data_Buff ,uchar Data_Len);
void SPI_Flash_Read_Data(unsigned long Addr ,uchar *Data_Buff ,uchar Data_Len);
void SPI_Flash_Read_ID(uchar *ID);
uchar SPI_Flash_Read_Elecsign(void);
void SPI_Flash_Unprotected(void);
#endif
链接: https://pan.baidu.com/s/1kAQgutIqBOV433cngYP24g
提取码: cysd
最后放弃了25P64了,因为擦除需要64K内存。103c8t6才20K的RAM。4k的w25q64比较合适