在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 10072|回复: 21

急,求助,单片机操 作 NAND flash 擦 除 的 问 题 ( 含源代码 )

[复制链接]
发表于 2008-12-23 09:05:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
我现在用的nand flash是三星的K9K8G08U0A,通过单片机的GPIO口与之连接、进行控制,我想通过单片机直接对flash的全部地址进行擦除操作,但不成功,发现只擦除了一部分,大部分的内容没有被擦除,还有一个现象是每次擦除时失败的块数是一定的,即对每片8192个块擦除时反应的擦除失败的块数每次都是一样的,感觉好像是地址的问题,也不知道具体原因在哪里,请各位帮忙看一下代码,是否有什么错误,谢谢。
  另外,如果谁有现成的代码,能否将有关擦除的部分发给我一份作为参考呢,再次谢谢!我的邮箱是
jyarmy@163.com
  我的单片机的型号是Luminary的LM3S3749,共有60路GPIO,flash的控制信号(ALE,CLE,WE,RE,WP,R/B)、片选信号及8路IO全部连接到单片机的GPIO口上。
  一共使用了8片K9K8G08U0A,控制信号和IO信号全部共用,8路片选分别接到MCU的GPIO E口上,从PE0到PE7;GPIO A的PA2接RE,PA3接WE,PA4接R/B,PA5接WP,PA6接CLE,PA7接ALE;GPIO D的PD0到PD7分别与IO0到IO7连接。下面是代码:


/*
写命令.
cmd_char : 命令字符
*/
void cmd_send(unsigned char cmd_char)
{
/*
  0   1   1   x   0   1   0   0 = 0x64
ALE CLE WP# R/B WE# RE#
PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 */
GPIOPinWrite(PA, Pin7 | Pin6 | Pin5 | Pin3 | Pin2 , 0x64); //CLE=1,ALE=0,准备写命令

GPIOPinWrite(PD, Pin0 | Pin1 | Pin2 | Pin3 | Pin4 | Pin5 | Pin6 | Pin7 , cmd_char);// 把命令写入IO
SysCtlDelay(1);//may be
GPIOPinWrite(PA, Pin3, (1<<3));//拉高WE#
SysCtlDelay(1);   
GPIOPinWrite(PA, Pin6, 0x0);//CLE置低   
}

