搜索
bottom↓
回复: 13

MEGA128外扩flash AT29C020/W29c020读写程序(已测试 GCCAVR CVAVR)

[复制链接]

出0入0汤圆

发表于 2010-3-24 12:05:17 | 显示全部楼层 |阅读模式
#include"mega128.h"
#include"delay.h"
#define SetBit(Port,N)  (Port|=(1<<N))    //设置IO某一位
#define ClrBit(Port,N)  (Port&=~(1<<N))   //清空IO某一位
#define ReverBit(Port,N)  (Port^=(1<<N))   //取反IO某一位
#define GetBit(Pin,N)   ((Pin>>N)&0x01)   //读取IO某一位

#define U2X0  1
#define UPE0  2
#define DOR0  3
#define FE0   4
#define UDRE0 5
#define RXC0  7   
#define High_A17    PORTD.7
#define High_A16    PORTD.6
#define ext_sram_add1 (*(volatile unsigned char *)0x5555)
#define ext_sram_add2 (*(volatile unsigned char *)0x2aaa)
#define ext_sram_add3 (*(volatile unsigned char *)0x1100)
//#define ext_sram_add(i) (*(volatile unsigned char *)i)
//unsigned char ext_sram_add @0x1200;    //外部FLASH的起始地址
//unsigned char *p=&ext_sram_add;        //定义一个指针指向外部FLASH的起始地址
unsigned char data[20]={1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1};  //作为写入FLASH测试用的
unsigned char rec_buf[128];  //作为读出数据的缓冲
/**************************************************
                 usart0初始化
**************************************************/
void USART0_Init(void)
{
        UCSR0A=0x20; //波特率不加倍,单机通信模式
        //UCSR0A=0x22; //波特率加倍,单机通信模式
        UCSR0B=0x18; //中断不使能,允许发送和接收
        UCSR0C=0x06;//异步模式,无校验,8位数据,1位停止位
        //UCSR0C=0x36;//异步模式,odd奇校验,8位数据,1位停止位
        UBRR0H=0x00;
        //UBRR0L=47;//9600波特率 晶振7.3728
        UBRR0L=95;//9600波特率   晶振14.7456
}
/**************************************************
                 串口发送一个字节
**************************************************/
void USART0_SendByte(unsigned char data)
{
        while(!(UCSR0A&(1<<UDRE0)));  //等待发送缓冲空
        UDR0=data;    //发送数据
}
/**************************************************************
        向W29C020某一个扇区(128B)写数据 一共2的11次方2048个
        扇区,参数high,low是最高地址线A17,A16
        注意:地址范围为0x001100到0x11ffff,超出界限,结果不定,
        比如第一扇区的的地址范围为0x001100~0x001180,第二扇区的地址为
        0x001200~0x001280
        前11位为页地址,后面7为某一页的字节地址
**************************************************************/   
void Write_W29(unsigned char high ,unsigned char low,unsigned int addr,unsigned char len,unsigned char *dat)
{  
    unsigned char ii,byte_add;
    unsigned int  sect;
    unsigned char buf[128];
    unsigned char *ptr;
    sect=addr-addr%128;   
    ptr=(unsigned char*)sect;   
    High_A17=high;        
    High_A16=low;             //获取扇区地址  
    for (ii=0;ii<128;ii++)  //写之前先读出128字节的变量
    {  
        buf[ii]=*ptr;
        ptr++;
    }   
    ptr=(unsigned char*)sect;  //指针返回到扇区首地址
    byte_add=addr%128;         //原先数据的字节末地址
    ext_sram_add1=0xaa;
    ext_sram_add2=0x55;
    ext_sram_add1=0xa0;     //软件保护模式下写数据到W29C020
    for (ii=0;ii<byte_add;ii++)    //写入原先不需要变化的数据
    {  
       *ptr=buf[ii];
       ptr++;     
    }   
    ptr=(unsigned char*)(sect+byte_add);  //指针指向需要改变信息的首地址
    for (ii=0;ii<len;ii++)               //写入len字节长度的需要变化的数据
    {   
        *ptr=dat[ii];
        ptr++;
    }
   delay_ms(10);                             //延时10MS等待写操作完成
}   
/**************************************************************
        读W29C020某一个扇区的len长度的数据
        参数说明同写函数
**************************************************************/   
void Read_W29(unsigned char high ,unsigned char low,unsigned int addr,unsigned char len,unsigned char *buf)
{  
    unsigned char ii;
    unsigned char *ptr;  
    ptr=(unsigned char*)addr;   
    High_A17=high;        
    High_A16=low;             //获取扇区地址  
    for (ii=0;ii<len;ii++)  
    {  
        buf[ii]=*ptr;
        ptr++;
    }          
}   
/**************************************************
                 主函数
**************************************************/
void main(void)
{   
    unsigned char i=0;
        USART0_Init();  //初始化USART0接口  
        MCUCR=0x80;     //使能外部SRAM
    XMCRA=0x00;
        DDRE=0xff;
        DDRD=0xff;
        PORTD=0x00;      //使能 CS A16 A17 =11
        SetBit(PORTE,2); //程序启动蜂鸣器响50MS
        delay_ms(500.0);
        ClrBit(PORTE,2); //关蜂鸣器  
        /*ext_sram_add1=0xaa;
        ext_sram_add2=0x55;
        ext_sram_add1=0x80;
        ext_sram_add1=0xaa;
        ext_sram_add2=0x55;
        ext_sram_add1=0x60;  
        delay_us(15);   
        PORTD=0xc0;
        USART0_SendByte( ext_sram_add3);
        ext_sram_add1=0xaa;
        ext_sram_add2=0x55;
        ext_sram_add1=0xf0;
        delay_us(15);  */                 //测试返回W29C020的ID
               
        //Write_W29(0,0,0x1220,0x20,data);     //下数据到W29C020
        //delay_ms(200);  
        //PORTD=0xc0;
        //p=&ext_sram_add;
        Read_W29(0,0,0x1200,128,rec_buf);
        for(i=0;i<128;i++)               //通过串口发送读出的20字节FLASH数据
    {
                  USART0_SendByte(rec_buf);   
        }  
           while(1)
           {            
             ReverBit(PORTE,3);
                 delay_ms(500);//LED每隔500ms闪烁一次               
           }
}
——————————————————————————————————
基于CVAVR编译器

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2010-3-24 12:06:17 | 显示全部楼层
#include"avr/io.h"
#include"avr/interrupt.h"
#include"util/delay.h"
#define SetBit(Port,N)  (Port|=(1<<N))    //设置IO某一位
#define ClrBit(Port,N)  (Port&=~(1<<N))   //清空IO某一位
#define ReverBit(Port,N)  (Port^=(1<<N))   //取反IO某一位
#define GetBit(Pin,N)   ((Pin>>N)&0x01)   //读取IO某一位

