打印

关于断电延时和EEPROM数据保存(申酷!!)

[复制链接]
7013|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
neng10128|  楼主 | 2009-2-6 11:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
原来想用AD检测断电的,做出来测试几遍不行,听了各位的意见。
就花了一个下午完成用一个I/O断电检测电路。把法拉电容改小了,节约开支,一个2200uf的普通电容就足够了。经测试能正常保存数据到EEPROM。

电路见下面的图片链接。

该解决方案的程序:
#include <stc12c2052ad.H>
#include <intrins.h>   //汇编头文件
#define uchar unsigned char 
#define uint unsigned int 
sbit p12 = P1^2;
uchar i;

void delay(uint z)     //延时ms
{
    uint x,y;
    for(x=112;x>0;x--)
        for(y=z;y>0;y--);
}

void init_232(void)     //串口初始化
{
    SCON = 0x50;
    TMOD |= 0x20;
    TH1 = 0xfa;         //波特率 9600
    TL1 = 0xfa;
    PCON |= 0x80;
    EA = 1;
    ES = 1;
    TR1 = 1;
}

void send_char(uchar w)       //串口发送一个字符
{
    SBUF = w;
    while(TI == 0);
    TI = 0;
}

void send_string(uchar *s,uint string_length)  //串口发送一个字符串
{
    uint i = 0;
    do
        {
        send_char(*(s + i));
        i++;     
        }
    while(i < string_length);
}

/*EEPROM字符读取*/
uchar eeprom_read(uchar x,y)
{
    ISP_ADDRH = x;
    ISP_ADDRL = y;
    ISP_CONTR = 0x9b;
    ISP_CMD = 0x01;
    ISP_TRIG = 0x46;
    ISP_TRIG = 0xb9;
    _nop_();
    ISP_CONTR=0; 
    ISP_CMD=0;     
    ISP_TRIG=0;    
    return(ISP_DATA);
}

/*EEPROM字符写入*/
void eeprom_write(uchar x,y,z)
{
    ISP_DATA = z;
    ISP_ADDRH = x;
    ISP_ADDRL = y;
    ISP_CONTR = 0x9b;
    ISP_CMD = 0x02;
    ISP_TRIG = 0x46;
    ISP_TRIG = 0xb9;
    _nop_();
    ISP_CONTR=0; 
    ISP_CMD=0;     
    ISP_TRIG=0;    
}

/*EEPROM扇区擦除*/
void eeprom_erase(uchar x,y)
{
    ISP_ADDRH = x;
    ISP_ADDRL = y;
    ISP_CONTR = 0x9b;
    ISP_CMD = 0x03;
    ISP_TRIG = 0x46;
    ISP_TRIG = 0xb9;
    _nop_();
    ISP_CONTR=0; 
    ISP_CMD=0;     
    ISP_TRIG=0;    
}



void main()
{
    init_232();
    i = 0;
    delay(10);
    while(1)
    {
        if((p12 == 0) && (i == 0))
        {
            eeprom_erase(0x10,0x00);        //擦除第一扇区
            delay(1);
            eeprom_write(0x10,0x00,0x88);    //在第一扇区写入88
            delay(1);
            i = 1;
        }  

    }

}


/*串口接收中断函数*/
void RS232() interrupt 4
{
    uchar ch = 0;
    if(RI)
    {
        ch = SBUF;
        RI = 0;    
        send_char(ch);
    }
    switch(ch)
    {
        case 1: send_char(eeprom_read(0x10,0x00));    //串口助手输入16进制1,读EEPROM第一扇区
                break;
        case 2: send_char(eeprom_read(0x12,0x00));    //串口助手输入16进制2,读EEPROM第2扇区
                break;
        case 3: eeprom_write(0x10,0x00,0x55);        //串口助手输入16进制3,写EEPROM第一扇区55
                break;
        case 4: eeprom_write(0x12,0x00,0x66);        //串口助手输入16进制4,写EEPROM第2扇区66
                break;
        case 5: eeprom_erase(0x10,0x00);            //串口助手输入16进制5,擦除EEPROM第一扇区
                break;
        case 6: eeprom_erase(0x12,0x00);            //串口助手输入16进制6,擦除EEPROM第2扇区
                break;

        default: break;
    }
}

相关链接:http://p13.freep.cn/p.aspx?u=v20_p13_p_0902071545521220_0.jpg

相关帖子

沙发
jonsencool| | 2009-2-6 11:33 | 只看该作者

用IO直接测

用IO直接测,在硬件上改一下,和过零检测一样

使用特权

评论回复
板凳
neng10128|  楼主 | 2009-2-6 11:35 | 只看该作者

