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 }