#define U2X0  1
#define UPE0  2
#define DOR0  3
#define FE0   4
#define UDRE0 5
#define RXC0  7   
#define ext_sram_add1 (*(volatile unsigned char *)0x5555)
#define ext_sram_add2 (*(volatile unsigned char *)0x2aaa)
#define ext_sram_add3 (*(volatile unsigned char *)0x1100)
//#define ext_sram_add(i) (*(volatile unsigned char *)i)
//unsigned char ext_sram_add @0x1200;    //外部FLASH的起始地址
//unsigned char *p=&ext_sram_add;        //定义一个指针指向外部FLASH的起始地址
unsigned char data[128]= {1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1,
                                                  1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1,
                                                  1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1,
                                                  1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1,
                                                  1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1,
                                                  1,2,3,4,5,6,7,8,9,10,10,9,8,7,6,5,4,3,2,1,
                                                  1,2,3,4,5,6,7,8};  //作为写入FLASH测试用的
unsigned char data1[128]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x7e,0xe7,0x7e,0xe7,0xaa,
                                                  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x7e,0xe7,0x7e,0xe7,0xaa,
                                                  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x7e,0xe7,0x7e,0xe7,0xaa,
                                                  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x7e,0xe7,0x7e,0xe7,0xaa,
                                                  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x7e,0xe7,0x7e,0xe7,0xaa,
                                                  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x7e,0xe7,0x7e,0xe7,0xaa,
                                                  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};

