找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5980|回复: 30
收起左侧

怎么把STC89C52RC单片机程式改成STC8F2K08S2的,而且要有断电记忆?

  [复制链接]
ID:468169 发表于 2019-1-15 00:32 来自手机 | 显示全部楼层 |阅读模式
500黑币
请帮忙把STC89C52RC52程式改成STC8F2K08S2程式,还有就是我下面的程式EEPROM断电记忆部分没办法记忆,有地方写的不对,请大神帮忙修改下……。
程式如下:
//头函数
#include <reg52.h>
#include<intrins.h>       
#define uint unsigned int
#define uchar unsigned char
#define RdCommand 0x01
#define PrgCommand 0x02                //定义ISP的操作命令
#define EraseCommand 0x03
#define Error 1
#define OK 0
#define WaitTime 0x01   //定义单片机的等待时间
sfr ISP_DATA = 0xe2;     //寄存器申明
sfr ISP_ADDRH=0xe3;
sfr ISP_ADDRL=0xe4;
sfr ISP_CMD=0XE5;
sfr ISP_TRIG=0xe6;
sfr ISP_CONTR=0xe7;
/*========================打开ISP,IAP功能=========================*/
void ISP_IAP_enable(void)
{
EA=0;                                           /*关中断*/
ISP_CONTR=ISP_CONTR & 0x18;                   /*0001,1000*/
ISP_CONTR=ISP_CONTR | WaitTime;           /*写入硬件延时*/
ISP_CONTR=ISP_CONTR | 0x80;         /*ISPEN=1*/

}
/*=============关闭ISP,IAP功能===================*/
void ISP_IAP_disable(void)
{
ISP_CONTR=ISP_CONTR & 0x7f;  /*ISPEN=0*/
ISP_TRIG=0x00;
EA=1;    /*开中断*/
}
/*================公用的触发代码=========*/
void ISPgoon(void)
{
ISP_IAP_enable();  /*打开ISP,IAP功能*/
ISP_TRIG=0x46;
ISP_TRIG=0xb9;
_nop_();
}
/*============字节读=============*/
unsigned char byte_read(unsigned int byte_addr)
{
   ISP_ADDRH=(unsigned char)(byte_addr>>8);  /*地址赋值*/
   ISP_ADDRL=(unsigned char)(byte_addr & 0x00ff);
   ISP_CMD=ISP_CMD & 0xf8;   /*清楚低3位*/
   ISP_CMD=ISP_CMD | RdCommand;   /*写入读指令*/
   ISPgoon();       /*触发执行*/
   ISP_IAP_disable();  /*关闭ISP,IAP功能*/
   return(ISP_DATA);    /*返回读到的数据*/
}
/*======================扇区擦除==================*/
void SectorErase(unsigned int sector_addr)
{
   unsigned int iSectorAddr;
   iSectorAddr=(sector_addr & 0xfe00);    /*区扇区地址*/
   ISP_ADDRH=(unsigned char )(iSectorAddr>>8);
   ISP_ADDRL=0x00;
   ISP_CMD=ISP_CMD&0xf8;   /*清空低3位*/
   ISP_CMD=ISP_CMD | EraseCommand;   /*擦除命令3*/
   ISPgoon();
   ISP_IAP_disable();       /*关闭ISP,IAP功能*/
}
/*===============字节写===============*/
void byte_write(unsigned int byte_addr,unsigned char original_data)
{
   ISP_ADDRH=(unsigned char)(byte_addr>>8);   /*取地址*/
   ISP_ADDRL=(unsigned char)(byte_addr&0x00ff);
   ISP_CMD=ISP_CMD&0xf8;  /*清空低3位*/
   ISP_CMD=ISP_CMD|PrgCommand;   /*写命令2*/
   ISP_DATA=original_data;  /*写入数据准备*/
   ISPgoon();      /*触发执行*/
   ISP_IAP_disable();    /*关闭IAP功能*/
}       
uchar scale1=10;                                   //定义占空比比例,初始是50%
uchar scale=30;                //定义占空比比例,初始是50%
uint Key_num,Key_num1,num2;

bit bdata flag_add_dec=0;        //长按时是加还是减取决于此变量
bit bdata flag_add_dec1=0;        //长按时是加还是减取决于此变量  

//管脚声明
sbit LED = P1^0;        //灯光控制输出 1
sbit K1= P3^6;          //触摸输入
sbit K2= P3^7;
sbit LED1 = P1^1;    //灯光控制输出2
sbit led3 = P1^2;
/*****************延时函数:大约1ms************************/
void delay(uchar i)
{
  uchar j,k;
  for(j=i;j>0;j--)
    for(k=121;k>0;k--);
}

/*********定时器初始化函数**********/
void init()
{
        TMOD=0x11;           //工作方式 1 定时器0,1
        TH0=0xff;
        TL0=0xe7;                //T0赋初值25us
        TH1=0xff;
        TL1=0xe7;
        EA=1;                   //中断总开关          
        ET0=1;                   //打开中断允许开关
        ET1=1;
        TR0=1;                   //打开定时器开关
        TR1=1;
}