/*擦除一个block
ulAddr:32位的地址 其中A18~A30起作用 ; CEx=0,1,2...7 片先信号
成功返回0 失败返回1   */
unsigned char block_erase(unsigned long ulAddr, int CEx)
{
long result=0;
unsigned char ucAddr=( ulAddr >> 12 );//A12~A19
unsigned long pins[8]={ Pin0, Pin1, Pin2, Pin3, Pin4, Pin5, Pin6, Pin7 };

/* 初始化:
  0   0   1   x   1   1   0   0 = 0x2C
ALE CLE WP# R/B WE# RE#
PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 */
GPIOPinWrite(PA, Pin7 | Pin6 | Pin5 | Pin3 | Pin2 ,0x2C);
  
GPIOPinWrite(PE, pins[CEx] , 0x0);   //拉低CE#
SysCtlDelay(3);
  
cmd_send(0x60);//发送0x60命令   
// SysCtlDelay(1);
  
/* 写地址:
  1   0   1   x   0   1   0   0 = 0xA4   
ALE CLE WP# R/B WE# RE#
PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 */   
GPIOPinWrite(PA, Pin7 | Pin6 | Pin5 | Pin3 | Pin2 , 0xA4); //CLE=0,ALE=1,准备写地址
GPIOPinWrite(PD, Pin0 | Pin1 | Pin2 | Pin3 | Pin4 | Pin5 | Pin6 | Pin7 , ucAddr); //A12~A19
SysCtlDelay(1);
GPIOPinWrite(PA, Pin3, (1<<3));//拉高WE#
SysCtlDelay(1);
GPIOPinWrite(PA, Pin3, (0<<3));//拉低WE#
SysCtlDelay(1);
ucAddr=(ulAddr >> 20);
GPIOPinWrite(PD, Pin0 | Pin1 | Pin2 | Pin3 | Pin4 | Pin5 | Pin6 | Pin7 , ucAddr); //A20~A27
SysCtlDelay(1);
GPIOPinWrite(PA, Pin3, (1<<3));//拉高WE#
SysCtlDelay(1);
GPIOPinWrite(PA, Pin3, (0<<3));//拉低WE#
SysCtlDelay(1);
ucAddr=(ulAddr >> 28);
GPIOPinWrite(PD, Pin0 | Pin1 | Pin2 | Pin3 | Pin4 | Pin5 | Pin6 | Pin7 , ucAddr); //A28~A30
SysCtlDelay(1);
GPIOPinWrite(PA, Pin3, (1<<3));//拉高WE#
SysCtlDelay(1);
  
cmd_send(0xD0);//写命令0xD0   
SysCtlDelay(4);// 应大于TWB 6大约为120ns
  
// GPIOPinWrite(PA, Pin6, 0x0);//CLE置低
  
while( result!= 0x10) //读R/B , 等待其变为高电平
  result=GPIOPinRead(PA,Pin4);
  
cmd_send(0x70);//发送0x70命令,准备读   
SysCtlDelay(5);// 应大于TWHR==60ns
  
/* 准备读:
  0   0   1   x   1   1   0   0 = 0x3C
ALE CLE WP# R/B WE# RE#
PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 */
GPIOPinWrite(PA, Pin7 | Pin6 | Pin5 | Pin3 | Pin2 , 0x3C); //CLE=0,ALE=0
GPIOPinWrite(PA, Pin2, 0x0);// RE# 置低
  
GPIOPinTypeGPIOInput( PD, Pin0 ) ; //PD0即IO0 置为输入
if( 0x00==GPIOPinRead(PD,Pin0))
  ucAddr=0;//擦除成功
else
  ucAddr=1;//擦除失败
GPIOPinWrite(PA, Pin2, 0xFF);//RE# 置高   
GPIOPinTypeGPIOOutput( PD, Pin0 ) ;// PD0置为输出
  
GPIOPinWrite(PE, pins[CEx] , 0xFF); //CE#置高
SysCtlDelay(5);
  
return ucAddr;
}

//将flash复位
//CEx=0,1,2...,7 表示片选信号
void flash_reset(int CEx)
{
  unsigned long result=0;
  /* 初始化:
    0   0   1   x   1   1   0   0 = 0x2C
  ALE CLE WP# R/B WE# RE#
  PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 */
  GPIOPinWrite(PA, Pin7 | Pin6 | Pin5 | Pin3 | Pin2 ,0x2C);
   
  GPIOPinWrite(PE, (0x00000001 << CEx) , 0x0);
  SysCtlDelay(3);
  cmd_send(0xFF);//reset command

  SysCtlDelay(3);
   
  while( result!= 0x10) //读R/B , 等待其变为高电平
    result=GPIOPinRead(PA,Pin4);
   
  GPIOPinWrite(PE, (0x00000001 << CEx) , 0xFF);
  SysCtlDelay(3);
}


// 对8片flash进行擦除
int main(void)
{
unsigned short i,j;
unsigned long block_addr;
unsigned char result;
int good, bad, totle;
//使能GPIO端口
SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA );
SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD );
SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOE );
  
SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOF );//control port PF4 PF5 PF6
//置相应GPIO端口为输入输出
GPIOPinTypeGPIOOutput( PA, Pin2 | Pin3 | Pin5 | Pin6 | Pin7 ); //PA2 3 4 5 6 7
GPIOPinTypeGPIOInput(PA, Pin4);//PA4为输入   
GPIOPinTypeGPIOOutput( PE, Pin0 | Pin1 | Pin2 | Pin3 | Pin4 | Pin5 | Pin6 | Pin7 ) ;// PE0~7 as CE#
GPIOPinTypeGPIOOutput( PD, Pin0 | Pin1 | Pin2 | Pin3 | Pin4 | Pin5 | Pin6 | Pin7 ) ;// PD0~7 as I/O
GPIOPinTypeGPIOOutput( PF, Pin4 | Pin5 | Pin6 );//PF4 5 6

