打印
[国产单片机]

STC12C5202AD 串口中断读写EEPROM问题

[复制链接]
3344|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wuqingliang1|  楼主 | 2010-8-24 16:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
各位高手请帮忙:
STC12C5202AD串口中断中调用EEPROM读写函数,再把EEPROM中内容用液晶显示出来,结果没有显示,而单独对EEPROM读写再液晶显示、串口中断程序调试都没问题,哪里的问题呢?
(EEPROM读写前都关了中断的)

部分函数如下:
/*************串口接收中断处理********************/
void UART_Routine(void) interrupt 4
{   
if(RI==1)
{
    RI = 0;
    EEPROM_Bytes_Write(1024,string1,12); // 将字符串写入首地址为0x00的EEPROM连续区域
  EEPROM_Byte_Read(1024,string,12);  // 将首地址为0x00的EEPROM连续区域数据读取存放到sting数组中
// Flag =1 ;
}
    else
  TI = 0;
}

/***********关闭 ISP_IAP 功能,安全防误操作*************/
void ISP_IAP_disable(void)
{
ISP_CONTR = 0x00;    // 禁止ISP_IAP操作
ISP_CMD  =  0x00;    // 去除ISP_IAP命令
ISP_TRIG = 0x00;    // 防止ISP_IAP命令误触发
ISP_ADDRH =  0x0FF;    // 送地址高字节单元为00,指向非EEPROM区
ISP_ADDRL  =  0x0FF;    // 送地址低字节单元为00,防止误操作
EA   =   1;     // 开中断
}
/*********************公用的触发代码********************/
void ISPgoon(void)
{
EA   = 0;     // 关中断  
ISP_CONTR  = 0x80|WAIT_TIME;  // 开ISP_IAP功能,设置FLASH操作等待时间
ISP_TRIG = 0x5A;
ISP_TRIG = 0xA5;    // 触发ISP_IAP命令
_nop_();
}
/********************************************************************************
功能说明:
  从指定首地址为addr的EEPROM区域读出size字节数据到buf指向的区域内,并返回实际读
出数据的字节数                                    *
********************************************************************************/
uint EEPROM_Byte_Read(uint addr, uchar *buf, const uint size)
{
uchar *p_buf;
uint  i, current_size;

p_buf = buf;
current_size = 0;
ISP_CMD = ISP_IAP_BYTE_READ;    // 读字节命令
for (i = 0; i < size; i++)
{
  if ((addr < EEPROM_ADDR_START) || (addr > EEPROM_ADDR_END))
  {
   break;      //地址越界检测
  }   
  ISP_ADDRH = addr>>8;   // 地址赋值
  ISP_ADDRL = addr&0x00ff;
  ISPgoon();      // 触发执行
  *p_buf = ISP_DATA;  
  addr++;
  p_buf++;
  current_size++;
}
        
ISP_IAP_disable();     // 关闭ISP_IAP功能
return (current_size);    // 返回读到数据的字节数
}
/********************************************************************************
功能说明:                  
把buf指向单元内的数据写入地址为addr的EEPROM单元内,成功返回1,或则返回0                      *
********************************************************************************/
BOOL EEPROM_Byte_Write(uint addr, uchar *buf)
{
ISP_CMD = ISP_IAP_BYTE_PROGRAM;  // 字节编程命令
if ((addr < EEPROM_ADDR_START) || (addr > EEPROM_ADDR_END))
{
  return 0;
}
ISP_ADDRH = addr>>8;    // 地址赋值
ISP_ADDRL = addr&0x00ff;
   
ISP_DATA = (*buf);     // 写入数据准备
ISPgoon();       // 触发执行
ISP_IAP_disable();     // 关闭ISP_IAP功能   
return 1;
}
/********************************************************************************
功能说明:擦除AddrInSector地址所在的整个扇区         
********************************************************************************/
void Erase_Sector(uint AddrInSector)
{
ISP_CMD = ISP_IAP_SECTOR_ERASE;  // 扇区擦除命令

ISP_ADDRH = AddrInSector>>8;
ISP_ADDRL = AddrInSector&0x00ff; // 地址赋值
ISPgoon();       // 触发执行
ISP_IAP_disable();     // 关闭ISP_IAP功能   
}
/********************************************************************************
功能说明:                 
从首地址为src扇区单元拷贝连续size字节数据到首地址为des的连续扇区单元内,并返
回实际拷贝的字节数                  
********************************************************************************/
uint CopySector(uint src, uint des, const uint size)
{
uchar temp;
uint current_size, i;
current_size = 0;
for (i = 0; i < size; i++)
{
  if (!EEPROM_Byte_Read(src, &temp, 1))
  {
   break;
  }
  if (!EEPROM_Byte_Write(des, &temp))
  {
   break;
  }
  des++;
  src++;
  current_size++;  
}
return  current_size;
}
/********************************************************************************
功能说明:                 
把buf指向区域内的size字节数据写入首地址为addr的EEPROM连续区域,并返回实际写入
数据的字节数                      *
********************************************************************************/
uint EEPROM_Bytes_Write(uint addr, uchar *buf, const uint size)
{
uchar *p_buf, temp, move;

uint i, bufaddr, current_size, cur_sector_start_addr;

p_buf = buf;

move = 0;
current_size = 0;

for (i = 0; i < size; i++)
{
  if (!EEPROM_Byte_Read(addr, &temp, 1))
  {
   break;
  }
  if (temp == 0xff)
  {
   EEPROM_Byte_Write(addr, p_buf);
  }
  else         // 发现第一个单元不是0xff,要重新写入数据需要擦除整个扇区         
  {
   Erase_Sector(EEPROM_ADDR_END);  // 擦除用作缓冲的这个扇区
   cur_sector_start_addr = addr&0xfe00;
   CopySector(cur_sector_start_addr
      , (EEPROM_ADDR_END + 1 - BYTES_EACH_SECTOR)
      , (addr - cur_sector_start_addr));
   bufaddr = (addr - cur_sector_start_addr)    // 把第一个非0xff单元前的数据拷贝到缓冲扇区
     + (EEPROM_ADDR_END + 1 - BYTES_EACH_SECTOR); // 计算剩余需要存储的数据需写入缓冲扇区的首个单元地址
   for (  ; i < size; i++)         // 把剩余要存储的数据写入缓冲扇区
   {
    EEPROM_Byte_Write(bufaddr, p_buf);
    addr++;
    bufaddr++;
    p_buf++;
    current_size++;
   }
   if (addr < cur_sector_start_addr + USEING_EACH_SECTOR ) // 把需要改变区域后的数据写入缓冲扇区
   {
    CopySector(addr, bufaddr, USEING_EACH_SECTOR
       - (addr - cur_sector_start_addr));
   }
   Erase_Sector(cur_sector_start_addr);     // 擦除当前扇区
   move = 1;
   break;
  }
  addr++;
  p_buf++;
  current_size++;
}
if (move)
{
  CopySector((EEPROM_ADDR_END - BYTES_EACH_SECTOR + 1)    // 把缓冲扇区数据拷贝到当前扇区
     , cur_sector_start_addr, USEING_EACH_SECTOR);
}
return current_size;
}

相关帖子

沙发
David_ming| | 2010-8-24 19:53 | 只看该作者
:L这么多.......写个简单的写入操作试试成功不,还有,在中断里写IAP,时间很长的呀。还有如果子程序在主程序里边有调用,那么要声明成可重入函数

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
wuqingliang1 + 1
板凳
ysh5888| | 2010-9-7 19:44 | 只看该作者
操作EEPROM要禁止中断。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
wuqingliang1 + 1
地板
wuqingliang1|  楼主 | 2010-9-8 10:16 | 只看该作者
谢谢各位,问题解决了,对EEPROM处理没问题,是我调用LCD程序时出了问题

使用特权

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

本版积分规则

0

主题

29

帖子

1

粉丝