打印

这样使用EEPROM可行吗?怎么我调用时候没反应。。。

[复制链接]
3401|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
laocuo1142|  楼主 | 2014-8-5 10:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*函数功能:延时1ms*/
void delay1ms()
{
    unsigned char i,j;
        for(i=0;i<10;i++)
                for(j=0;j<33;j++)
                            ;
}
/*函数功能:延时若干秒,入口参数:n*/
void delay (unsigned char n)
{
    unsigned char i;
    for (i=0;i<n;i++)
    delay1ms();
}
/***********************************************************

EEPROM设置:把采集周期、温度门限、系列号写入
            
***********************************************************/
/*关闭IAP功能,使MCU进入安全模式*/
void IAP_Disable()
{
        IAP_CONTR=0;                        //关闭IAP功能
        IAP_CMD=0;                          //清命令寄存器,使寄存器无命令
        IAP_TRIG=0;                         //清触发寄存器,使触发寄存器无触发
        IAP_ADDRH=0x80;                     //数据指针指向non-EEPROM地方
        IAP_ADDRL=0;                        //清IAP地址防止被误用
}
/*从EEPROM中读一个字节,入口参数:addr,出口参数:Flash data*/
BYTE IapReadByte(WORD addr)
{
        BYTE dat;
        IAP_CONTR=ENABLE_IAP;               //打开IAP功能,设置flash操作等待时间
        IAP_CMD=CMD_READ;                   //IAP/ISP/EEPROM字节读命令
        IAP_ADDRH=addr;                     //设置目标单元位置的高8位地址
        IAP_ADDRL=addr>>8;                  //设置目标单元位置的低8位地址
        IAP_TRIG=0x5a;                      //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此搜索
        IAP_TRIG=0xa5;                      //送完A5h 后,ISP/IAP 命令立即被触发起动
        _nop_();
        dat=IAP_DATA;
        IAP_Disable();
    return dat;       
}
/*写入字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据*/
void IapProgramByte(WORD addr,BYTE dat)
{
    IAP_CONTR=ENABLE_IAP;               //打开 IAP 功能, 设置Flash 操作等待时间
    IAP_CMD=CMD_PROGRAM;                //IAP/ISP/EEPROM 字节编程命令
    IAP_ADDRL=addr;                     //设置目标单元地址的高8 位地址
    IAP_ADDRH=addr>>8;                  //设置目标单元地址的低8 位地址
    IAP_DATA=dat;                       //要编程的数据先送进IAP_DATA 寄存器
    IAP_TRIG=0X5A;                      //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG=0XA5;                      //送完A5h 后,ISP/IAP 命令立即被触发起动
    _nop_();
    IAP_Disable();                      //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态
}
/*擦除扇区, 入口:DPTR = 扇区地址*/
void IapEraseSector(WORD addr)
{
    IAP_CONTR=ENABLE_IAP;               //打开 IAP 功能, 设置Flash 操作等待时间
    IAP_CMD=CMD_ERASE;                  //IAP/ISP/EEPROM 扇区擦除命令
    IAP_ADDRL=addr;                     //设置目标单元地址的高8 位地址
    IAP_ADDRH=addr>>8;                  //设置目标单元地址的低8 位地址
    IAP_TRIG=0X5A;                      //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG=0XA5;                      //送完A5h 后,ISP/IAP 命令立即被触发起动
    _nop_();
    IAP_Disable();                      //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态
}
/*把采集周期、温度门限、系列号写入1,2,3号扇区*/
void SheZhiCanShu()
{       
    IapEraseSector(IAP_ADDRESS1);
    delay(10);
    IapProgramByte(0x0000,0xAA);
        IapProgramByte(0x0002,0x01);
    IapProgramByte(0x0004,0x00);
        IapProgramByte(0x0006,0x0A);
    IapProgramByte(0x0008,0x00);
        IapProgramByte(0x000A,0x01);                     
}
/*把采集周期、温度门限、系列号读出*/
void DuChuCanShu()
{
    if(IapReadByte(0x0000)==0xAA)
    {
            TxTime=IapReadByte(0x0002);
            TempH=IapReadByte(0x0004);
        TempL=IapReadByte(0x0006);
            addrH=IapReadByte(0x0008);
            addrL=IapReadByte(0x000A);
    }
    else
    {
        SheZhiCanShu();
    }
}

