nand.c
上传用户:xs588588
上传日期:2021-03-30
资源大小:242k
文件大小:14k
源码类别:

DSP编程

开发平台:

C/C++

  1. #include <MSP430X14X.h>
  2. #include <stdio.h>
  3. #include "Nand.h"
  4. void Init_CLK(void);
  5. //全局变量
  6. extern int nSM_R_B;
  7. void SM_Port_Init(void)
  8. {
  9.     P4DIR = 0;
  10.     P4DIR |= BIT0;    //设置CLE为输出管脚
  11.     P4DIR |= BIT1;    //设置CE~为输出管脚
  12.     P4DIR |= BIT2;    //设置ALE为输出管脚
  13.     P4DIR |= BIT3;    //设置RE~为输出管脚
  14.     P4DIR |= BIT4;    //设置WE~为输出管脚
  15.     P1DIR &= ~(BIT1); //设置R/B为输入管脚
  16.     return;
  17. }
  18. void CLE_Enable(void)
  19. {
  20.     P4OUT |= BIT0;
  21.     return;
  22. }
  23. void CLE_Disable(void)
  24. {
  25.     P4OUT &= ~(BIT0);
  26.     return;
  27. }
  28. void CE_Enable(void)
  29. {
  30.     P4OUT &= ~(BIT1);
  31.     return;
  32. }
  33. void CE_Disable(void)
  34. {
  35.     P4OUT |= BIT1;
  36.     return;
  37. }
  38. void ALE_Enable(void)
  39. {
  40.     P4OUT |= BIT2;
  41.     return;
  42. }
  43. void ALE_Disable(void)
  44. {
  45.     P4OUT &= ~(BIT2);
  46.     return;
  47. }
  48. void WE_Enable(void)
  49. {
  50.     P4OUT &= ~(BIT4);
  51.     return;
  52. }
  53. void WE_Disable(void)
  54. {
  55.     P4OUT |= BIT4;
  56.     return;
  57. }
  58. void RE_Enable(void)
  59. {
  60.     P4OUT &= ~(BIT3);
  61.     return;
  62. }
  63. void RE_Disable(void)
  64. {
  65.     P4OUT |= BIT3;
  66.     return;
  67. }
  68. int GetSMStatus(void)
  69. {
  70.     int nTemp = 0;
  71.     return nTemp;
  72. }
  73. ////////////////////////////////////////
  74. // 正确返回 1,错误返回 0
  75. int PageWrite(int nCol,unsigned long nRow,char *pBuf)
  76. {
  77.     int nTemp = 0;
  78.     int i;
  79.     int j;
  80.     unsigned nADD1;
  81.     unsigned nADD2;
  82.     unsigned nADD3;
  83.     
  84.     nADD1 = nRow & 0x00ff;
  85.     nADD2 = (nRow >> 8) &0x00ff;
  86.     nADD3 = (nRow >> 16) & 0x00ff; //处理最高地址的时候必须注意的是其余没有用的位必须是 0
  87.     
  88.     CE_Enable();
  89.     
  90.     P5DIR = 0xff; //设置P5口为输出方向
  91.     
  92.     CLE_Enable();
  93.     WE_Enable();
  94.     P5OUT = 0x80; //页写命令
  95.     WE_Disable();
  96.     CLE_Disable();
  97.     
  98.     ALE_Enable();
  99.     WE_Enable();
  100.     P5OUT = (unsigned char)(nCol); // 行的起始地址
  101.     WE_Disable();
  102.     //for(i = 3;i > 0;i--);
  103.     WE_Enable();
  104.     P5OUT = nADD1;
  105.     WE_Disable();
  106.     //for(i = 3;i > 0;i--);
  107.     WE_Enable();
  108.     P5OUT = nADD2;
  109.     WE_Disable();
  110.     //for(i = 3;i > 0;i--);
  111.     WE_Enable();
  112.     P5OUT = nADD3;
  113.     WE_Disable();
  114.     ALE_Disable();
  115.     
  116.     //WE_Enable();
  117.     for(j = 0;j < 528;j++)
  118.     {
  119.      WE_Enable();
  120.      P5OUT = pBuf[j];
  121.      //for(i = 3;i > 0;i--);
  122.      WE_Disable();
  123.     }
  124.     //WE_Disable();
  125.     
  126.     CLE_Enable();
  127.     WE_Enable();
  128.     P5OUT = 0x10;
  129.     WE_Disable();
  130.     CLE_Disable();
  131.     
  132.     //等待R/B中断
  133.     //while(!nSM_R_B) ;
  134.     //nSM_R_B = 0;
  135.     for(i = 100;i > 0;i--);
  136.     
  137.     CLE_Enable();
  138.     WE_Enable();
  139.     P5OUT = 0x70;
  140.     WE_Disable();
  141.     CLE_Disable();
  142.     
  143.     P5DIR = 0x00; //设置P5口为输入方向
  144.     for(i = 1000;i > 0;i--)
  145.     {
  146.      RE_Enable();
  147.      nTemp = P5IN;
  148.      RE_Disable();
  149.      if(nTemp == 0xc0) break;
  150.     }
  151.     
  152.     if(nTemp == 0xc0) return 1;
  153.     else return 0;
  154. }
  155. ////////////////////////////////////////
  156. // 正确返回 1,错误返回 0
  157. int WriteByte(int nCommand,int nCol,unsigned long nRow,char nValue)
  158. {
  159.     int nTemp = 0;
  160.     int i;
  161.     unsigned nADD1;
  162.     unsigned nADD2;
  163.     unsigned nADD3;
  164.     
  165.     nADD1 = nRow & 0x00ff;
  166.     nADD2 = (nRow >> 8) &0x00ff;
  167.     nADD3 = (nRow >> 16) & 0x00ff; //处理最高地址的时候必须注意的是其余没有用的位必须是 0
  168.     
  169.     CE_Enable();
  170.     
  171.     P5DIR = 0xff; //设置P5口为输出方向
  172.     CLE_Enable();
  173.     WE_Enable();
  174.     P5OUT = (unsigned char)(nCommand); //指针
  175.     WE_Disable();
  176.     CLE_Disable();
  177.     
  178.     CLE_Enable();
  179.     WE_Enable();
  180.     P5OUT = 0x80; //页写命令
  181.     WE_Disable();
  182.     CLE_Disable();
  183.     
  184.     ALE_Enable();
  185.     WE_Enable();
  186.     P5OUT = (unsigned char)(nCol); // 行的起始地址
  187.     WE_Disable();
  188.     //for(i = 3;i > 0;i--);
  189.     WE_Enable();
  190.     P5OUT = nADD1;
  191.     WE_Disable();
  192.     //for(i = 3;i > 0;i--);
  193.     WE_Enable();
  194.     P5OUT = nADD2;
  195.     WE_Disable();
  196.     //for(i = 3;i > 0;i--);
  197.     WE_Enable();
  198.     P5OUT = nADD3;
  199.     WE_Disable();
  200.     ALE_Disable();
  201.   
  202.     WE_Enable();
  203.     P5OUT = nValue;
  204.     WE_Disable();
  205.     
  206.     
  207.     CLE_Enable();
  208.     WE_Enable();
  209.     P5OUT = 0x10;
  210.     WE_Disable();
  211.     CLE_Disable();
  212.     
  213.     //等待R/B中断
  214.     //while(!nSM_R_B) ;
  215.     //nSM_R_B = 0;
  216.     for(i = 100;i > 0;i--);
  217.     
  218.     CLE_Enable();
  219.     WE_Enable();
  220.     P5OUT = 0x70;
  221.     WE_Disable();
  222.     CLE_Disable();
  223.     
  224.     P5DIR = 0x00; //设置P5口为输入方向
  225.     for(i = 1000;i > 0;i--)
  226.     {
  227.      RE_Enable();
  228.      nTemp = P5IN;
  229.      RE_Disable();
  230.      if(nTemp == 0xc0) break;
  231.     }
  232.     //printf("SM Write: nTemp = %x ,",nTemp);
  233.     if(nTemp == 0xc0) return 1;
  234.     else return 0;
  235. }
  236. ////////////////////////////////////////
  237. // 正确返回 1,错误返回 0
  238. char ReadByte(int nCommand,int nCol,unsigned long nRow)
  239. {
  240.     int i;
  241.     char chrLow = 0;
  242.     unsigned char nADD1;
  243.     unsigned char nADD2;
  244.     unsigned char nADD3;
  245.     
  246.     nADD1 = nRow & 0x00ff;
  247.     nADD2 = (nRow >> 8) & 0x00ff;
  248.     nADD2 = (nRow >> 16) & 0x00ff;
  249.     
  250.     CE_Enable();
  251.     
  252.     P5DIR = 0xff; //设置P5口为输出方向
  253.     
  254.     CLE_Enable();
  255.     WE_Enable();
  256.     P5OUT = (unsigned char)(nCommand); //输出读命令代码;
  257.     WE_Disable();
  258.     CLE_Disable();
  259.     
  260.     ALE_Enable();
  261.     WE_Enable();
  262.     P5OUT = (unsigned char)(nCol);
  263.     WE_Disable();
  264.     //for(i = 3;i > 0;i--);
  265.     WE_Enable();
  266.     P5OUT = (unsigned char)(nADD1);
  267.     WE_Disable();
  268.     //for(i = 3;i > 0;i--);
  269.     WE_Enable();
  270.     P5OUT = (unsigned char)(nADD2);
  271.     WE_Disable();
  272.     //for(i = 3;i > 0;i--);
  273.     WE_Enable();
  274.     P5OUT = (unsigned char)(nADD3);
  275.     WE_Disable();
  276.     ALE_Disable();
  277.     
  278.     //等待R/B中断
  279.     //while(!nSM_R_B) ;
  280.     //nSM_R_B = 0;
  281.     for(i = 100;i > 0;i--);
  282.     
  283.     P5DIR = 0; //设置P5口为输入方向
  284.     RE_Enable();
  285.     chrLow = P5IN;
  286.     RE_Disable();
  287.     
  288.     CE_Disable();
  289.     return chrLow;
  290. }
  291. ////////////////////////////////////////
  292. // 正确返回 1,错误返回 0
  293. int PageRead(int nCol,unsigned long nRow,char *pBuf)
  294. {
  295.     int nTemp = 0;
  296.     int i;
  297.     int j;
  298.     unsigned char nADD1;
  299.     unsigned char nADD2;
  300.     unsigned char nADD3;
  301.     
  302.     nADD1 = nRow & 0x00ff;
  303.     nADD2 = (nRow >> 8) & 0x00ff;
  304.     nADD2 = (nRow >> 16) & 0x00ff;
  305.     
  306.     CE_Enable();
  307.     
  308.     P5DIR = 0xff; //设置P5口为输出方向
  309.     
  310.     CLE_Enable();
  311.     WE_Enable();
  312.     P5OUT = 0x00; //输出读命令代码 0x00;
  313.     WE_Disable();
  314.     CLE_Disable();
  315.     
  316.     ALE_Enable();
  317.     WE_Enable();
  318.     P5OUT = (unsigned char)(nCol);
  319.     WE_Disable();
  320.     //for(i = 3;i > 0;i--);
  321.     WE_Enable();
  322.     P5OUT = (unsigned char)(nADD1);
  323.     WE_Disable();
  324.     //for(i = 3;i > 0;i--);
  325.     WE_Enable();
  326.     P5OUT = (unsigned char)(nADD2);
  327.     WE_Disable();
  328.     //for(i = 3;i > 0;i--);
  329.     WE_Enable();
  330.     P5OUT = (unsigned char)(nADD3);
  331.     WE_Disable();
  332.     ALE_Disable();
  333.     
  334.     //等待R/B中断
  335.     //while(!nSM_R_B) ;
  336.     //nSM_R_B = 0;
  337.     for(i = 100;i > 0;i--);
  338.     
  339.     P5DIR = 0; //设置P5口为输入方向
  340.     //RE_Enable();
  341.     for(j = 0;j < 528;j++)
  342.     {
  343.      RE_Enable();
  344.      pBuf[j] = P5IN;
  345.      //for(i = 3;i > 0;i--); //是否需要延时
  346.      RE_Disable();
  347.     }
  348.     //RE_Disable();
  349.     
  350.     CE_Disable();
  351.     return nTemp;
  352. }
  353. ////////////////////////////////////////
  354. // 正确返回 1,错误返回 0
  355. int ReadID(unsigned char pBuf[2])
  356. {
  357.     int nTemp = 0;
  358.     int nMaker = 0;
  359.     int nDevice = 0;
  360. //    int nUniqueID = 0;
  361. //    int nPlaneCode = 0;
  362.     CE_Enable(); // 使能片选信号
  363.     ALE_Disable();
  364.     CLE_Disable();
  365.     RE_Disable();
  366.     WE_Disable();
  367.     P5DIR = 0XFF; // 设置P5口为输出方向
  368.     
  369.     CLE_Enable();
  370.     //for(i = 3;i > 0;i--);
  371.     WE_Enable();
  372.     //for(i = 5;i > 0;i--);
  373.     P5OUT = 0x90; // 输出命令代码 0x90
  374.     WE_Disable();
  375.     CLE_Disable();
  376.     
  377.     ALE_Enable();
  378.     //for(i = 3;i > 0;i--);
  379.     WE_Enable();
  380.     //for(i = 5;i > 0;i--);
  381.     P5OUT = 0x00; // 地址周期
  382.     WE_Disable();
  383.     ALE_Disable();
  384.     
  385.     P5DIR = 0x00; // 设置P5口为输入方向
  386.     
  387.     RE_Enable();
  388.     nMaker = P5IN;
  389.     RE_Disable();
  390.     
  391.     RE_Enable();
  392.     nDevice = P5IN;
  393.     RE_Disable();
  394.     //RE_Enable();
  395.     //nUniqueID = P5IN;
  396.     //RE_Disable();
  397.     //RE_Enable();
  398.     //nPlaneCode = P5IN;
  399.     //RE_Disable();
  400.     
  401.     CE_Disable();
  402.     
  403.     if(nMaker == 0xec)
  404.     {
  405.      if(nDevice == 0x76 || nDevice == 0x79)
  406.      {
  407.          nTemp = 1;
  408.          pBuf[0] = (unsigned char)(nMaker);
  409.          pBuf[1] = (unsigned char)(nDevice);
  410.      }
  411.     }
  412.     return nTemp;
  413. }
  414. /////////////////////////////////////////
  415. //成功返回 1,错误返回 0
  416. int BlockErase(unsigned long nAddr)
  417. {
  418.     int nTemp = 0;
  419.     int i;
  420.     unsigned char nADD1;
  421.     unsigned char nADD2;
  422.     unsigned char nADD3;
  423.     
  424.     nADD1 = nAddr & 0x00ff;
  425.     nADD2 = (nAddr >> 8) & 0x00ff;
  426.     nADD3 = (nAddr >> 16) & 0x00ff;
  427.     
  428.     CE_Enable();
  429.     
  430.     P5DIR = 0xff; //设置P5口为输出方向
  431.     
  432.     CLE_Enable();
  433.     WE_Enable();
  434.     P5OUT = 0x60; //输出块擦出命令
  435.     WE_Disable();
  436.     CLE_Disable();
  437.     
  438.     ALE_Enable();
  439.     WE_Enable();
  440.     P5OUT = (unsigned char)(nADD1);
  441.     WE_Disable();
  442.     //for(i = 3;i > 0;i--);
  443.     WE_Enable();
  444.     P5OUT = (unsigned char)(nADD2);
  445.     WE_Disable();
  446.     //for(i = 3;i > 0;i--);
  447.     WE_Enable();
  448.     P5OUT = (unsigned char)(nADD3);
  449.     WE_Disable();
  450.     ALE_Disable();
  451.     
  452.     CLE_Enable();
  453.     WE_Enable();
  454.     P5OUT = 0xd0;
  455.     WE_Disable();
  456.     CLE_Disable();
  457.     
  458.     //等待R/B中断
  459.     //while(!nSM_R_B);
  460.     //nSM_R_B = 0;
  461.     for(i = 200;i > 0;i--);
  462.     
  463.     //CLE_Enable();
  464.     //WE_Enable();
  465.     //P5OUT = 0x70;
  466.     //WE_Disable();
  467.     //CLE_Disable();
  468.     
  469.     P5DIR = 0; //设置P5口为输入方向
  470.     
  471.     RE_Enable();
  472.     nTemp = P5IN;
  473.     RE_Disable();
  474.     
  475.     CE_Disable();
  476.     //printf("SM: nTemp = %x ,",nTemp);
  477.     if(nTemp & 0x01) return 0;
  478.     else return 1;
  479. }
  480. /////////////////////////////////////////////
  481. // 正确返回 1,错误返回 0
  482. int VerifyValid(unsigned long nAddr)
  483. {
  484.     int j;
  485.     int buf;
  486.     //char pBuf[528];
  487.     
  488.     for(j = 0;j < 32;j++)
  489.     {
  490.         buf = ReadByte(0x50,5,(nAddr + j));
  491.         
  492.         //printf("SM: buf = %x ,j = %d",buf,j);
  493.         if(buf != 0x00ff) break;
  494.         
  495.     }
  496.     if(buf != 0x00ff) return 0;
  497.     else return 1;
  498. }
  499. void ResetSM(void)
  500. {  
  501.     int i;
  502.     CE_Enable();
  503.     
  504.     P5DIR = 0xff; // 设置P5口为输出方向
  505.     
  506.     CLE_Enable();
  507.     WE_Enable();
  508.     P5OUT = 0xff; // 输出RESET控制命令
  509.     WE_Disable();
  510.     CLE_Disable();
  511.     
  512.     //while(!nSM_R_B);
  513.     //nSM_R_B = 0;
  514.     for(i = 100;i > 0;i--);
  515.     
  516.     CE_Disable();
  517.     
  518.     return;
  519. }
  520. ////////////////////////////////////////
  521. // 正确返回 1,错误返回 0
  522. int BlockRead(unsigned long nAddr,char pBuf[32][528])
  523. {
  524.     int i,j;
  525.     int n;
  526.     unsigned char nADD1;
  527.     unsigned char nADD2;
  528.     unsigned char nADD3;
  529.     
  530.     nADD1 = nAddr & 0x00ff;
  531.     nADD2 = (nAddr >> 8) & 0x00ff;
  532.     nADD3 = (nAddr >> 16) & 0x00ff;
  533.     
  534.     CE_Enable();
  535.     
  536.     P5DIR = 0xff; // 将P5口设置为输出方向
  537.     for(i = nADD1;i < nADD1 + 32;i++)
  538.     {
  539.      ResetSM();
  540.     
  541.      CLE_Enable();
  542.      WE_Enable();
  543.      P5OUT = 0x00;
  544.      WE_Disable();
  545.      CLE_Disable();
  546.     
  547.      ALE_Enable();
  548.      WE_Enable();
  549.      P5OUT = 0x00;
  550.      WE_Disable();
  551.     
  552.      WE_Enable();
  553.      P5OUT = (unsigned char)(i);
  554.      WE_Disable();
  555.     
  556.      WE_Enable();
  557.      P5OUT = (unsigned char)(nADD2);
  558.      WE_Disable();
  559.     
  560.      WE_Enable();
  561.      P5OUT = (unsigned char)(nADD3);
  562.      WE_Disable();
  563.      ALE_Disable();
  564.     
  565.      //while(!nSM_R_B);
  566.      //nSM_R_B = 0;
  567.      for(n = 100;n > 0;n--);
  568.     
  569.      P5DIR = 0x00; // 将P5口设置为输入方向
  570.      for(j = 0;j < 528;j++)
  571.      {
  572.          RE_Enable();
  573.          pBuf[i][j] = P5IN;
  574.          RE_Disable();
  575.      }
  576.     }
  577.     
  578.     CE_Disable();
  579.     
  580.     
  581.     return 1;
  582. }
  583. ////////////////////////////////////////
  584. // 正确返回 1,错误返回 0
  585. int CopyToFlash(unsigned long nAddr)
  586. {
  587.     return 1;
  588. }
  589. ////////////////////////////////////////
  590. // 正确返回 1,错误返回 0
  591. int RealTimeBadMark(unsigned long nAddr)
  592. {
  593.     int i;
  594.     int rg_stat;
  595.     for(i = 0;i < 32;i++)
  596.     {
  597.      rg_stat = WriteByte(0x50,5,nAddr + i,0x00f0);
  598.      //printf("rg_stat = %x i = %d",rg_stat,i);
  599.      if((rg_stat & 0x01) != 0) return 0;
  600.     }
  601.     
  602.     ResetSM();
  603.     return 1;
  604. }
  605. int main(void)
  606. {
  607.     unsigned long nAddr;
  608.     int j;
  609.     int n;
  610.     int nTemp;
  611.     char pBuf0[528];
  612.     char pBuf1[528];
  613.     int nCount_Err;
  614.     int nLen;
  615.     // 关闭看门狗
  616.     WDTCTL = WDTPW + WDTHOLD;   
  617.     // 关闭中断
  618.     _DINT();                   
  619.     
  620.     // 初始化
  621.     Init_CLK();
  622.     SM_Port_Init();
  623.     // 打开中断
  624.     _EINT();                
  625.     
  626.     // 擦除块地址为1024的块
  627.     nAddr = 1024;
  628.     BlockErase(nAddr);
  629.     // 延迟一点时间
  630.     for(j = 1000;j > 0;j--) ;
  631.     // 判断擦除的块是否为0xFF,起始页地址为1024
  632.     for(j = 0;j < 528;j++) pBuf0[j] = j;
  633.     // 按页写入数据,地址为:1024
  634.     PageWrite(0,1024,pBuf0);
  635.     // 延迟一点时间
  636.     for(j = 1000;j > 0;j--) ;
  637.     //按页读操作
  638.     PageRead(0,1024,pBuf1);
  639.     //比较读出数据和写入数据是否相等
  640.     nCount_Err = 0;
  641.     for(j = 0;j < 528;j++)
  642.     {
  643.      if(pBuf0[j] != pBuf1[j])
  644.      {
  645.          nCount_Err += 1;
  646.          break;
  647.      }    
  648.     }
  649.     
  650.     return 0;
  651. }
  652. void Init_CLK(void)
  653. {
  654.     unsigned int i;
  655.     BCSCTL1 = 0X00; //将寄存器的内容清零
  656. //XT2震荡器开启
  657. //LFTX1工作在低频模式
  658. //ACLK的分频因子为1
  659.     do 
  660.     {
  661. IFG1 &= ~OFIFG;                       // 清除OSCFault标志
  662. for (i = 0x20; i > 0; i--);                
  663.     }
  664.     while ((IFG1 & OFIFG) == OFIFG);      // 如果OSCFault =1   
  665.     BCSCTL2 = 0X00; //将寄存器的内容清零
  666.     BCSCTL2 += SELM1; //MCLK的时钟源为TX2CLK,分频因子为1
  667.     BCSCTL2 += SELS; //SMCLK的时钟源为TX2CLK,分频因子为1
  668. }