SysCtlDelay(8000000);

  

GPIOPinWrite(PE, Pin0 | Pin1 | Pin2 | Pin3 | Pin4 | Pin5 | Pin6 | Pin7, 0xFF);//片选先全置高
for(j=0;j<8;j++){
      block_addr=0x0;
      good=0; bad=0;
      flash_reset(j);
      for(i=0;i<8192;i++){     
        result=block_erase( block_addr, j );
        if(result==0)
        good++;
        else
        bad++;   
        block_addr += 0x40000;
      }
    SysCtlDelay(2);
    totle=good+bad;   
}
}
发表于 2008-12-23 09:20:17 | 显示全部楼层

经过验证的代码,希望可以帮助你

经过验证的代码,希望可以帮助你

//------------------------------------------------------------------------

#ifndef __K9F1208_H_
#define    __K9F1208_H_  
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include <C8051F200.h>                 // SFR declarations
#include <stdio.h>
#include <string.h>
#include <intrins.h>

#define uchar unsigned char
#define uint  unsigned  int

sbit rRB  = P2^7;
sbit rRE  = P3^0;
sbit rCE  = P3^1;
sbit rCLE = P3^2;
sbit rALE = P3^3;
sbit rWE  = P3^4;
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
#define PORT1_MODE_REG    PRT1CF
#define PORT2_MODE_REG    PRT2CF
#define PORT3_MODE_REG    PRT3CF

#define PORTMODE_OUTPUT    0XFF
#define PORTMODE_INPUT    0X00

extern    volatile uchar xdata g_cFlashPagebuf[512];
extern    volatile uchar idata g_cFlashSparebuf[16];

extern    volatile uchar idata g_cFlashID[4];
extern    volatile uchar idata g_cFlashAddr[4];
extern    volatile uchar data g_cFlashStatus;

#define PAGE_SIZE        (512+16)
#define PAGES_PER_BLOCK    (32)
#define BLOCK_SIZE        (PAGE_SIZE*PAGES_PER_BLOCK)
#define TOTAL_BLOCKS    (4096)
#define TOTAL_PAGES        (TOTAL_BLOCKS*PAGES_PER_BLOCK)
//---------------------------------------------------------------------------------------------------------------------------
// NOTE : 1. The 00h command defines starting address of the 1st half of registers.
//           The 01h command defines starting address of the 2nd half of registers.
//           After data access on the 2nd half of register by the 01h command, the status pointer is
//           automatically moved to the 1st half register(00h) on the next cycle.
//        2. Page Program(True) and Copy-Back Program(True) are available on 1 plane operation.
//           Page Program(Dummy) and Copy-Back Program(Dummy) are available on the 2nd,3rd,4th plane of multi plane operation.
//        3. The 71h command should be used for read status of Multi Plane operation.
//           Caution : Any undefined command inputs are prohibited except for above command set of Table 1.
// Function                   1st Cycle     2nd Cycle     3rd Cycle     Acceptable Command during Busy
// Read 1                          00h/01h(1)  -                -
// Read 2                          50h         -                -
// Read ID                         90h         -                -
// Reset                           FFh         -                -           O
// Page Program (True  2)          80h         10h                -
// Page Program (Dummy  2)         80h         11h                -
// Copy-Back Program(True  2)    00h         8Ah                10h
// Copy-Back Program(Dummy 2)    03h         8Ah                11h
// Block Erase                    60h         D0h                -
// Multi-Plane Block Erase         60h---60h   D0h                -
// Read Status                    70h         -                -           O
// Read Multi-Plane Status         71h(3)        -                -           O
//---------------------------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------
//
//------------------------------------------------------------------
extern    void NOP(uint x);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
extern    void FLASH_Reset(void);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
extern    void FLASH_Read_ID(void);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
extern    uchar FLASH_Read_Status(void);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Write_Cmd(uchar cmd);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Write_Addr(uchar cnt);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Write_Data(uchar x);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
extern    void FLASH_Read_Page(unsigned long int blockno,uchar pageno);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
extern    void FLASH_Write_Page(unsigned long int blockno,uchar pageno);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
extern    void FLASH_Erase_Blocks(unsigned long int blockno);
//------------------------------------------------------------------
//
//------------------------------------------------------------------
extern    void FLASH_Erase_Chip(void);