/****************主函数**********************/
void main()
{
    uint l;
    uchar num1;

        init();                  //调用初始化函数

         num1=byte_read(0x2003);  //程序开始时读取EEPROM中数据
   if(num1>=20)             //防止首次上电时读取出错
   num1=0;
       
        while(1)                   //循环
        {       
                if(K1==0)        //有触摸信号                                               
                {
                        delay(20);//延时,去抖,除掉干扰信号
                        if(K1==0)        //再次判断有触摸信号
                        {
                                while(!K1)//触摸信号不消失就会在此循环中
                                {       
                                        Key_num++;                   //长按计时变量加
                                        if(Key_num>=100)   //检测到是长按(如果没加到100就退出则执行后面的if(Key_num!=0))
                                        {
                                                Key_num=0;           //清零,执行长按功能
                                                if(TR0==1)           //在灯开着时才可以调节亮度
                                                {         
                                                        while(!K1)                                    //触摸信号一直在,进入循环,进行加减亮度
                                                        {                                                                         

                                                                if(flag_add_dec==0)                  //是加状态
                                                                {        l--;
                                                                        scale++;
                                                                                          //灯光比例++
                                                                        if(scale>=61)          //达到最亮
                                                                        scale=61;                  //保持最亮
                                                                        LED1=~LED;

                                                          

                                                        }               
       
                                                               
                                                               
                                                                else
                                                                {
                                                                           l++;
                                                                        scale--;                   //灯光比例--
                                                                        if(scale<=2)           //达到最暗
                                                                {
                                                                        scale=2;                   //保持最暗
                                                               
                                                                }       
                                                                       
                                                                }


                                                           delay(30);
                                                        }
                                                         
                                                        flag_add_dec=!flag_add_dec;         //执行一次长按后,此变量取反(1变0,0变1)
                                                                 if(num2>=5)
                                                         {
                                                           num2=0;
                                                           num1++;
                                                           SectorErase(0x2000);  //擦除扇区
                                                           byte_write(0x2003,num1);  //重新写入数据
                                                           if(num1==20)
                                                           {
                                                             num1=0;
                                                           }
                                                         }

                                                }
                                        }
                                        delay(2);                  //此延时是调节长按时间的
                                }
                                if(Key_num!=0)                  //如果不是长按按键
                                {
                                        Key_num=0;                  //清零
                                        TR0=~TR0;                  //定时器取反,就是开关定时器,从而开关灯
                                        if(TR0==0)                  //如果是关灯时,将LED输出置高,关闭输出
                                        LED=1;
                                        LED1=1;
                                }       
                        }
       

                }
       
        }
}

/******************定时器T0服务函数:脉冲发生函数*******************/
void time0() interrupt 1
{
        uchar n;
        TH0=0xff;
        TL0=0xe7;                //T0赋初值10us
        n++;                         //每25us  n++
        if(n<scale)                 //n<设置比例时,打开灯
        {          
                        LED=0;  LED1=~LED;
        }
        else if(n>=scale)//n大于等于设置比例时 关闭灯
        {         
                LED=1;    LED1=~LED;
        }
        if(n==60)                 //n==40  :25us*40=1ms   1kHZ
        {
                n=0;                 //n=0
        }
       
}

void time() interrupt 3
{
        TH1=0xff;
        TL1=0xe7;                //T0赋初值12.5us
        num2++;                         //每25us  n++
       
       
}

回复

使用道具 举报

ID:123289 发表于 2019-1-15 07:53 | 显示全部楼层
当你能搞清51原理后,这个不难,只要看一下:【STC89C52RC52】和【STC8F2K08S2】手册,找一下它俩的区别,就OK了。如果你的51基础不行,就麻烦了。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:468169 发表于 2019-1-15 09:55 来自手机 | 显示全部楼层
yzwzfyz 发表于 2019-1-15 07:53
当你能搞清51原理后,这个不难,只要看一下:【STC89C52RC52】和【STC8F2K08S2】手册,找一下它俩的区别, ...

问题是,我现在用52RC的做断电记忆它记忆不了,我都调试很久都没调试出来,想不到好办法了,因为刚接触单片机不久,好多地方没弄懂……。
回复

使用道具 举报

ID:351872 发表于 2019-1-15 11:57 | 显示全部楼层
#include "reg51.h"
#include "intrins.h"

//测试工作频率为11.0592MHz

sfr     IAP_DATA    =   0xC2;
sfr     IAP_ADDRH   =   0xC3;
sfr     IAP_ADDRL   =   0xC4;
sfr     IAP_CMD     =   0xC5;
sfr     IAP_TRIG    =   0xC6;
sfr     IAP_CONTR   =   0xC7;

#define WT_30M          0x80
#define WT_24M          0x81
#define WT_20M          0x82
#define WT_12M          0x83
#define WT_6M           0x84
#define WT_3M           0x85
#define WT_2M           0x86
#define WT_1M           0x87

void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                                //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

