www.pudn.com > msp430nand.rar > nand.c


#include  
#include  
#include "Nand.h" 
 
void Init_CLK(void); 
//全局变量 
extern int nSM_R_B; 
void SM_Port_Init(void) 
{ 
    P4DIR = 0; 
    P4DIR |= BIT0;    //设置CLE为输出管脚 
    P4DIR |= BIT1;    //设置CE~为输出管脚 
    P4DIR |= BIT2;    //设置ALE为输出管脚 
    P4DIR |= BIT3;    //设置RE~为输出管脚 
    P4DIR |= BIT4;    //设置WE~为输出管脚 
    P1DIR &= ~(BIT1); //设置R/B为输入管脚 
    return; 
} 
void CLE_Enable(void) 
{ 
    P4OUT |= BIT0; 
    return; 
} 
void CLE_Disable(void) 
{ 
    P4OUT &= ~(BIT0); 
    return; 
} 
void CE_Enable(void) 
{ 
    P4OUT &= ~(BIT1); 
    return; 
} 
void CE_Disable(void) 
{ 
    P4OUT |= BIT1; 
    return; 
} 
void ALE_Enable(void) 
{ 
    P4OUT |= BIT2; 
    return; 
} 
void ALE_Disable(void) 
{ 
    P4OUT &= ~(BIT2); 
    return; 
} 
void WE_Enable(void) 
{ 
    P4OUT &= ~(BIT4); 
    return; 
} 
void WE_Disable(void) 
{ 
    P4OUT |= BIT4; 
    return; 
} 
void RE_Enable(void) 
{ 
    P4OUT &= ~(BIT3); 
    return; 
} 
void RE_Disable(void) 
{ 
    P4OUT |= BIT3; 
    return; 
} 
int GetSMStatus(void) 
{ 
    int nTemp = 0; 
    return nTemp; 
} 
//////////////////////////////////////// 
// 正确返回 1,错误返回 0 
int PageWrite(int nCol,unsigned long nRow,char *pBuf) 
{ 
    int nTemp = 0; 
    int i; 
    int j; 
    unsigned nADD1; 
    unsigned nADD2; 
    unsigned nADD3; 
     
    nADD1 = nRow & 0x00ff; 
    nADD2 = (nRow >> 8) &0x00ff; 
    nADD3 = (nRow >> 16) & 0x00ff;	//处理最高地址的时候必须注意的是其余没有用的位必须是 0 
     
    CE_Enable(); 
     
    P5DIR = 0xff;			//设置P5口为输出方向 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0x80;			//页写命令 
    WE_Disable(); 
    CLE_Disable(); 
     
    ALE_Enable(); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nCol);	// 行的起始地址 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = nADD1; 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = nADD2; 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = nADD3; 
    WE_Disable(); 
    ALE_Disable(); 
     
    //WE_Enable(); 
    for(j = 0;j < 528;j++) 
    { 
    	WE_Enable(); 
    	P5OUT = pBuf[j]; 
    	//for(i = 3;i > 0;i--); 
    	WE_Disable(); 
    } 
    //WE_Disable(); 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0x10; 
    WE_Disable(); 
    CLE_Disable(); 
     
    //等待R/B中断 
    //while(!nSM_R_B) ; 
    //nSM_R_B = 0; 
    for(i = 100;i > 0;i--); 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0x70; 
    WE_Disable(); 
    CLE_Disable(); 
     
    P5DIR = 0x00;			//设置P5口为输入方向 
    for(i = 1000;i > 0;i--) 
    { 
    	RE_Enable(); 
    	nTemp = P5IN; 
    	RE_Disable(); 
    	if(nTemp == 0xc0) break; 
    } 
     
    if(nTemp == 0xc0) return 1; 
    else return 0; 
} 
//////////////////////////////////////// 
// 正确返回 1,错误返回 0 
int WriteByte(int nCommand,int nCol,unsigned long nRow,char nValue) 
{ 
    int nTemp = 0; 
    int i; 
    unsigned nADD1; 
    unsigned nADD2; 
    unsigned nADD3; 
     
    nADD1 = nRow & 0x00ff; 
    nADD2 = (nRow >> 8) &0x00ff; 
    nADD3 = (nRow >> 16) & 0x00ff;	//处理最高地址的时候必须注意的是其余没有用的位必须是 0 
     
    CE_Enable(); 
     
    P5DIR = 0xff;			//设置P5口为输出方向 
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nCommand);	//指针 
    WE_Disable(); 
    CLE_Disable(); 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0x80;			//页写命令 
    WE_Disable(); 
    CLE_Disable(); 
     
    ALE_Enable(); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nCol);	// 行的起始地址 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = nADD1; 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = nADD2; 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = nADD3; 
    WE_Disable(); 
    ALE_Disable(); 
   
    WE_Enable(); 
    P5OUT = nValue; 
    WE_Disable(); 
     
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0x10; 
    WE_Disable(); 
    CLE_Disable(); 
     
    //等待R/B中断 
    //while(!nSM_R_B) ; 
    //nSM_R_B = 0; 
    for(i = 100;i > 0;i--); 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0x70; 
    WE_Disable(); 
    CLE_Disable(); 
     
    P5DIR = 0x00;			//设置P5口为输入方向 
    for(i = 1000;i > 0;i--) 
    { 
    	RE_Enable(); 
    	nTemp = P5IN; 
    	RE_Disable(); 
    	if(nTemp == 0xc0) break; 
    } 
    //printf("SM Write: nTemp = %x ,",nTemp); 
    if(nTemp == 0xc0) return 1; 
    else return 0; 
} 
//////////////////////////////////////// 
// 正确返回 1,错误返回 0 
char ReadByte(int nCommand,int nCol,unsigned long nRow) 
{ 
    int i; 
    char chrLow = 0; 
    unsigned char nADD1; 
    unsigned char nADD2; 
    unsigned char nADD3; 
     
    nADD1 = nRow & 0x00ff; 
    nADD2 = (nRow >> 8) & 0x00ff; 
    nADD2 = (nRow >> 16) & 0x00ff; 
     
    CE_Enable(); 
     
    P5DIR = 0xff;		//设置P5口为输出方向 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nCommand);		//输出读命令代码; 
    WE_Disable(); 
    CLE_Disable(); 
     
    ALE_Enable(); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nCol); 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD1); 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD2); 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD3); 
    WE_Disable(); 
    ALE_Disable(); 
     
    //等待R/B中断 
    //while(!nSM_R_B) ; 
    //nSM_R_B = 0; 
    for(i = 100;i > 0;i--); 
     
    P5DIR = 0;			//设置P5口为输入方向 
 
    RE_Enable(); 
    chrLow = P5IN; 
    RE_Disable(); 
     
    CE_Disable(); 
    return chrLow; 
} 
 