unsigned char rec_buf[128];  //作为读出数据的缓冲
unsigned char rec_buf1[128];  //作为读出数据的缓冲
/**************************************************
                 usart0初始化
**************************************************/
void USART0_Init(void)
{
        UCSR0A=0x20; //波特率不加倍,单机通信模式
        //UCSR0A=0x22; //波特率加倍,单机通信模式
        UCSR0B=0x18; //中断不使能,允许发送和接收
        UCSR0C=0x06;//异步模式,无校验,8位数据,1位停止位
        //UCSR0C=0x36;//异步模式,odd奇校验,8位数据,1位停止位
        UBRR0H=0x00;
        //UBRR0L=47;//9600波特率 晶振7.3728
        UBRR0L=95;//9600波特率   晶振14.7456
}
/**************************************************
                 串口发送一个字节
**************************************************/
void USART0_SendByte(unsigned char data)
{
        while(!(UCSR0A&(1<<UDRE0)));  //等待发送缓冲空
        UDR0=data;    //发送数据
}
/**************************************************************
        向W29C020某一个扇区(128B)写数据 一共2的11次方2048个
        扇区,参数high,low是最高地址线A17,A16
        注意:地址范围为0x001100到0x11ffff,超出界限,结果不定,
        比如第一扇区的的地址范围为0x001100~0x001180,第二扇区的地址为
        0x001200~0x001280
        前11位为页地址,后面7为某一页的字节地址
**************************************************************/   
void Write_W29(unsigned char high ,unsigned char low,unsigned int addr,unsigned char len,unsigned char *dat)
{  
    unsigned char ii,byte_add;
    unsigned int  sect;
    unsigned char buf[128];
    unsigned char *ptr;
    sect=addr-addr%128;   
    ptr=(unsigned char*)sect;  
        if(high==0x01)
        {
                SetBit(PORTD,7);       
        }
        else
        {
                ClrBit(PORTD,7);
        }
    if(low==0x01)
        {
                SetBit(PORTD,6);       
        }
        else
        {
                ClrBit(PORTD,6);
        }                       //获取扇区地址  
    for (ii=0;ii<128;ii++)  //写之前先读出128字节的变量
    {  
        buf[ii]=*ptr;
        ptr++;
    }   
    ptr=(unsigned char*)sect;  //指针返回到扇区首地址
    byte_add=addr%128;         //原先数据的字节末地址
    ext_sram_add1=0xaa;
    ext_sram_add2=0x55;
    ext_sram_add1=0xa0;     //软件保护模式下写数据到W29C020
    for (ii=0;ii<byte_add;ii++)    //写入原先不需要变化的数据
    {  
       *ptr=buf[ii];
       ptr++;     
    }   
    ptr=(unsigned char*)(sect+byte_add);  //指针指向需要改变信息的首地址
    for (ii=0;ii<len;ii++)               //写入len字节长度的需要变化的数据
    {   
        *ptr=dat[ii];
        ptr++;
    }
    _delay_ms(10);                             //延时10MS等待写操作完成
}   
/**************************************************************
        读W29C020某一个扇区的len长度的数据
        参数说明同写函数
**************************************************************/   
void Read_W29(unsigned char high ,unsigned char low,unsigned int addr,unsigned char len,unsigned char *buf)
{  
    unsigned char ii;
    unsigned char *ptr;  
    ptr=(unsigned char*)addr;   
    if(high==0x01)
        {
                SetBit(PORTD,7);       
        }
        else
        {
                ClrBit(PORTD,7);
        }
    if(low==0x01)
        {
                SetBit(PORTD,6);       
        }
        else
        {
                ClrBit(PORTD,6);
        }                       //获取扇区地址  
    for (ii=0;ii<len;ii++)  
    {  
        buf[ii]=*ptr;
        ptr++;
    }          
}   
/**************************************************
                 主函数
**************************************************/
int main(void)
{   
    unsigned char i=0;
        USART0_Init();  //初始化USART0接口  
        MCUCR=0x80;     //使能外部SRAM
    XMCRA=0x00;
        DDRE=0xff;
        DDRD=0xff;
        PORTD=0x00;      //使能 CS A16 A17 =11
        SetBit(PORTE,2); //程序启动蜂鸣器响50MS
        _delay_ms(500.0);
        ClrBit(PORTE,2); //关蜂鸣器  
        /*ext_sram_add1=0xaa;
        ext_sram_add2=0x55;
        ext_sram_add1=0x80;
        ext_sram_add1=0xaa;
        ext_sram_add2=0x55;
        ext_sram_add1=0x60;  
        delay_us(15);   
        PORTD=0xc0;
        USART0_SendByte( ext_sram_add3);
        ext_sram_add1=0xaa;
        ext_sram_add2=0x55;
        ext_sram_add1=0xf0;
        delay_us(15);  */                 //测试返回W29C020的ID
               
        //Write_W29(0,0,0x1100,128,data);     //下数据到W29C020
    //Write_W29(0,0,0x1180,128,data1);
        _delay_ms(200);  
        //PORTD=0xc0;
        //p=&ext_sram_add;
        Read_W29(0,0,0x1100,128,rec_buf);
    Read_W29(0,0,0x1180,128,rec_buf1);
        for(i=0;i<128;i++)               //通过串口发送读出的20字节FLASH数据
    {
                  USART0_SendByte(rec_buf);   
        }
        for(i=0;i<128;i++)              
    {
                  USART0_SendByte(rec_buf1);   
        }  
           while(1)
           {            
             ReverBit(PORTE,3);
                 _delay_ms(500);//LED每隔500ms闪烁一次               
           }
}

————————————————————————————————-
基于GCCAVR编译器的

出0入0汤圆

发表于 2010-3-24 12:42:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-24 12:49:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-24 13:15:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-24 13:22:23 | 显示全部楼层
谢谢分享。

出0入0汤圆

发表于 2010-9-25 16:34:35 | 显示全部楼层
正需要,不过M32该怎么用?

出0入0汤圆

发表于 2010-9-25 18:32:14 | 显示全部楼层
感谢分享!!

出0入0汤圆

 楼主| 发表于 2010-9-26 23:19:04 | 显示全部楼层
回复【6楼】root_007
正需要,不过m32该怎么用?
-----------------------------------------------------------------------

M32有总线吗?有的话 是一样 ,没有的话需要模拟

出0入0汤圆

发表于 2010-9-26 23:45:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-11 11:20:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-11 12:50:19 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2011-2-24 16:41:18 | 显示全部楼层
mark

出0入0汤圆

发表于 2014-2-21 10:50:52 | 显示全部楼层
谢谢 楼主分享 正好需要  好吧 我觉得我可能挖坟了0.0
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 17:28

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表