char IapRead(int addr)
{
    char dat;

    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 1;                                //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                             //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

void IapProgram(int addr, char dat)
{
    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 2;                                //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                             //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(int addr)
{
    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 3;                                //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}

void main()
{
    IapErase(0x0400);
    P0 = IapRead(0x0400);                       //P0=0xff
    IapProgram(0x0400, 0x12);
    P1 = IapRead(0x0400);                       //P1=0x12

    while (1);
}

这是8F系列断电记忆的例程  你可以学习下。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:250700 发表于 2019-1-15 14:05 | 显示全部楼层
STC系列单片机,断电记忆原理,硬件需要有断电检测电路,STC89C52RC没有自带检测电路可以利用外部中断(在电源电压低到一个阀值、并且要高于EEPROM可以写入电压),若产生中断就 保存 所有需要保存的数据,在单片机上电时读出 上次 保存的数据,STC8F2K08S2 自带低电压中断功能 可以直接 在 低压中断 保存数据,若不考虑 EEPROM 擦写寿命、可以在上电 读出 数据后 擦除 EEPROM的使用扇区,也可以 在扇区中分块使用、一个扇区 多次使用 提高擦写寿命。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:468169 发表于 2019-1-15 15:48 来自手机 | 显示全部楼层
GUELL 发表于 2019-1-15 14:05
STC系列单片机,断电记忆原理,硬件需要有断电检测电路,STC89C52RC没有自带检测电路可以利用外部中断(在 ...

嗯,那有STC8F2K08S2的例程吗,最好有EEPROM这方面的……。
回复

使用道具 举报

ID:142059 发表于 2019-1-16 09:47 | 显示全部楼层
nanyexin 发表于 2019-1-15 09:55
问题是,我现在用52RC的做断电记忆它记忆不了,我都调试很久都没调试出来,想不到好办法了,因为刚接触单 ...

那就是你的eeprom读写不成功,还想什么

评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:468169 发表于 2019-1-16 16:01 来自手机 | 显示全部楼层
Angle145 发表于 2019-1-16 09:47
那就是你的eeprom读写不成功,还想什么

我也知道是读写不成功呀,所以我是想不出来哪里的问题呀,所以才请教大神们呀?
回复

使用道具 举报

ID:468169 发表于 2019-1-23 11:52 来自手机 | 显示全部楼层
5100103 发表于 2019-1-15 11:57
#include "reg51.h"
#include "intrins.h"


你好。我已经把这个EEPROM例程放进我的程式中,断电重启还是没有办法记忆,我现在用的是STC8F2K08S2这款IC。
回复

使用道具 举报

ID:213173 发表于 2019-1-23 16:53 | 显示全部楼层
nanyexin 发表于 2019-1-23 11:52
你好。我已经把这个EEPROM例程放进我的程式中,断电重启还是没有办法记忆,我现在用的是STC8F2K08S2这款I ...

掉电记忆是需要外部硬件支持的,否则单片机没有电源怎么工作?如下图,C2值远大于C1。把写EEPROM的程序放在外部中断里。一旦掉电进入外部中断,由C2维持短暂工作。 无标题.jpg

回复

使用道具 举报

ID:468169 发表于 2019-1-24 09:15 | 显示全部楼层
wulin 发表于 2019-1-23 16:53
掉电记忆是需要外部硬件支持的,否则单片机没有电源怎么工作?如下图,C2值远大于C1。把写EEPROM的程序放 ...

不是可以用計時器萊做計數,每幾秒寫入一次嗎?我現在用的就是這個方法,沒幾秒寫進去一次,但是我按照你說的數據手冊中一樣的EEPROM例程來帶進去裏面一點反應都沒有,是不是不能按照數據手冊的測試例程來做,,,,
回复

使用道具 举报

ID:213173 发表于 2019-1-24 09:58 | 显示全部楼层
nanyexin 发表于 2019-1-24 09:15
不是可以用計時器萊做計數,每幾秒寫入一次嗎?我現在用的就是這個方法,沒幾秒寫進去一次,但是我按照你 ...

看来你的单片机可能已经玩坏了。EEPROM写入次数不是无限的,数据手册称30万次。如果5秒写1次,工作十几天就报废了。正确做法是每次断电写1次。并且轮流使用不同扇区,可以用几十年。
STC官方例程没有问题,参照此例程编写的应用程序用于产品达数千件,无一意外。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:158375 发表于 2019-1-24 10:42 | 显示全部楼层
nanyexin 发表于 2019-1-16 16:01
我也知道是读写不成功呀,所以我是想不出来哪里的问题呀,所以才请教大神们呀?

火气莫要太大!
看来你还是不知道为什么实现掉电记忆。
看12楼,他说的一点没错。
不然,你要使用铁电......

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:468169 发表于 2019-1-24 13:18 | 显示全部楼层
wulin 发表于 2019-1-24 09:58
看来你的单片机可能已经玩坏了。EEPROM写入次数不是无限的,数据手册称30万次。如果5秒写1次,工作十几天 ...

但是我看我公司這裡用的單片機用的也是掉電記憶,他們外圍電路并沒有加大電容,也是可以做斷電記憶,那他們用的是什麽方法呢?所以我猜想是在什麽特定時間寫入的,所以我才用幾秒寫入方法來《《《《

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:468169 发表于 2019-1-24 13:22 | 显示全部楼层
笨笨兔 发表于 2019-1-24 10:42
火气莫要太大!
看来你还是不知道为什么实现掉电记忆。
看12楼,他说的一点没错。

是呀,這是個好方法,但是我看見有很多斷電記憶的單片機并沒有電解電容,那他們爲什麽可以做掉電記憶,我公司就有兩款是這樣子的,單片機外圍電路就只有幾個電阻,一個觸摸腳,一個觸摸腳靈敏度的調節電容.......

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:213173 发表于 2019-1-24 14:24 | 显示全部楼层
nanyexin 发表于 2019-1-24 13:18
但是我看我公司這裡用的單片機用的也是掉電記憶,他們外圍電路并沒有加大電容,也是可以做斷電記憶,那他 ...

我推荐这个方法只是诸多方法之一,不同的芯片可以设计对应的方法,只要在电源电压没有降低到无法写EEPROM之前完成保存数据都是可行的。STC8F2K08S2的最低工作电压2.0V。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:472325 发表于 2019-1-24 16:44 | 显示全部楼层
nanyexin 发表于 2019-1-15 09:55
问题是,我现在用52RC的做断电记忆它记忆不了,我都调试很久都没调试出来,想不到好办法了,因为刚接触单 ...

1.是写不进还是读不出?
2.用一个简单的代码,那怕就用控制P/I口灯来做试验,只要能做到记忆,后面就只是多调试的问题了

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:155507 发表于 2019-1-24 22:17 | 显示全部楼层
楼主,注意下载时,硬件选项中的“设置用户EEPROM大小”要选择你需要的EEPROM大小值,否则会访问不成功的。
解决了是下载配置的问题,把地址改成0x0000就可以了!
回复

使用道具 举报

ID:468169 发表于 2019-1-26 01:23 来自手机 | 显示全部楼层
wulin 发表于 2019-1-23 16:53
掉电记忆是需要外部硬件支持的,否则单片机没有电源怎么工作?如下图,C2值远大于C1。把写EEPROM的程序放 ...

如果用大电容那个外部中断该怎的设置呢?我有写了个普通的0和1LED灯它是可以记忆的,但是我换到单键做无极调光里面就记忆不了,想用大电容控制写入,但是调试了挺久都不行……。
回复

使用道具 举报

ID:213173 发表于 2019-1-26 10:32 | 显示全部楼层
nanyexin 发表于 2019-1-26 01:23
如果用大电容那个外部中断该怎的设置呢?我有写了个普通的0和1LED灯它是可以记忆的,但是我换到单键做无 ...

硬件连接示意图
无标题.jpg


//基于STC8F2K64S4,测试工作频率为11.0592MHz
//此程序使用外部中断1(INT1),也可以选择:
//比较器中断(CMP),低压检测中断(LVD)
//注:此程序未经实物验证,只是提供编程思路
#include <STC8.H>
//#include "reg51.h"
#include "intrins.h"
#define uint unsigned int
#define uchar unsigned char
sbit key1=P3^4;       
sbit key2=P3^5;       
sbit LED=P1^7;
uchar num=0x00;
//        关闭IAP功能
void IapIdle()
{
    IAP_CONTR = 0;             //关闭IAP功能
    IAP_CMD = 0;               //清除命令寄存器
    IAP_TRIG = 0;              //清除触发寄存器
    IAP_ADDRH = 0x80;          //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}
//从ISP/IAP/EEPROM区域读取一字节
uchar IapRead(uint addr)
{
    uchar dat;
    IAP_CONTR = 0x83;          //使能IAP
    IAP_CMD = 1;               //设置IAP读命令
    IAP_ADDRL = addr;          //设置IAP低地址
    IAP_ADDRH = addr >> 8;     //设置IAP高地址
    IAP_TRIG = 0x5a;           //写触发命令(0x5a)
    IAP_TRIG = 0xa5;           //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;            //读IAP数据
    IapIdle();                 //关闭IAP功能
    return dat;
}
//写一字节数据到ISP/IAP/EEPROM区域
void IapProgram(uint addr, uchar dat)
{
    IAP_CONTR = 0x83;          //使能IAP
    IAP_CMD = 2;               //设置IAP写命令
    IAP_ADDRL = addr;          //设置IAP低地址
    IAP_ADDRH = addr >> 8;     //设置IAP高地址
    IAP_DATA = dat;            //写IAP数据
    IAP_TRIG = 0x5a;           //写触发命令(0x5a)
    IAP_TRIG = 0xa5;           //写触发命令(0xa5)
    _nop_();
    IapIdle();                 //关闭IAP功能
}
//        ISP/IAP/EEPROM扇区擦除
void IapErase(uint addr)
{
    IAP_CONTR = 0x83;          //使能IAP
    IAP_CMD = 3;               //设置IAP擦除命令
    IAP_ADDRL = addr;          //设置IAP低地址
    IAP_ADDRH = addr >> 8;     //设置IAP高地址
    IAP_TRIG = 0x5a;           //写触发命令(0x5a)
    IAP_TRIG = 0xa5;           //写触发命令(0xa5)
    _nop_();
    IapIdle();                 //关闭IAP功能
}
//初始化PWM
void PWM_Init()
{
        CCON = 0;                   //初始化PCA控制寄存器
        CL = 0;                     //复位PCA寄存器
        CH = 0;
        CMOD = 0x02;                //设置PCA时钟源,PWM频率=11.0592MHZ/2/256=21.600KHZ
        PCA_PWM0 = 0x00;            //PCA模块0工作于8位PWM
        CCAP0H = CCAP0L = 0x80;     //PWM0的占空比为50%
        CCAPM0 = 0x42;              //PCA模块0为8位PWM模式
        CR = 1;                     //PCA定时器开始工作
}
void keyscan()
{
        static uint count1=0,count2=0;       
        if(!key1)//亮度增加
        {
                if(++count1>=2000)
                {                       
                        count1=0;
                        if(num>0x00)
                                num--;
                }
        }
        if(!key2)//亮度减弱
        {
                if(++count2>=2000)
                {                       
                        count2=0;
                        if(num<0xcc)//亮度下限
                                num++;
                }
        }
}

void main()
{
        P1M0 = 0x80;                        //P1.7推挽输出
        P1M1 = 0x00;                        //P1.7推挽输出
        P3M0 = 0x00;                        //P3.2高阻
        P3M1 = 0x04;                        //P3.2高阻
        PWM_Init();                                //初始化PWM
        IT0 = 1;            //设置INT0下降沿中断
        EX0 = 1;            //使能INT0中断
        EA = 1;
        num = IapRead(0x0400);
        if(num>0xcc)//占空比不大于80%
        num=0xcc;

        while (1)
        {
                keyscan(); //按键扫描
                CCAP0H=num;//P1.7 PWM输出
        }
}
//中断服务程序
void exint0() interrupt 0 //INT0中断入口
{
    IapErase(0x0400);//扇区擦除
    IapProgram(0x0400,num);//保存num值
}


回复

使用道具 举报

ID:468169 发表于 2019-1-26 17:30 | 显示全部楼层
wulin 发表于 2019-1-26 10:32
硬件连接示意图

已经调试了三个多小时了,没有一点进展,请大师帮我看看哪里有问题?
#include <STC8F2K08S2.h>
#include<intrins.h>       
#include<math.h>                  //计算小数点的头文件
#define uint unsigned int
#define uchar unsigned char

#define WT_30M          0x80
#define WT_24M          0x81
#define WT_20M          0x82
#define WT_12M          0x83
#define WT_6M           0x84
#define WT_3M           0x85
#define WT_2M           0x86
#define WT_1M           0x87
/********************************************************************
                            延时函数
*********************************************************************/
void delay(uchar dat)//延时程序
{
uchar m,n,s;
for(m=dat;m>0;m--)
for(n=20;n>0;n--)
for(s=248;s>0;s--);
}
void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                                //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

char IapRead(int addr)
{
    char dat;

    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 1;                                //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                             //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

void IapProgram(int addr, char dat)
{
    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 2;                                //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                             //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(int addr)
{
    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 3;                                //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}
uchar scale1=10;                                   //定义占空比比例,初始是50%
uchar scale=40;                //定义占空比比例,初始是50%
uchar num2;
uchar Key_num,Key_num1;
uchar n;

bit bdata flag_add_dec=0;        //长按时是加还是减取决于此变量
bit flag=0;        //长按时是加还是减取决于此变量  
bit write=0;
//管脚声明
sbit LED = P1^0;        //灯光控制输出 1
sbit K1= P3^3;          //触摸输入
sbit LED1 = P1^1;    //灯光控制输出2




/*********定时器初始化函数**********/
void init()
{
            IT0=1;//跳变沿出发方式(下降沿)
        EX0=1;//打开INT0的中断允许。       
        TMOD=0x11;           //工作方式 1 定时器0,1
        TH0=0xff;
        TL0=0xe7;                //T0赋初值25us
        TH1=0xff;
        TL1=0xe7;
        EA=1;                   //中断总开关          
        ET0=1;                   //打开中断允许开关
        ET1=1;
   TR0=1;//打开定时器开关
        TR1=1;
}



/****************主函数**********************/
void main()
{
  
          
   
        init();                  //调用初始化函数
        num2 = IapRead(0x0400);
        if(num2>81)
        {
           num2=scale;
        }

          
        while(1)                   //循环
        {         
       

                 
                if(K1==0)        //有触摸信号                                               
                {
                  
                        delay(20);//延时,去抖,除掉干扰信号
                        if(K1==0)        //再次判断有触摸信号
                       
                        {       
                                 
                                while(!K1)//触摸信号不消失就会在此循环中
                                {       
                                        Key_num++;                   //长按计时变量加
                                        if(Key_num>=100)   //检测到是长按(如果没加到100就退出则执行后面的if(Key_num!=0))
                                        {       
                                                Key_num=0;           //清零,执行长按功能
                                                   //在灯开着时才可以调节亮度
                                                         
                                                        while(!K1)                                    //触摸信号一直在,进入循环,进行加减亮度
                                                        {                                                                         

                                                                if(flag_add_dec==0)                  //是加状态

                                                                {       
                                                                  
                                                                       
                                                                  
                                                                        scale++;       
                                                                                                //灯光比例++

                                                                        if(scale>=81)          //达到最亮
                                                                        scale=81;                  //保持最亮
                                   
                                                                  
                                                        }       
                                                               
                                                                else
                                                                {
                                                                  
                                                               
                                                                        scale--;
                                                                           //灯光比例--
                                                                        if(scale<=2)           //达到最暗
                                                                {
                                                                        scale=2;                   //保持最暗
                                                                       
                                                                }       
                                                                       
                                                                }

                                               
                                                           delay(30);
                                                        }
                                                         
                                                        flag_add_dec=!flag_add_dec;         //执行一次长按后,此变量取反(1变0,0变1)
                                                       
                       
                                        }
                               
                                delay(2);                  //此延时是调节长按时间的
                                }
                               
                                if(Key_num!=0)                  //如果不是长按按键
                                {
                               
                                        Key_num=0;                  //清零
                                        TR0=~TR0;                  //定时器取反,就是开关定时器,从而开关灯
                                        if(TR0==0)                  //如果是关灯时,将LED输出置高,关闭输出
                                        LED=1;
                                        LED1=1;
                                }
                            
                        }
                  
               
                }

                num2=scale;
                }

                               
        }
   
          


/******************定时器T0服务函数:脉冲发生函数*******************/
void time0() interrupt 1
{
   
        TH0=0xff;
        TL0=0xe7;                //T0赋初值10us
        n++;                         //每25us  n++
       
        if(n<scale)                 //n<设置比例时,打开灯
        {          
                        LED=0;  LED1=~LED;
        }
        else if(n>=scale)//n大于等于设置比例时 关闭灯
        {         
                LED=1;    LED1=~LED;
        }
        if(n==80)                 //n==40  :25us*40=1ms   1kHZ
        {
                n=0;                 //n=0
        }

}

void time() interrupt 3
{
        TH1=0xff;
        TL1=0xe7;                //T0赋初值12.5us
                 //每25us  n++
       
       
}
/*外部中断0----*/
void Int0()        interrupt 0                //外部中断0的中断函数
{

                                    IapErase(0x0400);  //擦除扇区
                    IapProgram(0x0400,num2);//写入新的地址                           
                           
                       
                         
}

回复

使用道具 举报

ID:468169 发表于 2019-1-26 19:58 来自手机 | 显示全部楼层
nanyexin 发表于 2019-1-26 17:30
已经调试了三个多小时了,没有一点进展,请大师帮我看看哪里有问题?
#include
#include       

现在已经能记忆了,但是只能记忆最亮,不能随意记忆,是不是哪里设置的不对,因为我的是无极调光,不能只记录最亮的。
还有,怎么写入和读取多个数呢?
回复

使用道具 举报

ID:213173 发表于 2019-1-26 21:27 | 显示全部楼层
nanyexin 发表于 2019-1-26 17:30
已经调试了三个多小时了,没有一点进展,请大师帮我看看哪里有问题?
#include
#include       

在没有充分经验的情况下不要试图一下子就能把比较复杂的程序调试通。因该分块调试,都调通后再合在一起统调比较容易发现问题。就你的程序而言,定时器明显设置不合理,微秒级定时要用模式2,节省中断重装时间。而且你设置的是12T模式,T0中断任务耗时30um,T1中断任务耗时8um,CPU响应中断、保存现场也需要时间,可是你设置25us要发生两次中断,也就是说前面中断任务还没有完成,下一次的中断请求又到来,这叫CPU情何以堪?
回复

使用道具 举报

ID:468169 发表于 2019-1-26 23:19 来自手机 | 显示全部楼层
wulin 发表于 2019-1-26 10:32
硬件连接示意图



大师。我调试了很久,终于可以记忆它了,不过就是只能记忆0和1,就是灯亮或不亮。但是我的功能是无级调光,不能只记忆0和1,我要在哪里修改才可以调光亮度在那个级都可以记忆呀?
回复

使用道具 举报

ID:468169 发表于 2019-1-27 16:36 来自手机 | 显示全部楼层
5100103 发表于 2019-1-15 11:57
#include "reg51.h"
#include "intrins.h"


请问STC8F EEPROM中怎么记忆多个字节,要怎地修改?
回复

使用道具 举报

ID:213173 发表于 2019-1-28 13:52 | 显示全部楼层
nanyexin 发表于 2019-1-26 23:19
大师。我调试了很久,终于可以记忆它了,不过就是只能记忆0和1,就是灯亮或不亮。但是我的功能是无级调光 ...

//不完全看明白你的意图,把你的程序改成单键控制掉电记忆PWM调光灯
//去掉定时器PWM调光,用主循环完成PWM调光,去掉delay延时用计数法
//完成消抖、短按、长按、长按连+连-。程序按1T单片机编写,经实际电路验证无误。
//操作平台IAP15W4K58S4,因不涉及其它内部新增功能,程序与STC8F2K08S2通用。
//#include <STC8F2K08S2.h>
#include <STC8.H>
#include<intrins.h>        
//#include<math.h>            //计算小数点的头文件
#define uint unsigned int
#define uchar unsigned char
#define WT_12M   0x83                        //CPU的等待时间
#define key_S 500                                        //宏定义短按(约20ms)
#define key_L 25000                                //宏定义长按(约1s)
#define key_M 24500                                //宏定义长按步进速度
//管脚声明
sbit LED = P1^0;                       //开关指示
sbit K1= P3^3;          //触摸输入
sbit PWM = P1^1;                    //灯光控制输出
//子程序声明
void init();
void keyscan();
void IapIdle();
uchar IapRead(uint addr);
void IapProgram(uint addr, uchar dat);
void IapErase(uint addr);
//变量声明
uchar scale;                        //占空变量
uchar num;                                //计数变量
uchar save;                                //保存的数据变量
bit flag=0;                                //长按标志
bit flag_add_dec=0;        //长按时加减标志
/****************主函数**********************/
void main()
{
        P0M0 = 0x00;//初始化端口弱上拉
        P0M1 = 0x00;
        P1M0 = 0x00;
        P1M1 = 0x00;
        P2M0 = 0x00;
        P2M1 = 0x00;
        P3M0 = 0x00;
        P3M1 = 0x00;
        P4M0 = 0x00;
        P4M1 = 0x00;
        P5M0 = 0x00;
        P5M1 = 0x00;
        P6M0 = 0x00;
        P6M1 = 0x00;
        P7M0 = 0x00;
        P7M1 = 0x00;

        init();      //调用初始化函数

        save=IapRead(0x0400);//读取EEPROM保存的数据

        if(save==0xff)                //如果初次加电EEPROM没有写数据,默认寄存器0xff。
                save = 0x01;        //初始化占空变量与开关变量

        scale = save>>1;        //分解--占空变量
        LED = save & 0x01;//分解--开关变量

        while(1)          //循环
        {         
                keyscan();//按键扫描
                if(LED==0)//PWM控制
                {
                        if(++num==100)
                                num=0;
                        if(num<scale)
                                PWM=0;
                        else PWM=1;
                }
                save =(scale<<1)|LED;//占空变量与开关变量合并为1个字节
        }
}
void keyscan()                                                //按键扫描
{
        static uint count=0;                        //计数变量
        static uchar count1=0;                //1T单片机12倍计数变量
        if(!K1)   
        {  
                if(++count1>=12)
                {//如果使用12T单片机要屏蔽此段语句
                        count1=0;
                        count++;  
                }
                if(count>=key_L)                        //长按
                {
                        if(flag_add_dec==0)        //是加状态
                        {        
                                if(scale<100)                //达到最亮       
                                        scale++;       //灯光比例++
                        }
                        else
                        {
                                if(scale>0)                        //达到最暗  
                                        scale--;       //灯光比例--            
                        }
                        count=key_M;                        //
                        flag=1;                                        //长按标志置1
                }
        }  
        else                                                         //按键松手
        {  
                if(flag==1)                //判断长按松手
                {
                        flag=0;
                        flag_add_dec=~flag_add_dec;//长按加减标志取反
                        count=0;                                //count清0
                }
                else         if(count>key_S && count<key_L)//判断短按松手
                {
                        LED=~LED;               
                        if(LED==1)
                                PWM=1;
                        count=0;                                //count清0
                }
        }   
}
/*********外部中断0初始化函数**********/
void init()
{
        IT0=1;//跳变沿出发方式(下降沿)
        EX0=1;//打开INT0的中断允许。        
        EA=1; //中断总开关         
}
/**********外部中断0************/
void Int0() interrupt 0 //外部中断0的中断函数
{
        IapErase(0x0400);  //擦除扇区
        IapProgram(0x0400, save); //保存占空变量与开关变量合并为1个字节的数据                       
}


void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                                //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

uchar IapRead(uint addr)
{
    uchar dat;

    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 1;                                //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                             //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

void IapProgram(uint addr, uchar dat)
{
    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 2;                                //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                             //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(uint addr)
{
    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 3;                                //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}
回复

使用道具 举报

ID:250700 发表于 2019-1-28 15:14 | 显示全部楼层
nanyexin 发表于 2019-1-15 15:48
嗯,那有STC8F2K08S2的例程吗,最好有EEPROM这方面的……。

;;;这是STC15W系列的 汇编语言编写的 停电保存数据,上电恢复数据 部分的程序
;;;在 STC12C系列 上有使用过,
;;; STC8F2K08S2 可以对比一下几个相关寄存器地址是否一致,一致可以直接使用
;;;用C语言的没有        
        ; / *** *** *** *** *** *** /   CPU         STC15W404AS
         ; / *** *** *** *** *** *** /                 12.000MHz

         WDT_CONTR  EQU  0C1H          ; 看门狗
         ISP_DATA   EQU  0C2H          ; EEPROM 数据寄存器
         ISP_ADDRH  EQU  0C3H          ; 地址寄存器H
         ISP_ADDRL  EQU  0C4H          ; 地址寄存器L
         ISP_CMD    EQU  0C5H          ; 命令寄存器
         ISP_TRIG   EQU  0C6H          ; 触发寄存器
         ISP_CONTR  EQU  0C7H          ; ( 等待时间 <  6M   4 )
         ISPRH      EQU   78H          ; ( 等待时间 < 12M   3 )
         ISPRL      EQU   79H          ; ( 等待时间 < 20M   2 )  
         ISPWH      EQU   7AH          ; ( 等待时间 < 12M   3 )
         ISPWL      EQU   7BH          ; ( 等待时间 < 20M   2 )  

         ; / *** *** *** *** *** *** /   通用数据存储器    RAM  256 字节
         ; / *** *** *** *** *** *** /   定义内部RAM L     EEPROM    5K

         RIV_R0  EQU     1CH
         RIV_R1  EQU     1DH
         
         PTJSA0  EQU     50H           ; 停电保存数据
         PTJSA1  EQU     51H           ; 可以根据需要字节
         ; -------------------------------

                  
         ; / *** *** *** *** *** *** /
         ;   ISP - 78H 79H 7AH 7BH
         
         PJSQS0  EQU     7EH      
         PJSQS1  EQU     7FH


         ; / *** *** *** *** *** *** /   通用      标志位
         ; / *** *** *** *** *** *** /   20H --- 2FH

         PLVD_BZ BIT     26H           ; 停电处理标志
         PLVD_B2 BIT     27H
         
         ; / *** *** *** *** *** *** /   程序入口
         ; / *** *** *** *** *** *** /

         ORG     0000H            
L0000:   LJMP    MIN000                ; 初始化 主程序 START


         ORG     0033H            
L0033:   LJMP    LVD000                ; LVD  低电压 ( LVDF )
         ; RETI
        
         ; / *** *** *** *** *** *** /   ELVDI (低电压) 中断
         ; / *** *** *** *** *** *** /   
         ; 5V-3.7V   5.50V - 3.30V         4.06V - 1.32V

LVD000:  PUSH    PSW                   ; 电流检测
         PUSH    ACC
         SETB    RS0                   ; 1 区  R1 R3
         CLR     RS1
         ANL     PCON, #11011111B      ; 清 LVDF 位
         MOV     A, PCON
         JNB     ACC.5, LVD008         ; LVDF
         CLR     EA            
         CLR     TR1
         SETB    PLVD_BZ           
         JNB     PLVD_B2, LVD008
         CLR     PLVD_B2
LVD003:  MOV     A, PJSQS0             ; 数据
         MOV     B, #08H
         MUL     AB
         MOV     ISPWL, A              ; 0000H - 01FFH
         MOV     ISPWH, B
         MOV     R1, #PTJSA0           ; 断电保存数据写入
         MOV     R3, #08H
LVD006:  MOV     A, @R1
         LCALL   ISP010                ; 字节写
         INC     ISPWL
         INC     R1
         DJNZ    R3, LVD006
         INC     PJSQS0
LVD007:  ANL     PCON, #11011111B      ;  清 LVDF 位
         MOV     A, PCON
         JB      ACC.5, LVD007              
LVD008:  CLR     PLVD_BZ         
         SETB    EA
         POP     ACC
         POP     PSW
         RETI
         
         ; / *** *** *** *** *** *** /   初始化 主程序A
         ; / *** *** *** *** *** *** /

MIN000:  MOV     SP, #0B0H             ; 初始化 主程序 SP = B0H - FFH  

         MOV     IE, #11000000B        ; IE.6 ( EPCA_LVD 中断 )         

         
MIN002:  LCALL   MIM000                ; 初始化


MIN010:  NOP                           ; 主程序
         NOP
         MOV     WDT_CONTR, #3EH       ; 看门狗 初始化 12M ( 1.0485 S )
         NOP                           ; 喂狗 同
         NOP
         ; 主控程序在这里加入
         
MIN050:  JMP     MIN010
         RET
         

         ; / *** *** *** *** *** *** /   读写 STC15W404AS  EEPROM  
         ; / *** *** *** *** *** *** /   1 字节读

ISP000:  MOV     ISP_CONTR, #83H       ; 打开 IAP 功能 设置等待时间
         MOV     ISP_CMD, #01H         ; 送字节读命令
         MOV     ISP_ADDRH, ISPRH      ; 送地址高字节
         MOV     ISP_ADDRL, ISPRL      ; 送地址低字节
         CLR     EA                    ; 关中断
         MOV     ISP_TRIG, #5AH        ; 起动 ISP/IAP 触发寄存器
         MOV     ISP_TRIG, #0A5H
         NOP
         MOV     A, ISP_DATA           ; 将读出的数据送往Acc
         JB      PLVD_BZ, $+5
         SETB    EA
         LCALL   ISP030                ; 关闭 IAP 功能
         RET

         ; / *** *** *** *** *** *** /   1 字节编程

ISP010:  MOV     ISP_CONTR, #83H       ; 打开 IAP 功能 设置等待时间
         MOV     ISP_CMD, #02H         ; 送字节编程命令
         MOV     ISP_ADDRH, ISPWH      ; 送地址高字节
         MOV     ISP_ADDRL, ISPWL      ; 送地址低字节
         MOV     ISP_DATA, A           ; 数据进ISP_DATA
         CLR     EA                    ; 关中断
         MOV     ISP_TRIG, #5AH        ; 起动 ISP/IAP 触发寄存器
         MOV     ISP_TRIG, #0A5H
         NOP
         JB      PLVD_BZ, $+5
         SETB    EA
         LCALL   ISP030                ; 关闭 IAP 功能
         RET

         ; / *** *** *** *** *** *** /   擦除扇区

ISP020:  MOV     ISP_CONTR, #83H       ; 打开 IAP 功能 设置等待时间
         MOV     ISP_CMD, #03H         ; 送擦除扇区命令
         MOV     ISP_ADDRH, ISPWH      ; 送地址高字节
         MOV     ISP_ADDRL, ISPWL      ; 送地址低字节
         CLR     EA                    ; 关中断
         MOV     ISP_TRIG, #5AH        ; 起动 ISP/IAP 触发寄存器
         MOV     ISP_TRIG, #0A5H
         NOP
         JB      PLVD_BZ, $+5
         SETB    EA
         LCALL   ISP030                ; 关闭 IAP 功能
         RET

         ; / *** *** *** *** *** *** /   关闭 IAP 功能

ISP030:  MOV     ISP_CONTR, #00H
         MOV     ISP_CMD, #00H
         MOV     ISP_TRIG, #00H
         MOV     ISP_ADDRH, #0FFH      ; 指向非EEPROM区
         MOV     ISP_ADDRL, #0FFH
         RET
         

         RET

         ; / *** *** *** *** *** *** /   初始化   STC15W404AS
         ; / *** *** *** *** *** *** /   读回DAT         ***
      
MIM000:  MOV     R4, #20               ; 50000 uS * 20
MIM001:  NOP
         NOP
         MOV     WDT_CONTR, #3CH       ; 看门狗 初始化 12M ( 1.0485 S )
         NOP     
         NOP                           ; 喂狗 同
         DJNZ    R4, MIM001     
         CLR     PLVD_BZ               ;
         CLR     PLVD_B2
         MOV     RIV_R1, #50           ; 30 S
         LCALL   MIM050                ; 机器编号
         NOP
MIM010:  MOV     PJSQS0, #40H          ; 读回     编码
MIM013:  DEC     PJSQS0                ; 0000H - 01FFH
         MOV     A, PJSQS0
         CJNE    A, #0FFH, MIM015
         RET
MIM015:  MOV     B, #08H               ; 计算地址
         MUL     AB
         MOV     ISPRL, A              ; 0000H - 01FFH
         MOV     ISPRH, B
         LCALL   ISP000                ; 字节读
         CJNE    A, #0FFH, MIM016
         JMP     MIM013
MIM016:  MOV     R0, #PTJSA0     
         MOV     R3, #08H
MIM018:  LCALL   ISP000                ; 字节读
         MOV     @R0, A                ; 写 RAM
         INC     ISPRL
         INC     R0
         DJNZ    R3, MIM018
         INC     PJSQS0

MIM050:  RET

         ; / *** *** *** *** *** *** /   结束

         END
回复

使用道具 举报

ID:468169 发表于 2019-1-31 22:19 来自手机 | 显示全部楼层
wulin 发表于 2019-1-28 13:52
//不完全看明白你的意图,把你的程序改成单键控制掉电记忆PWM调光灯
//去掉定时器PWM调光,用主循环完成 ...

STC8F2K08S2不是没有PWM(PCA)寄存器吗?
Screenshot_20190131_222213_com.UCMobile.jpg
回复

使用道具 举报

ID:213173 发表于 2019-2-1 07:33 | 显示全部楼层
nanyexin 发表于 2019-1-31 22:19
STC8F2K08S2不是没有PWM(PCA)寄存器吗?

STC8F2K08S2是没有硬件PWM(PCA)寄存器,在这个程序中PWM调光是在主循环中由软件处理。
回复

使用道具 举报

ID:468169 发表于 2020-9-13 11:52 来自手机 | 显示全部楼层
wulin 发表于 2019-1-23 16:53
掉电记忆是需要外部硬件支持的,否则单片机没有电源怎么工作?如下图,C2值远大于C1。把写EEPROM的程序放 ...

大师,现在我要把这个程式改为两路iO口输出,具体工作为:上电一路IO口输出高电平另一个不输出,,断电再上电输出另一路高电平,怎么实现?
回复

使用道具 举报

ID:140489 发表于 2020-9-29 11:08 | 显示全部楼层
给你一段我的代码,调光完成,松手后存储pwm值
/*----------------------------
感应扫描
----------------------------*/
void keyscan()
{
        if(PHO==0)        //没有感应 要及时清零一些标志
        {

                ucKeyLock1=0;   //感应自锁标志清零
                uiKeyTimeCnt1=0;//感应去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。
                if(flag2)                //长按松手后,存储pwm值
                {
                        IapEraseSector(0x0001); // 清除EEPROM
                        IapProgramByte(0x0001, pwm_val); // 将pwm值据写入EEPROM
                        flag2 = 0;                           //pwm值写入EEPROM后,存储标志清零
                }

        }
        else if(ucKeyLock1==0)//有感应,且是第一次感应
        {       
                IR = 1;                          //关闭红外发射
                ++uiKeyTimeCnt1;  //延时计数器
                if(uiKeyTimeCnt1>const_key_time1)//短按
                {
                        uiKeyTimeCnt1=0;
                        ucKeyLock1=1; //自锁按键置位,避免一直触发
                        flag1 = !flag1;
                }               
        }
        else if(uiKeyTimeCnt1<const_key_time2)//长按
        {
                ++uiKeyTimeCnt1;  //延时计数器
                if(uiKeyTimeCnt1==const_key_time2)
                {
                        uiKeyTimeCnt1=198;//此处调节调光速度,值越大,调光越快
                        flag2=1;                  //存储标志置1
                        if(flag == 1)
                        {
                               
                                if(pwm_val < 255)
                               
                                {
                                  pwm_val++;        //亮度变暗
                               
                                  if(pwm_val==255)//此处赋值255可以调灭
                                  {
                                                  delay(100);
                                                  flag = 0;
                                  }
                                }
                        }
                       
                        if( flag ==0 )
                        {
                                if(pwm_val > 0)
                                {
                                  pwm_val--;        //亮度变亮
                               
                                  if(pwm_val==0)//
                                  {
                                                delay(100);
                                                flag = 1;
                                  }
                                }
                        }
                }               
        }                                               
}
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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