#endif
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------



//----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include "K9F1208.h"

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
volatile uchar xdata g_cFlashPagebuf[512];
volatile uchar idata g_cFlashSparebuf[16];

volatile uchar idata g_cFlashID[4];
volatile uchar idata g_cFlashAddr[4];
volatile uchar data g_cFlashStatus;

//---------------------------------------------------------------------------------------------------------------------------
// NOTE : 1. The 00h command defines starting address of the 1st half of registers.
//           The 01h command defines starting address of the 2nd half of registers.
//           After data access on the 2nd half of register by the 01h command, the status pointer is
//           automatically moved to the 1st half register(00h) on the next cycle.
//        2. Page Program(True) and Copy-Back Program(True) are available on 1 plane operation.
//           Page Program(Dummy) and Copy-Back Program(Dummy) are available on the 2nd,3rd,4th plane of multi plane operation.
//        3. The 71h command should be used for read status of Multi Plane operation.
//           Caution : Any undefined command inputs are prohibited except for above command set of Table 1.
// Function                   1st Cycle     2nd Cycle     3rd Cycle     Acceptable Command during Busy
// Read 1                          00h/01h(1)  -                -
// Read 2                          50h         -                -
// Read ID                         90h         -                -
// Reset                           FFh         -                -           O
// Page Program (True  2)          80h         10h                -
// Page Program (Dummy  2)         80h         11h                -
// Copy-Back Program(True  2)    00h         8Ah                10h
// Copy-Back Program(Dummy 2)    03h         8Ah                11h
// Block Erase                    60h         D0h                -
// Multi-Plane Block Erase         60h---60h   D0h                -
// Read Status                    70h         -                -           O
// Read Multi-Plane Status         71h(3)        -                -           O
//---------------------------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------
//
//------------------------------------------------------------------
void NOP(uint x)
{
    while(x--);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Reset(void)
{
    rCE     = 0;
    rCLE     = 0;
    rALE     = 0;
    rWE     = 1;
    rRE     = 1;
//-----------------------
    P1         = 0XFF;
    rCLE     = 1;
    rWE        = 0;
    rWE        = 1;
    rCLE     = 0;
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Read_ID(void)
{
    uchar data i;

    P1        = 0X90;
    rCLE     = 1;
    rWE        = 0;
    rWE        = 1;
    rCLE     = 0;

    P1        = 0X00;
    rALE     = 1;
    rWE        = 0;
    rWE        = 1;
    rALE     = 0;

    PORT1_MODE_REG = PORTMODE_INPUT;

    for(i = 0 ; i < 4 ; i++)
    {
        P1                 = 0XFF;
        rRE                = 0;
        g_cFlashID     = P1;
        rRE                = 1;
    }

    PORT1_MODE_REG = PORTMODE_OUTPUT;
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
uchar FLASH_Read_Status(void)
{
/*
    PORT1_MODE_REG = PORTMODE_OUTPUT;

       P1        = 0X70;
    rCLE     = 1;
    rWE        = 0;
    rWE        = 1;
    rCLE     = 0;

    PORT1_MODE_REG = PORTMODE_INPUT;

    P1                 = 0XFF;
    rRE                = 0;
    g_cFlashStatus     = P1;
    rRE                = 1;
   
    return(g_cFlashStatus);
*/
    uchar data res;

    PORT1_MODE_REG = PORTMODE_INPUT;
   
    P1     = 0xFF;
    rRE = 0;
    res = P1;
    rRE = 1;

    PORT1_MODE_REG = PORTMODE_OUTPUT;

    return(res);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Write_Cmd(uchar cmd)
{
    P1         = cmd;
    rCLE     = 1;
    rWE     = 0;
    rWE     = 1;
    rCLE     = 0;
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Write_Addr(uchar cnt)
{
    uchar data i;

    rALE     = 1;

    for (i = cnt; i != 0; i--)
    {
        P1     = g_cFlashAddr[cnt-i];
        rWE = 0;
        rWE = 1;
    }

    rALE     = 0;
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Write_Data(uchar x)
{
    P1     = x;
    rWE = 0;
    rWE = 1;
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Read_Page(unsigned long int blockno,uchar pageno)
{
    uint data i;

    unsigned long int data U32temp = (blockno << 5) + pageno;

    g_cFlashAddr[0] = 0;
    g_cFlashAddr[1] = (U32temp >> 0)  & 0X000000FF;
    g_cFlashAddr[2] = (U32temp >> 8)  & 0X000000FF;
    g_cFlashAddr[3] = (U32temp >> 16) & 0X000000FF;

    FLASH_Write_Cmd(0X00);
    FLASH_Write_Addr(4);

    rRB = 1;
    while (rRB == 0);

    for (i = 0; i < 512; i++)
    {
        g_cFlashPagebuf = FLASH_Read_Status();
    }

    for (i = 0; i < 16; i++)
    {
        g_cFlashSparebuf = FLASH_Read_Status();
    }
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Write_Page(unsigned long int blockno,uchar pageno)
{
    uint data i;

    unsigned long int data U32temp = (blockno << 5) + pageno;
   
    g_cFlashAddr[0] = 0;
    g_cFlashAddr[1] = (U32temp >> 0)  & 0X000000FF;
    g_cFlashAddr[2] = (U32temp >> 8)  & 0X000000FF;
    g_cFlashAddr[3] = (U32temp >> 16) & 0X000000FF;
   
    FLASH_Write_Cmd(0X00);
    FLASH_Write_Cmd(0X80);
    FLASH_Write_Addr(4);
   
    for (i = 0; i < 512; i++)
    {
        FLASH_Write_Data(g_cFlashPagebuf);
    }

    for (i = 0; i < 16; i++)
    {
        FLASH_Write_Data(g_cFlashSparebuf);
    }

    FLASH_Write_Cmd(0X10);
   
    rRB = 1;
    while (rRB == 0);

    do
    {
        FLASH_Write_Cmd(0X70);
    }
    while ((FLASH_Read_Status() & 0X41) != 0X40);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Erase_Blocks(unsigned long int blockno)
{
//--- 31     25            14                0  
//---  |      |                |                 |
//---  XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
//--- |- Byte 3-|- Byte 2-|- Byte 1-|- Byte 0-|

    unsigned long int data U32temp = blockno << 5;

    g_cFlashAddr[0] = (U32temp >> 0)  & 0X000000FF;
    g_cFlashAddr[1] = (U32temp >> 8)  & 0X000000FF;
    g_cFlashAddr[2] = (U32temp >> 16) & 0X000000FF;
   
    FLASH_Write_Cmd(0X60);
    FLASH_Write_Addr(3);
    FLASH_Write_Cmd(0XD0);
   
    rRB = 1;
    while (rRB == 0);

    do
    {
        FLASH_Write_Cmd(0X70);
    }
    while ((FLASH_Read_Status() & 0X41) != 0X40);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
void FLASH_Erase_Chip(void)
{
    uint data i;

    for(i = 0 ; i < TOTAL_BLOCKS ; i++)
    {
        FLASH_Erase_Blocks(i);
    }
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

K9F1208.rar

2.6 KB, 下载次数: 68 , 下载积分: 资产 -2 信元, 下载支出 2 信元

头像被屏蔽
发表于 2008-12-23 11:20:35 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
发表于 2009-1-23 00:08:20 | 显示全部楼层
顶你!
头像被屏蔽
发表于 2009-1-24 09:41:47 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
发表于 2009-2-1 22:14:08 | 显示全部楼层

我也有成功的

只是公司不允发,大多数是时序出了问题
发表于 2009-3-4 15:59:17 | 显示全部楼层
学习一下!
发表于 2009-10-25 19:34:00 | 显示全部楼层
不错,学习了!
发表于 2009-11-1 07:51:14 | 显示全部楼层
二楼好人啊
发表于 2009-12-27 12:39:42 | 显示全部楼层
顶三楼,谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2025-2-9 00:13 , Processed in 0.049302 second(s), 12 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表