re jonsencool

本人后生初学,大侠能说说具体方法吗?

使用特权

评论回复
地板
hotpower| | 2009-2-6 12:41 | 只看该作者

应该用电压比较器

使用特权

评论回复
5
ayb_ice| | 2009-2-6 12:48 | 只看该作者

这些和硬件,软件有关

使用特权

评论回复
6
coldra| | 2009-2-6 12:50 | 只看该作者

AD的参考电压怎么取的?

使用特权

评论回复
7
lyjian| | 2009-2-6 13:04 | 只看该作者

AD的参考电压使用了VCC吧?

VCC下降时AD的参考电压同样下降,AD采样的数据根本就不会变。(例如VCC=5V是和VCC=4V时AD采集的数据都是一样的。)
ADout=Vin/Vref*256(8bit AD)
假设变阻器的分压比为K,则Vin=K*VCC,如果Vref=VCC,则ADout=K*256。
AD输出和VCC没任何关系(如果AD使用VCC作为参考的话)。

使用特权

评论回复
8
hotpower| | 2009-2-6 23:02 | 只看该作者

法拉电容在掉电时电压迅速回落在某1电压值,故要切断输出I

使用特权

评论回复
9
neng10128|  楼主 | 2009-2-7 10:24 | 只看该作者

回楼上各位大侠

断电后,AD采样值能慢慢变大,说明单片机还在工作啊!能工作却不能存数据到EEPROM,这是很奇怪的。如果我用按键识别的话就能保存,说明EEPROM是正常的。
这件事情没道理啊!

使用特权

评论回复
10
lyjian| | 2009-2-7 16:03 | 只看该作者

明显就是应为AD使用了VCC作为参考

使用特权

评论回复
11
neng10128|  楼主 | 2009-2-7 16:07 | 只看该作者

回楼上

回楼上,假设我AD采用VCC参考,那么我拔掉电源后,AD值怎么会慢慢变大。。。。。。

使用特权

评论回复
12
lyjian| | 2009-2-7 16:31 | 只看该作者

STC12C2052AD本来就只能用VCC做AD参考

使用特权

评论回复
13
neng10128|  楼主 | 2009-2-7 16:40 | 只看该作者

TO 楼上

AD_DATA = 256 * Vin / VCC
VCC是死的,Vin是活的。随便改变一个AD_DATA就会改变了。
我一开始是设计的断电后电容放电,VCC慢慢变小,Vin保持不变。AD_DATA就会变大。检测到变大后就保存数据。尝试了很多次不行,就改成I/O口检测,能正常保存了。

使用特权

评论回复
14
kbgyzp| | 2009-2-7 23:02 | 只看该作者

掉电保护你没考虑电压波动吗?

如果电压处于波动或震荡时怎么办?难道你不停的的存数据吗?

使用特权

评论回复
15
洪七公| | 2009-2-8 00:42 | 只看该作者

断电EEPROM数据保存这个问题实际很简单,也是技巧问题~~~

因为法拉电容只为MCU和EEPROM掉电时供电,而外设掉电后将无电能。
故可在写EEPROM时先读取外设的某一特定数据,
例读外部RAM的某一特定地址的特定数据0x55aa.
若读错误,测认为系统已掉电~~~

若读出为0x55aa,则认为在法拉电容能**的时间内肯定能
正确地读写EEPROM~~~

使用特权

评论回复
16
洪七公| | 2009-2-8 01:29 | 只看该作者

关于利用“无形资源”捕捉掉电及断电EEPROM数据保存问题

楼主的图是一种方法,但俺认为不太完美~~~

一般232器件都是2路而实际只用1路,那么另一路可以作为232芯片接入测试
及外围掉电检测。

方法是将另一路232芯片的TTL电平端入接地,232电平端出借接232电平端入
即自环,最后再经此TTL电平端出接MCU的某一IO,如图的P1.2

正常时VCC可使232芯片输出TTL低电平到P1.2,即未掉电且232芯片工作正常。
当外围掉电后,232芯片的VCC回落至0V,那么P1.2也将上升为VDD(<VCC)

若P1.2刚跳变至高,由于法拉电容维持VDD>VCC,故可读写EEPROM.

实际产品中也可从任何外设读取特定数据的方法来“曲线检测掉电”~~~

方法太多,只要多动脑即可~~~

使用特权

评论回复
17
guanqiong| | 2013-4-27 21:52 | 只看该作者
楼主可否单独发个电路图给我呢?我下载不了,我的QQ502610528,发我邮箱也行,谢谢啦

使用特权

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

本版积分规则

4

主题

16

帖子

0

粉丝