相关帖子

沙发
ningling_21| | 2014-8-5 10:57 | 只看该作者
照资料里的例程抄下来差不多都可以...

使用特权

评论回复
板凳
laocuo1142|  楼主 | 2014-8-5 11:01 | 只看该作者
ningling_21 发表于 2014-8-5 10:57
照资料里的例程抄下来差不多都可以...

读写的原程序是按例程抄的,但是下面的应用是自己写的,能不能这么操作?

使用特权

评论回复
地板
八步电影网| | 2014-8-5 11:05 | 只看该作者
前排占位支持了,嘿嘿

使用特权

评论回复
5
ningling_21| | 2014-8-5 11:21 | 只看该作者
laocuo1142 发表于 2014-8-5 11:01
读写的原程序是按例程抄的,但是下面的应用是自己写的,能不能这么操作? ...

可以这样操作
_nop_(); 可以多加几个,注意IAP空间的地址和芯片型号对应关系...

使用特权

评论回复
6
laocuo1142|  楼主 | 2014-8-5 11:34 | 只看该作者
ningling_21 发表于 2014-8-5 11:21
可以这样操作
_nop_(); 可以多加几个,注意IAP空间的地址和芯片型号对应关系... ...

按你说的,我加了_nop_();,但是串口调试助手回应,我的输出还是FF,没有按照我的值输出,怎么回事!!!

使用特权

评论回复
7
ningling_21| | 2014-8-5 12:31 | 只看该作者
laocuo1142 发表于 2014-8-5 11:34
按你说的,我加了_nop_();,但是串口调试助手回应,我的输出还是FF,没有按照我的值输出,怎么回事!!! ...

什么芯片型号?

使用特权

评论回复
8
laocuo1142|  楼主 | 2014-8-5 13:22 | 只看该作者
ningling_21 发表于 2014-8-5 12:31
什么芯片型号?

STC11L32XE

使用特权

评论回复
9
rszhao| | 2014-8-5 14:04 | 只看该作者
你设置的问题 还有看看你的电压是否正常 这个料读写EEPROM 是没有问题的 我用过

使用特权

评论回复
10
junle| | 2014-8-5 14:18 | 只看该作者
对IAP_TRIG先写入46在写入b9 ;把a5和5a换掉,STC12系列是这样!如果不行再看看datasheet!

使用特权

评论回复
11
laocuo1142|  楼主 | 2014-8-5 15:03 | 只看该作者
junle 发表于 2014-8-5 14:18
对IAP_TRIG先写入46在写入b9 ;把a5和5a换掉,STC12系列是这样!如果不行再看看datasheet! ...

好像是STC11系列,我读了芯片手册,这个A5和5A好像是没问题的,写入了怎么感觉没反应

使用特权

评论回复
12
laocuo1142|  楼主 | 2014-8-5 15:07 | 只看该作者
ningling_21 发表于 2014-8-5 12:31
什么芯片型号?