//////////////////////////////////////// 
// 正确返回 1,错误返回 0 
int PageRead(int nCol,unsigned long nRow,char *pBuf) 
{ 
    int nTemp = 0; 
    int i; 
    int j; 
    unsigned char nADD1; 
    unsigned char nADD2; 
    unsigned char nADD3; 
     
    nADD1 = nRow & 0x00ff; 
    nADD2 = (nRow >> 8) & 0x00ff; 
    nADD2 = (nRow >> 16) & 0x00ff; 
     
    CE_Enable(); 
     
    P5DIR = 0xff;		//设置P5口为输出方向 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0x00;		//输出读命令代码 0x00; 
    WE_Disable(); 
    CLE_Disable(); 
     
    ALE_Enable(); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nCol); 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD1); 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD2); 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD3); 
    WE_Disable(); 
    ALE_Disable(); 
     
    //等待R/B中断 
    //while(!nSM_R_B) ; 
    //nSM_R_B = 0; 
    for(i = 100;i > 0;i--); 
     
    P5DIR = 0;			//设置P5口为输入方向 
    //RE_Enable(); 
    for(j = 0;j < 528;j++) 
    { 
    	RE_Enable(); 
    	pBuf[j] = P5IN; 
    	//for(i = 3;i > 0;i--);	//是否需要延时 
    	RE_Disable(); 
    } 
    //RE_Disable(); 
     
    CE_Disable(); 
    return nTemp; 
} 
//////////////////////////////////////// 
// 正确返回 1,错误返回 0 
int ReadID(unsigned char pBuf[2]) 
{ 
    int nTemp = 0; 
    int nMaker = 0; 
    int nDevice = 0; 
//    int nUniqueID = 0; 
//    int nPlaneCode = 0; 
    CE_Enable();		// 使能片选信号 
    ALE_Disable(); 
    CLE_Disable(); 
    RE_Disable(); 
    WE_Disable(); 
    P5DIR = 0XFF;		// 设置P5口为输出方向 
     
    CLE_Enable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    //for(i = 5;i > 0;i--); 
    P5OUT = 0x90;		// 输出命令代码 0x90 
    WE_Disable(); 
    CLE_Disable(); 
     
    ALE_Enable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    //for(i = 5;i > 0;i--); 
    P5OUT = 0x00;		// 地址周期 
    WE_Disable(); 
    ALE_Disable(); 
     
    P5DIR = 0x00;		// 设置P5口为输入方向 
     
    RE_Enable(); 
    nMaker = P5IN; 
    RE_Disable(); 
     
    RE_Enable(); 
    nDevice = P5IN; 
    RE_Disable(); 
    //RE_Enable(); 
    //nUniqueID = P5IN; 
    //RE_Disable(); 
    //RE_Enable(); 
    //nPlaneCode = P5IN; 
    //RE_Disable(); 
     
    CE_Disable(); 
     
    if(nMaker == 0xec) 
    { 
    	if(nDevice == 0x76 || nDevice == 0x79) 
    	{ 
    	    nTemp = 1; 
    	    pBuf[0] = (unsigned char)(nMaker); 
    	    pBuf[1] = (unsigned char)(nDevice); 
    	} 
    } 
    return nTemp; 
} 
///////////////////////////////////////// 
//成功返回 1,错误返回 0 
int BlockErase(unsigned long nAddr) 
{ 
    int nTemp = 0; 
    int i; 
    unsigned char nADD1; 
    unsigned char nADD2; 
    unsigned char nADD3; 
     
    nADD1 = nAddr & 0x00ff; 
    nADD2 = (nAddr >> 8) & 0x00ff; 
    nADD3 = (nAddr >> 16) & 0x00ff; 
     
    CE_Enable(); 
     
    P5DIR = 0xff;			//设置P5口为输出方向 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0x60;			//输出块擦出命令 
    WE_Disable(); 
    CLE_Disable(); 
     
    ALE_Enable(); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD1); 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD2); 
    WE_Disable(); 
    //for(i = 3;i > 0;i--); 
    WE_Enable(); 
    P5OUT = (unsigned char)(nADD3); 
    WE_Disable(); 
    ALE_Disable(); 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0xd0; 
    WE_Disable(); 
    CLE_Disable(); 
     
    //等待R/B中断 
    //while(!nSM_R_B); 
    //nSM_R_B = 0; 
    for(i = 200;i > 0;i--); 
     
    //CLE_Enable(); 
    //WE_Enable(); 
    //P5OUT = 0x70; 
    //WE_Disable(); 
    //CLE_Disable(); 
     
    P5DIR = 0;				//设置P5口为输入方向 
     
    RE_Enable(); 
    nTemp = P5IN; 
    RE_Disable(); 
     
    CE_Disable(); 
    //printf("SM: nTemp = %x ,",nTemp); 
    if(nTemp & 0x01) return 0; 
    else return 1; 
} 
///////////////////////////////////////////// 
// 正确返回 1,错误返回 0 
int VerifyValid(unsigned long nAddr) 
{ 
    int j; 
    int buf; 
    //char pBuf[528]; 
     
    for(j = 0;j < 32;j++) 
    { 
        buf = ReadByte(0x50,5,(nAddr + j)); 
         
        //printf("SM: buf = %x ,j = %d",buf,j); 
        if(buf != 0x00ff) break; 
         
    } 
    if(buf != 0x00ff) return 0; 
    else return 1; 
} 
void ResetSM(void) 
{   
    int i; 
    CE_Enable(); 
     
    P5DIR = 0xff;			// 设置P5口为输出方向 
     
    CLE_Enable(); 
    WE_Enable(); 
    P5OUT = 0xff;			// 输出RESET控制命令 
    WE_Disable(); 
    CLE_Disable(); 
     
    //while(!nSM_R_B); 
    //nSM_R_B = 0; 
    for(i = 100;i > 0;i--); 
     
    CE_Disable(); 
     
    return; 
} 
//////////////////////////////////////// 
// 正确返回 1,错误返回 0 
int BlockRead(unsigned long nAddr,char pBuf[32][528]) 
{ 
    int i,j; 
    int n; 
    unsigned char nADD1; 
    unsigned char nADD2; 
    unsigned char nADD3; 
     
    nADD1 = nAddr & 0x00ff; 
    nADD2 = (nAddr >> 8) & 0x00ff; 
    nADD3 = (nAddr >> 16) & 0x00ff; 
     
    CE_Enable(); 
     
    P5DIR = 0xff;				// 将P5口设置为输出方向 
    for(i = nADD1;i < nADD1 + 32;i++) 
    { 
    	ResetSM(); 
    	 
    	CLE_Enable(); 
    	WE_Enable(); 
    	P5OUT = 0x00; 
    	WE_Disable(); 
    	CLE_Disable(); 
    	 
    	ALE_Enable(); 
    	WE_Enable(); 
    	P5OUT = 0x00; 
    	WE_Disable(); 
    	 
    	WE_Enable(); 
    	P5OUT = (unsigned char)(i); 
    	WE_Disable(); 
    	 
    	WE_Enable(); 
    	P5OUT = (unsigned char)(nADD2); 
    	WE_Disable(); 
    	 
    	WE_Enable(); 
    	P5OUT = (unsigned char)(nADD3); 
    	WE_Disable(); 
    	ALE_Disable(); 
    	 
    	//while(!nSM_R_B); 
    	//nSM_R_B = 0; 
    	for(n = 100;n > 0;n--); 
    	 
    	P5DIR = 0x00;				// 将P5口设置为输入方向 
    	for(j = 0;j < 528;j++) 
    	{ 
    	    RE_Enable(); 
    	    pBuf[i][j] = P5IN; 
    	    RE_Disable(); 
    	} 
    } 
     
    CE_Disable(); 
     
     
    return 1; 
} 
//////////////////////////////////////// 
// 正确返回 1,错误返回 0 
int CopyToFlash(unsigned long nAddr) 
{ 
    return 1; 
} 
//////////////////////////////////////// 
// 正确返回 1,错误返回 0 
int RealTimeBadMark(unsigned long nAddr) 
{ 
    int i; 
    int rg_stat; 
				 
    for(i = 0;i < 32;i++) 
    { 
    	rg_stat = WriteByte(0x50,5,nAddr + i,0x00f0); 
    	//printf("rg_stat = %x i = %d",rg_stat,i); 
    	if((rg_stat & 0x01) != 0) return 0; 
    } 
     
    ResetSM(); 
	 
    return 1; 
} 
int main(void) 
{ 
    unsigned long nAddr; 
    int j; 
    int n; 
    int nTemp; 
    char pBuf0[528]; 
    char pBuf1[528]; 
    int nCount_Err; 
    int nLen; 
    // 关闭看门狗 
    WDTCTL = WDTPW + WDTHOLD;    
    // 关闭中断 
    _DINT();			                   
     
    // 初始化 
    Init_CLK(); 
    SM_Port_Init(); 
    // 打开中断 
    _EINT(); 			               
     
    // 擦除块地址为1024的块 
    nAddr = 1024; 
    BlockErase(nAddr); 
    // 延迟一点时间 
    for(j = 1000;j > 0;j--) ; 
    // 判断擦除的块是否为0xFF,起始页地址为1024 
    for(j = 0;j < 528;j++) pBuf0[j] = j; 
    // 按页写入数据,地址为:1024 
    PageWrite(0,1024,pBuf0); 
    // 延迟一点时间 
    for(j = 1000;j > 0;j--) ; 
    //按页读操作 
    PageRead(0,1024,pBuf1); 
    //比较读出数据和写入数据是否相等 
    nCount_Err = 0; 
    for(j = 0;j < 528;j++) 
    { 
    	if(pBuf0[j] != pBuf1[j]) 
    	{ 
    	    nCount_Err += 1; 
    	    break;	 
    	}    	 
    } 
     
    return 0; 
} 
void Init_CLK(void) 
{ 
    unsigned int i; 
    BCSCTL1 = 0X00;			//将寄存器的内容清零 
					//XT2震荡器开启 
					//LFTX1工作在低频模式 
					//ACLK的分频因子为1 
					 
    do  
    { 
	IFG1 &= ~OFIFG;                       // 清除OSCFault标志 
	for (i = 0x20; i > 0; i--);                 
    } 
    while ((IFG1 & OFIFG) == OFIFG);      // 如果OSCFault =1    
					 
    BCSCTL2 = 0X00;			//将寄存器的内容清零 
    BCSCTL2 += SELM1;		//MCLK的时钟源为TX2CLK,分频因子为1 
    BCSCTL2 += SELS;		//SMCLK的时钟源为TX2CLK,分频因子为1 
}