找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1822|回复: 3
打印 上一主题 下一主题
收起左侧

请教一下大佬们关于IAP15w4k58s4型号单片机比较器的问题

[复制链接]
跳转到指定楼层
楼主
ID:660830 发表于 2019-12-25 15:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
求大佬帮帮忙,我使用的是IAP15w4k58s4单片机,进行掉电保存验证,结果测试比较器没起作用怎么回事,烧录哪里我已经设置了允许低压中断还有允许低压eeprom操作,不知道还有哪里出了问题,感激不尽

#include "STC15W4K.H"
#include "intrins.h"
#include "time_uart.h"
#include <stdio.h>

#define uint unsigned int
#define uchar unsigned char

#define CMD_IDLE        0                 //空闲模式
#define CMD_READ        1                 //IAP字节读命令
#define CMD_PROGRAM        2                 //IAP字节编程命令
#define CMD_ERASE        3                 //IAP扇区擦除命令
#define ENABLE_IAP  0x83         //ifSYSCLK<12MHZ

#define IAP_address                0x0400

//sfr CMPCR1 = 0xE6;                //比较器控制寄存器1
#define CMPEN        0x80        //比较器模块使能
#define CMPIF         0x40        //比较器中断标志位
#define PIE                0x20        //比较器上升沿中断使能位
#define NIE                0x10        //比较器下降沿中断使能位
#define PIS                0x08        //比较器正极选择位
#define NIS                0x04        //比较器负极选择位
#define CMPOE        0x02        //比较器输出控制位
#define CMPRES        0x01        //比较器比较结果位

//sfr        CMPCR2        =0xE7;                //比较器控制寄存器2
#define INVCMPO        0x80        //比较器结果反向输出控制位
#define        DISFLT        0x40        //比较器输出端滤波使能位
#define LCDTY        0x3F        //比较器输出的区抖时间控制
void delayms(uint n);
void iap_idle();
uint iap_readbyte(uint addr);
void iap_writebyte(uint addr,uint dat);
void iap_erase_sector(uint addr);

uint num;

void cmp_iar() interrupt 21 using 1
{
           CMPCR1&=~CMPIF;                           //掉电后触发下降沿中断,向flash写入数据
           iap_erase_sector(0x400);
           iap_writebyte(0x400,num);
}

void main()
{       
        P5M0=0;
        P5M1=0;
       
        P55=1;
        num=9;
        init_uart();
        CMPCR1=0;                        //初始化比较器寄存器1和2
        CMPCR2=0;
       
        CMPCR1&=~PIS;                //选择外部管脚P55 CMP+作为比较器正极输入源
        CMPCR1&=~NIS;                //选择内部BandGap电压作为比较器负极输入源
        CMPCR1&=~CMPOE;                //禁用比较器的比较结果输出
        CMPCR2&=~INVCMPO;        //比较器比较结果正常输出到P12
        CMPCR2&=~DISFLT;        //使能比较器输出端0.1us滤波电路
        CMPCR2&=~LCDTY;                //比较器结果不去抖动直接输出
        //CMPCR1|=PIE;                //使能比较器上升沿中断
        CMPCR1|=NIE;                //使能比较器下降沿中断
       
        CMPCR1|=CMPEN;                //使能比较器
        EA=1;
//        if(iap_readbyte(0x400)!=9)
//                iap_erase_sector(0x400);       

        while(1)
        {
                if(iap_readbyte(0x400)==9)
                {
                //        CMPCR1&=~CMPEN;                //失能比较器

                        while(1)
                        {
                                delayms(1000);
                                SBUF='0';
                                while(!TI);
                                TI=0;
                        }
                }
               
                if(CMPCR1&CMPRES)         //正常状态CMP也就是P55大于BandGap电压,没问题
                {
                        delayms(1000);
                        SBUF='9';
                        while(!TI);
                        TI=0;
                }
                else   //掉电后,我以为可能程序还会走一点,结果中断没进入这里也没进入
                {
                         iap_erase_sector(0x400);
                           iap_writebyte(0x400,num);       
                }               

        }

}

void delayms(uint n)
{
        uint j,k;
        for(j=0;j<n;j++)
                for(k=0;k<111;k++); //时钟频率11.0592MHZ
}

//关闭IAP
void iap_idle()
{
        IAP_CONTR=0;
        IAP_CMD=0;
        IAP_TRIG=0;
        IAP_ADDRH=0x80;
        IAP_ADDRL=0;
}

//从ISP IAP EEPROM区域读取一个字节

uint iap_readbyte(uint addr)
{
        uint dat;

        IAP_CONTR=ENABLE_IAP;
        IAP_CMD=CMD_READ;
        IAP_ADDRL=addr;
        IAP_ADDRH=addr>>8;
        IAP_TRIG=0x5A;
        IAP_TRIG=0xA5;
        _nop_();
        dat=IAP_DATA;
        iap_idle();

        return dat;
}

//写一字节数据到ISP IAP EEPROM区域
void iap_writebyte(uint addr,uint dat)
{
        IAP_CONTR=ENABLE_IAP;
        IAP_CMD=CMD_PROGRAM;
        IAP_ADDRL=addr;
        IAP_ADDRH=addr>>8;
        IAP_DATA=dat;
        IAP_TRIG=0x5A;
        IAP_TRIG=0xA5;
        _nop_();
        iap_idle();
}

//扇区擦去
void iap_erase_sector(uint addr)
{
          IAP_CONTR=ENABLE_IAP;
        IAP_CMD=CMD_ERASE;
        IAP_ADDRL=addr;
        IAP_ADDRH=addr>>8;
        IAP_TRIG=0x5A;
        IAP_TRIG=0xA5;
        _nop_();
        iap_idle();
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:401564 发表于 2019-12-25 16:30 | 只看该作者
STC的电压比较器的使用方法太反人类了,要设定一大堆寄存器,而且,输出结果并不是单纯的+-两个端口的电压大小关系,太扯了
掉电保存的话,还是用外部中断吧,如果中断不够用,那就直接检测某个端口的电平状态吧,反正都比电压比较器好使
回复

使用道具 举报

板凳
ID:660830 发表于 2019-12-25 19:20 | 只看该作者
我直接通过杜邦线拉低P55能进入中段,说明比较器可以用,而现在问题是我验证用的单片机是最小系统的板子,是不是这个比较器需要外部电路才可实现,之前我是直接断电验证的,我以为本身芯片里面就会配置有啥的,这样就断电后还可以运行一小会这样
回复

使用道具 举报

地板
ID:213173 发表于 2019-12-25 21:11 | 只看该作者
掉电保存需要外部硬件支持。最简单的方法是供MCU的VCC有足够大的电容,当检测到外部掉电时,立即把相关数据保存在EEPROM中。一般维持1~2秒VCC无明显下降,足可以保存1000个字节。并不是楼主认为的利用低压检测功能来完成此项工作。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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