EEPROM的读写数据,在主程序里面怎么操作?我可能是这里没搞清楚把
void main()
{
    delay(50);
    RE=0;
        UartInit();
        delay(10);
    T0_init();
    delay(10);
        SheZhiCanShu();
    delay(10);
    DuChuCanShu();

使用特权

评论回复
13
junle| | 2014-8-5 15:18 | 只看该作者
laocuo1142 发表于 2014-8-5 15:03
好像是STC11系列,我读了芯片手册,这个A5和5A好像是没问题的,写入了怎么感觉没反应 ...

STC11系列我没用过只能根据其他类型芯片给你建议最好还是看看datasheet!

使用特权

评论回复
14
ningling_21| | 2014-8-5 15:26 | 只看该作者
本帖最后由 ningling_21 于 2014-8-5 15:28 编辑
laocuo1142 发表于 2014-8-5 15:07
EEPROM的读写数据,在主程序里面怎么操作?我可能是这里没搞清楚把
void main()
{

初始化时读取判断一次,之后就需要时再读取或写入...

例如:
main()
{
     x= read_51_eep(0x0000);
     if(x!=0xaa)
     {
         erase_sector(0x0000);
         wr_51_eep(0x0000,0xaa);
}

    while(1)
    {
   .............
}
}

使用特权

评论回复
15
ningling_21| | 2014-8-5 15:30 | 只看该作者
laocuo1142 发表于 2014-8-5 15:03
好像是STC11系列,我读了芯片手册,这个A5和5A好像是没问题的,写入了怎么感觉没反应 ...

看看头文件中 寄存器定义对不对。。。

sfr IAP_DATA  = 0xC2;              //ISP/IAP Flash数据寄存器
sfr IAP_ADDRH = 0xC3;             //ISP/IAP Flash地址高字节
sfr IAP_ADDRL = 0xC4;             //ISP/IAP Flash地址低字节           IAP_ADDH
sfr IAP_CMD   = 0xC5;             //ISP/IAP Flash命令寄存器
sfr IAP_TRIG  = 0xC6;              //ISP/IAP Flash命令触发器
sfr IAP_CONTR = 0xC7;             //ISP/IAP控制寄存器

使用特权

评论回复
16
laocuo1142|  楼主 | 2014-8-5 15:46 | 只看该作者
ningling_21 发表于 2014-8-5 15:30
看看头文件中 寄存器定义对不对。。。

sfr IAP_DATA  = 0xC2;              //ISP/IAP Flash数据寄存器

#include<reg51.h>
#include<intrins.h>

#define SomeNop();{_nop_();_nop_();}
#define INC(x,y) if(++x>=y) x=0

sbit P0_4=P0^4;

typedef unsigned char BYTE;
typedef unsigned char WORD;
/*声明关联IAP的特殊功能寄存器*/
sfr IAP_DATA=0xc2;
sfr IAP_ADDRH=0xc3;
sfr IAP_ADDRL=0xc4;
sfr IAP_CMD=0xc5;
sfr IAP_TRIG=0xc6;
sfr IAP_CONTR=0xc7;

/*定义ISP/IAP/EEPROM命令*/
#define CMD_IDLE 0;
#define CMD_READ 1;
#define CMD_PROGRAM 2;
#define CMD_ERASE 3;

/*声明串口的特殊功能寄存器*/
sfr AUXR = 0x8E;
sfr AUXR1 = 0xA2;
sfr BRT = 0x9c;

#define ENABLE_IAP 0x83                 //允许IAP,晶振11.0592M<12M,选择3

#define IAP_ADDRESS1 0x0000
#define IAP_ADDRESS2 0x0200
#define IAP_ADDRESS3 0x0400

sbit RE=P3^5;

unsigned int f68,faa;
unsigned char Time1;
unsigned char TempH1,TempL1;
unsigned char addrH1,addrL1;
unsigned char TxTime;
unsigned char TempH,TempL;
unsigned char addrH,addrL;

unsigned char MingLing[64];             //命令储存数组
unsigned char Pwrite=0;                 //命令数组计数
unsigned char Pread=0;

unsigned char HYMingLing[12];           //命令储存数组

unsigned int  f10ms,fuart,u10ms ;       //接收数据标志


//void IapEraseSector(WORD addr);
/************************************************************

延时函数

************************************************************/
/*函数功能:延时1ms*/
void delay1ms()
{
    unsigned char i,j;
        for(i=0;i<10;i++)
                for(j=0;j<33;j++)
                            ;
}
/*函数功能:延时若干秒,入口参数:n*/
void delay (unsigned char n)
{
    unsigned char i;
    for (i=0;i<n;i++)
    delay1ms();
}
/***********************************************************

EEPROM设置:把采集周期、温度门限、系列号写入
            
***********************************************************/
/*关闭IAP功能,使MCU进入安全模式*/
void IAP_Disable()
{
        IAP_CONTR=0;                        //关闭IAP功能
        IAP_CMD=0;                          //清命令寄存器,使寄存器无命令
        IAP_TRIG=0;                         //清触发寄存器,使触发寄存器无触发
        IAP_ADDRH=0x80;                     //数据指针指向non-EEPROM地方
        IAP_ADDRL=0;                        //清IAP地址防止被误用
}
/*从EEPROM中读一个字节,入口参数:addr,出口参数:Flash data*/
BYTE IapReadByte(WORD addr)
{
        BYTE dat;
        IAP_CONTR=ENABLE_IAP;               //打开IAP功能,设置flash操作等待时间
        IAP_CMD=CMD_READ;                   //IAP/ISP/EEPROM字节读命令
        IAP_ADDRH=addr;                     //设置目标单元位置的高8位地址
        IAP_ADDRL=addr>>8;                  //设置目标单元位置的低8位地址
        IAP_TRIG=0x5a;                      //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此搜索
        IAP_TRIG=0xa5;                      //送完A5h 后,ISP/IAP 命令立即被触发起动
        _nop_();
        dat=IAP_DATA;
        IAP_Disable();
    return dat;       
}
/*写入字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据*/
void IapProgramByte(WORD addr,BYTE dat)
{
    IAP_CONTR=ENABLE_IAP;               //打开 IAP 功能, 设置Flash 操作等待时间
    IAP_CMD=CMD_PROGRAM;                //IAP/ISP/EEPROM 字节编程命令
    IAP_ADDRL=addr;                     //设置目标单元地址的高8 位地址
    IAP_ADDRH=addr>>8;                  //设置目标单元地址的低8 位地址
    IAP_DATA=dat;                       //要编程的数据先送进IAP_DATA 寄存器
    IAP_TRIG=0X5A;                      //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG=0XA5;                      //送完A5h 后,ISP/IAP 命令立即被触发起动
    _nop_();
    IAP_Disable();                      //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态
}
/*擦除扇区, 入口:DPTR = 扇区地址*/
void IapEraseSector(WORD addr)
{
    IAP_CONTR=ENABLE_IAP;               //打开 IAP 功能, 设置Flash 操作等待时间
    IAP_CMD=CMD_ERASE;                  //IAP/ISP/EEPROM 扇区擦除命令
    IAP_ADDRL=addr;                     //设置目标单元地址的高8 位地址
    IAP_ADDRH=addr>>8;                  //设置目标单元地址的低8 位地址
    IAP_TRIG=0X5A;                      //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
    IAP_TRIG=0XA5;                      //送完A5h 后,ISP/IAP 命令立即被触发起动
    _nop_();
    IAP_Disable();                      //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态
}
/*把采集周期、温度门限、系列号写入1,2,3号扇区*/
void SheZhiCanShu()
{       
    IapEraseSector(IAP_ADDRESS1);
    delay(10);
    IapProgramByte(0x0000,0xAA);
    _nop_();
        IapProgramByte(0x0002,0x01);
    _nop_();
    IapProgramByte(0x0004,0x00);
    _nop_();
        IapProgramByte(0x0006,0x0A);
    _nop_();
    IapProgramByte(0x0008,0x00);
    _nop_();
        IapProgramByte(0x000A,0x01);
    _nop_();                     
}
/*把采集周期、温度门限、系列号读出*/
void DuChuCanShu()
{
        TxTime=IapReadByte(0x0002);
    _nop_();
        TempH=IapReadByte(0x0004);
    _nop_();
    TempL=IapReadByte(0x0006);
    _nop_();
        addrH=IapReadByte(0x0008);
    _nop_();
        addrL=IapReadByte(0x000A);
    _nop_();


/*    if(Data!=0xAA)
    {
        SheZhiCanShu();
    }*/
}
/************************************************************

定时器T0,普通定时,做数据接收是否完成标志

************************************************************/
/*定时器中断*/
void T0_time(void) interrupt 1
{
   TF0=0;
   TR0=0;                               //关中断
   --u10ms;
   if(u10ms==0)
   {
     f10ms=1;
   }
   TH0=0xfe;                            //重新赋初值
   TL0=0x0b;
   TR0=1;                               //开中断   
}
/*定时器初始化*/
void T0_init()
{
   TMOD=0x01;                            //设置定时器0为工作方式1
   TH0=0xfe;                             //重装初始值(65535-500)=65035=0xfe0b
   TL0=0x0b;
   ET0=1;                                //允许定时中断
   TR0=0;                                //启动定时中断
}
/************************************************************

485通信

************************************************************/
/*485串口初始化,独立波特率*/
void UartInit(void)                                //9600bps@11.0592MHz
{
        PCON &= 0x7f;                                //波特率不倍速
        SCON = 0x50;                                //8位数据,可变波特率
        BRT = 0xFD;                                    //设定独立波特率发生器重装值
        AUXR &= 0xfb;                                //独立波特率发生器时钟为Fosc/12,即12T
        AUXR |= 0x01;                                //串口1选择独立波特率发生器为波特率发生器
        AUXR |= 0x10;                                //启动独立波特率发生器
    AUXR1=0x80;                         //串口P1
    ES=1;
//    EA=1;
}
/*485串口中断程序*/
void USART_TI(void) interrupt 4
{
   
    if(RI==1)
    {
      RI=0;
      MingLing[Pwrite]=SBUF;            //把命令保存在数组里
      INC(Pwrite,64);                   //防止数组溢出
      if(MingLing[0]==0x68)
      {
          f68=1;
      }
      else
      {
          Pwrite=0;
      }
    }
}
/*命令解析,并进行相对应的回应*/
void JieXiMingLing()
{
    unsigned int i;
    unsigned char CRC=0;
    if(Pwrite>=6)
    {
        if(f68==1)                          //命令首字节为0x68,否则无效
        {
                if(MingLing[1]==0x77)           //地址查询命令
                {
                        if((MingLing[2]==0x00)&&(MingLing[3]==0x00)&&(MingLing[4]==0xdf)&&(MingLing[5]==0x0d))
                        {
                    HYMingLing[0]=0x77;
                    HYMingLing[1]=0x68;
                    HYMingLing[2]=addrH;
                    HYMingLing[3]=addrL;
                    HYMingLing[4]=0x0d;
                    RE=1;
                                 for(i=0;i<5;i++)
                                    {
                                         SBUF=HYMingLing;     //查询地址回应
                                           while(!TI);
                                        TI=0;                          
                                 }
                    RE=0;
                    Pwrite=0;
                    Pread=0;
                        }
               
            }     
        }
    }       
}

/***************************************************************

主函数

***************************************************************/
void main()
{
//    unsigned int i;
    unsigned char Data;
    delay(50);
    RE=0;
        UartInit();
        delay(10);
    T0_init();
    delay(10);       
        EA=1;                               //打开总中断
    Data=IapReadByte(0x0000);
    if(Data!=0xAA)
    {
        SheZhiCanShu();
    }

        while(1)
        {
        DuChuCanShu();
                if(Pwrite!=Pread)
              {
                  Pread=Pwrite;
                  TR0=1;
                  u10ms=2;
                  f10ms=0;
                  fuart=1;
              }
              if((f10ms==1)&&(fuart==1))
                  {
            fuart=0;
                      TR0=0;
                      JieXiMingLing();
                  }       
        }                     
}
看看我完整的程序,应该回应我77 68 00 01 0D,现在回应总是77 68 FF FF 0D,感觉没有读出EEPROM中的数据。

使用特权

评论回复
17
ningling_21| | 2014-8-5 16:05 | 只看该作者
把这段放到初始化部分,测试一下,看看是不是每次加1,上电再断电,再上电测试几次就知道了....

Data =         IapReadByte(0x0000);
        if(        Data==0xff)
        {
                 Data=0;
        }
        else
        {
                 Data++;
        }
        IapProgramByte(0x0000,Data);

        SBUF= Data;
        while(TI==0);
        TI=0;

使用特权

评论回复
18
laocuo1142|  楼主 | 2014-8-5 17:09 | 只看该作者
ningling_21 发表于 2014-8-5 16:05
把这段放到初始化部分,测试一下,看看是不是每次加1,上电再断电,再上电测试几次就知道了....

Data =         I ...

测试了一下,好像只把第一个AA写进去了,后面的都还是FF,这是怎么回事?

使用特权

评论回复
19
ningling_21| | 2014-8-5 17:39 | 只看该作者
laocuo1142 发表于 2014-8-5 17:09
测试了一下,好像只把第一个AA写进去了,后面的都还是FF,这是怎么回事?

有可能是后面的没写进去...

测试写4个字节吗?

使用特权

评论回复
20
laocuo1142|  楼主 | 2014-8-6 08:42 | 只看该作者
ningling_21 发表于 2014-8-5 17:39
有可能是后面的没写进去...

测试写4个字节吗?

我程序上面应该写入了6个字节,现在好像只有第一个写进去了,后面的都还是FF,难道我写入的方法不对?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1181

主题

5171

帖子

12

粉丝